conditionx
v1.0.0
Published
A lightweight, flexible condition engine for JavaScript and Node.js. Supports async rules, logical operators (AND, OR, NOT), object-based conditions, RegExp checks, and dynamic rule execution without if/else or switch statements.
Maintainers
Readme
🚀 O‘rnatish
npm orqali:
npm install conditionxYoki Yarn orqali:
yarn add conditionxYoki pnpm orqali:
pnpm add conditionx📦 Import qilish
import { run, AND, OR, NOT } from "conditionx";📌 O‘rnatmasdan turib (CDN orqali) import qilish
conditionx ni npm’dan o‘rnatmasdan ham ishlatishingiz mumkin. Buning uchun uni unpkg yoki jsDelivr orqali to‘g‘ridan-to‘g‘ri browserga yuklaysiz.
1️⃣ jsDelivr orqali import
<script type="module">
import { run, AND, OR, NOT } from "https://cdn.jsdelivr.net/npm/conditionx/+esm";
const ctx = { age: 22 };
run(ctx, { age: 22 }, () => console.log("Mos keldi!"));
</script>2️⃣ unpkg orqali import
<script type="module">
import { run, AND, OR, NOT } from "https://unpkg.com/conditionx?module";
run({ value: 10 }, { value: 10 }, () => console.log("OK"));
</script>3️⃣ esm.run orqali import (eng barqaror variant)
<script type="module">
import { run, AND, OR, NOT } from "https://esm.run/conditionx";
run({ x: 5 }, { x: 5 }, () => console.log("Ishladi!"));
</script>1-dars: Rule Engine nima?
Rule Engine — bu shartlarga asoslangan qaror qabul qilish tizimi. Ya’ni, kodga qator-qator if ... else if ... else yozish o‘rniga, shartlar (rule’lar) va ularning natijalarini tartibli, boshqarilishi oson, modul ko‘rinishida yozishga imkon beradigan mexanizm.
Oddiy qilib aytganda:
Rule Engine = “Shart → Amaliyot” juftliklarini boshqaradigan tizim.
🧠 Nega bunday tizimga ehtiyoj bor?
Chunki loyihalar murakkablashgani sari shartlar soni ham o‘sadi.
Oddiy if-else:
if (user.age > 18 && user.isActive) { ... }
else if (user.role === "admin") { ... }
else if (isHoliday() && !user.blocked) { ... }10–20 ta shartdan keyin kod:
- o‘qilmaydi
- test qilish qiyinlashadi
- kengaytirish mushkillashadi
- qo‘shilgan bitta shart boshqasini buzishi mumkin
Rule Engine esa buni tizimli qiladi:
run(
{ age: 25, active: true, role: "admin", isHoliday: true, blocked: false },
AND("age > 18", "active == true"), () => console.log("Kattalar uchun xabar"),
{ role: "admin" }, () => console.log("Adminlar uchun xabar"),
AND("isHoliday == true", "blocked == false"), () => console.log("Bugungi kun bayram!")
);Odatiy JavaScript bilan yozilganda:
const ctx = {
age: 25,
active: true,
role: "admin",
isHoliday: true,
blocked: false
};
if (ctx.age > 18 && ctx.active === true) {
console.log("Kattalar uchun xabar");
} else if (ctx.role === "admin") {
console.log("Adminlar uchun xabar");
} else if (ctx.isHoliday === true && ctx.blocked === false) {
console.log("Bugungi kun bayram!");
}Chiqish:
Kattalar uchun xabarShartlar:
- bo‘laklarga bo‘lingan
- oson tahrirlanadi
- uchinchi shaxs ham osongina tushunadi
- qayta ishlatiladi
⚙️ Rule Engine qanday ishlaydi?
Uning vazifasi oddiy:
- Shartni baholaydi
- U mos bo‘lsa — action (amal) bajariladi
- Mos bo‘lmasa — keyingi shartga o‘tadi
- To‘g‘ri shart topilganda — to‘xtaydi
conditionx Rule Engine’da bu run() orqali bajariladi — har bir shart ketma-ket tekshiriladi.
📌 Rule Engine qachon kerak bo‘ladi?
- Tooltiplarni boshqarishda
- Chatbot javoblarida
- Forma validatsiyada
- Eventlarni boshqarishda
- Filtrlash va match qilish tizimlarida
- Mikro-logika yoki mikro-til (DSL) yaratishda
- Bir nechta asinxron shartlarni tartib bilan tekshirish kerak bo‘lganda
🧩 Asosiy g‘oya
Rule Engine shuni qiladi:
✔ Shartlar → Modullar ✔ Qarorlar → Tizimli ✔ Kod → Toza va muvozanatli ✔ Kengaytirish → Oson ✔ Testlash → Soddalashadi
2-dars: Nima uchun Rule Engine kerak?
Rule Engine kerak bo‘lishining eng asosiy sababi — logikani tartibga solish, boshqarishni soddalashtirish va kodni shishib ketishdan saqlash. Keling, buni real muammolar orqali tushuntiramiz.
🧨 1. If-else lar soni ko‘payganda kod portlaydi
Loyiha kattalashgan sari shartlar soni oshadi:
if (isNewUser && !isBlocked && age > 18) { ... }
else if (user.role === "admin" && isNight() && !maintenance) { ... }
else if (...) { ... }10–20 ta shartdan keyin:
- kod o‘qilmaydi
- kimdir yangi shart qo‘shsa, boshqasi buziladi
- bir shart boshqasiga ta’sir qiladi
- debugging juda ko‘p vaqt oladi
Rule Engine esa shartlarni tarqoq if'lar emas, mustaqil qoidalar sifatida saqlashni taklif qiladi.
🧩 2. Shartlar modul bo‘lishi kerak
Rule Engine shartni funksiya, object, regex, AND/OR/NOT bilan modul sifatida yozish imkonini beradi.
Masalan:
const isAdmin = { role: "admin" };
const isAdult = ctx => ctx.age >= 18;
const isActive = ctx => ctx.active === true;
const showAdmin = () => console.log("Bu foydalanuvchi admin!");
const showAdult = () => console.log("Foydalanuvchi kattalar!");
const showActive = () => console.log("Foydalanuvchi aktiv!");
run(
{ age: 25, active: true, role: "admin" },
isAdmin, showAdmin,
isAdult, showAdult,
isActive, showActive
);Odatiy JavaScript bilan yozilganda:
const user = { age: 25, active: true, role: "admin" };
const isAdmin = user.role === "admin";
const isAdult = user.age >= 18;
const isActive = user.active === true;
const showAdmin = () => console.log("Bu foydalanuvchi admin!");
const showAdult = () => console.log("Foydalanuvchi kattalar!");
const showActive = () => console.log("Foydalanuvchi aktiv!");
if (isAdmin) {
showAdmin();
} else if (isAdult) {
showAdult();
} else if (isActive) {
showActive();
}Chiqish:
Bu foydalanuvchi admin!Bu modullar:
- qayta ishlatiladi
- alohida test qilinadi
- bir-biriga bog‘lanmaydi
If-else bilan buni qilish qiyin.
⚡ 3. Shartlar kombinatsiyasi sodda bo‘ladi
AND, OR, NOT — mantiqiy tuzilmalarni juda toza yozishga imkon beradi.
run(
{
age: 25,
active: true,
role: "admin",
blocked: false,
deleted: false,
banned: false,
suspended: false,
isHoliday: true,
hasPromo: false,
loginCount: 10
},
// 1) (Katta YOKI aktiv) VA (Bayram YOKI promo)
AND(
OR(ctx => ctx.age >= 18, ctx => ctx.active === true),
OR(ctx => ctx.isHoliday === true, ctx => ctx.hasPromo === true)
),
() => console.log("Umumiy ruxsat berildi."),
// 2) Admin VA bloklanmagan
AND(
ctx => ctx.role === "admin",
ctx => !ctx.blocked
),
() => console.log("Admin uchun maxsus ruxsat."),
// 3) Superadmin VA bloklanmagan VA o‘chirilmagan
AND(
ctx => ctx.role === "superadmin",
ctx => !ctx.blocked,
ctx => !ctx.deleted
),
() => console.log("Superadmin uchun maxsus ruxsat."),
// 4) Bloklanmagan VA guest emas
AND(
ctx => !ctx.blocked,
ctx => ctx.role !== "guest"
),
() => console.log("Oddiy foydalanuvchi uchun ruxsat."),
// 5) Suspended, lekin aktiv
AND(
ctx => ctx.suspended === true,
ctx => ctx.active === true
),
() => console.log("Aktiv, lekin suspended — chalkash holat.")
);Odatiy JavaScript bilan yozilganda:
function checkUser(user) {
if (
(user.age >= 18 && user.active === true) ||
(user.role === "admin" && !user.blocked) ||
(user.role === "superadmin" && !user.blocked && !user.deleted) ||
(!user.banned && (user.isHoliday || user.hasPromo)) ||
(user.active === true && user.loginCount > 5 && !user.suspended)
) {
if (user.role === "admin" && user.age < 18 && !user.active) {
console.log("Admin bo‘lsa ham, yosh yoki aktivlik bo‘yicha muammo.");
} else {
if (!user.blocked && user.role !== "guest") {
if (user.deleted) {
console.log("Foydalanuvchi o‘chirilgan.");
} else {
if ((user.role === "user" && user.age > 25) || user.role === "superadmin") {
console.log("Maxsus ruxsat berildi.");
} else if (user.suspended && user.active) {
console.log("O‘chirib qo‘yilgan, lekin faol holatda — chalkash holat.");
} else {
console.log("Umumiy ruxsat berildi.");
}
}
} else {
console.log("Bloklangan yoki guest.");
}
}
} else {
console.log("Hech qaysi shartga tushmadi.");
}
}
checkUser({
age: 25,
active: true,
role: "admin",
blocked: false,
deleted: false,
banned: false,
suspended: false,
isHoliday: true,
hasPromo: false,
loginCount: 10
});Chiqish:
Umumiy ruxsat berildi.If bilan bunda qo‘shma, chuqur, chalkash kod paydo bo‘ladi.
🔁 4. Qarorlar ketma-ketligi boshqariladi
Rule Engine’da:
- birinchi mos kelgan rule ishlaydi
- action bajariladi
- kerak bo‘lsa
next,stop, yoki context modifikatsiya qilinadi
Bu juda muhim:
✔ Tooltip system ✔ Chatbot javoblari ✔ Event handlerlar ✔ Validatsiya
hammasi qaror zanjiri asosida ishlaydi.
⚙️ 5. Kengaytirish juda oson
Agar ertaga yangi shart qo‘shilsa:
If-else: ❌ eski kodni ochish, o‘zgartirish, buzish ehtimoli
Rule Engine: ✔ yangi qoidani bitta qatorga qo‘shish kifoya
run(ctx,
isNewUser, showWelcome,
isAdmin, showAdminPanel,
isBlocked, showBanMessage,
isPremium, showPremiumBadge // 🔥 yangi qoida
);Eski kodga tegmaysan → xatolik xavfi kamayadi.
🔮 6. Katta loyihalarda professional yechim
Professional frontend/backendlarda:
- notification system
- rule-based routing
- recommendation engine
- form validation
- chatbot NLP fallback logikasi
hammasi rule engine yoki shunga o‘xshash tizimlardan foydalanadi.
conditionx engine — aynan shu professional yondashuvning yengil, moslashuvchan versiyasi.
📌 Xulosa
Rule Engine kerak, chunki:
✔ Kodni tozalaydi ✔ Murakkab shartlarni soddalashtiradi ✔ Modullik yaratadi ✔ Ko‘p shartli loyihalarda boshqaruvni osonlashtiradi ✔ Kengaytirishga mos ✔ Real ilovalarda juda kuchli mexanizm
3-dars: Asosiy tushunchalar
Rule Engine bilan ishlash uchun bir nechta foundational — ya’ni, asosiy poydevor tushunchalarni bilib olish kerak. Bu tushunchalar conditionx’ning ichki tuzilishini ham, undan qanday foydalanishni ham to‘liq ochib beradi.
🧩 1. Rule (qoida)
Rule — bu shart + amaliyot juftligi.
Shakli:
(shart, action)run() ana shunday juftliklarni ketma-ket tekshiradi.
Misol:
run(ctx,
isAdult, showAdultTooltip,
isAdmin, showAdminTooltip,
isBlocked, showBanMessage
);Rule Engine’da har bir qoidaning vazifasi bir xil:
Agar shart bajarilsa → action bajariladi.
🧠 2. Condition (shart)
Shart — bu rule’ning birinchi qismi va u true yoki false qaytarishi kerak.
conditionx engine quyidagi turlardagi shartlarni qo‘llab-quvvatlaydi:
✔ Funktsiya shartlar
const isAdult = ctx => ctx.age >= 18;✔ Asinxron shartlar
const isPremium = async ctx => {
return await fetchStatus(ctx.id) === "premium";
};✔ Regex
/input/i✔ Object matching
{ role: "admin", active: true }✔ AND / OR / NOT
AND(isAdult, isActive)✔ Massiv ko‘rinishida nested qoidalar
[isAdult, showAdult]Bularning hammasi avtomatik qayta ishlanadi.
⚙️ 3. Action (amal)
Shart bajarilganda ishlaydigan qism.
Action funksiyada:
- qaytgan qiymat bilan oqim boshqariladi
- context o‘zgartirilishi mumkin
Action’ning ruxsat etilgan natijalari:
✔ undefined yoki hech narsa qaytarmaslik
Rule tugaganini bildiradi.
✔ "stop"
if (result === "stop") return true;→ Rule chain shu yerda tugaydi.
✔ "next"
if (result === "next") continue;→ Shart bajarilgan bo‘lsa ham keyingi rule’ni tekshiradi.
✔ Object qaytarish
Bu qiymatlar contextga merge qilinadi.
return { step: "valid" }📦 4. Context (ctx)
ctx — bu qoidalar bajarilayotgan holatlar jamlanmasi.
U:
- shartlar tomonidan o‘qiladi
- actionlar tomonidan yangilanadi
- keyingi qoida uchun ham ishlatiladi
Context umumiy xotira sifatida xizmat qiladi.
Misol:
run({ input: "hello" }, ...rules)Action contextni o‘zgartirsa:
return { detected: true };engine uni birlashtiradi:
ctx = { input: "hello", detected: true }🔧 5. Logical Operators — AND, OR, NOT
Bu operatorlar conditionx engine’ning eng muhim qurolidir.
✔ AND(a, b, c...)
Barchasi true bo‘lsa → true
✔ OR(a, b, c...)
Hech bo‘lmaganda bittasi true bo‘lsa → true
✔ NOT(x)
x true bo‘lsa → false x false bo‘lsa → true
Ular shartlarni modulli qiladi.
🔁 6. Rule Flow (Qoidalar ketma-ketligi)
run() shart-action juftliklarini navbatma-navbat tekshiradi:
- Shartni baholaydi
- True → action bajariladi
- Action oqimga ta’sir qiladi
- Agar tugamas ekan → keyingi rulega o‘tadi
Bu juda muhim: birinchi mos kelgan qoida — g‘olib qoida.
🎯 Xulosa
Asosiy tushunchalar shular:
✔ Rule = shart + action ✔ Condition = turli ko‘rinishdagi boolean tekshiruv ✔ Action = natija / oqim boshqaruvi / context o‘zgarishi ✔ Context = umumiy holat ✔ AND / OR / NOT = mantiqiy konstruktorlar ✔ run() = butun jarayonning "dvigateli"
4-dars: Shartlarni yozish usullari
Rule Engine’da shartlar — eng asosiy qurilish materiali. Aynan shartlar yordamida tizimga “qachon nima qilish” ni o‘rgatamiz. Bu darsda engine qo‘llab-quvvatlaydigan barcha shart yozish usullarini o‘rganamiz.
🧠 1. Oddiy boolean shartlar
Agar shart oddiy qiymat bo‘lsa, engine uni boolean’ga aylantiradi.
run(
{},
false, () => console.log("To'g'ri"),
true, () => console.log("Xato"),
);Odatiy JavaScript bilan yozilganda:
if (false) {
console.log("To'g'ri");
} else if (true) {
console.log("Xato");
}Chiqish:
Xato✔ True → action ishlaydi ✖ False → keyingi qoidaga o‘tadi
Oddiy bo‘lsa ham ba’zi holatlarda qulay.
🧪 2. Funktsiya shaklidagi shart
Bu eng ko‘p ishlatiladigan turi.
run({ age: 18 },
ctx => ctx.age == 18, () => console.log("Teng"),
ctx => ctx.age >= 18, () => console.log("Katta"),
true, () => console.log("Kichik")
);Odatiy JavaScript bilan:
const ctx = { age: 18 };
if (ctx.age === 18) {
console.log("Teng");
} else if (ctx.age >= 18) {
console.log("Katta");
} else {
console.log("Kichik");
}Chiqish:
TengFunktsiya ctx oladi va true/false qaytaradi.
⚡ 3. Asinxron shartlar
Shart async bo‘lishi ham mumkin! Engine uni kutib turadi.
const db = {
async checkUser(id) {
console.log("DB tekshirilmoqda...");
await new Promise(res => setTimeout(res, 300));
return id === 1 ? "premium" : "free";
}
};
const hasPremium = async ctx => {
const status = await db.checkUser(ctx.id);
return status === "premium";
};
run({ id: 1 },
hasPremium, (ctx) => console.log("🎉 PREMIUM badge berildi:", ctx.id)
);Odatiy JavaScript bilan:
const db = {
async checkUser(id) {
console.log("DB tekshirilmoqda...");
await new Promise(res => setTimeout(res, 300));
return id === 1 ? "premium" : "free";
}
};
const ctx = { id: 1 };
(async () => {
const status = await db.checkUser(ctx.id);
if (status === "premium") {
console.log("🎉 PREMIUM badge berildi:", ctx.id)
} else {
console.log("❌ Premium emas:", ctx.id);
}
})();Chiqish:
DB tekshirilmoqda...
� PREMIUM badge berildi: 1Bu juda kuchli, chunki serverga so‘rov, API, DB ham shart bo‘lishi mumkin.
🔥 4. Regex shartlar
Agar shart RegExp bo‘lsa, engine uni ctx.inputga qo‘llaydi.
run({ input: "hello123" },
/^[a-z]+$/i, () => console.log("✨ Faqat harflardan iborat!"),
/\d+$/, () => console.log("🔢 Oxirida raqamlar bor!")
);Odatiy JavaScript bilan:
const input = "hello123";
if (/^[a-z]+$/i.test(input)) {
console.log("✨ Faqat harflardan iborat!");
} else if (/\d+$/.test(input)) {
console.log("🔢 Oxirida raqamlar bor!");
}Chiqish:
� Oxirida raqamlar bor!🧩 5. Object matching
Agar shart obyekt bo‘lsa, engine uni ctx bilan solishtiradi.
run(
{ role: "admin", active: true },
// ADMIN
{ role: "admin" },
() => console.log("⚡ Admin panel"),
// MODERATOR
{ role: "moderator" },
() => console.log("🛡 Moderator panel"),
// USER
{ role: "user" },
() => console.log("👤 User panel"),
// GUEST
{ role: "guest" },
() => console.log("🌐 Guest page")
);Odatiy JavaScript bilan:
const ctx = { role: "admin", active: true };
if (ctx.role === "admin") {
console.log("⚡ Admin panel");
} else if (ctx.role === "moderator") {
console.log("🛡 Moderator panel");
} else if (ctx.role === "user") {
console.log("👤 User panel");
} else if (ctx.role === "guest") {
console.log("🌐 Guest page");
} else {
console.log("🚫 Ruxsat yo‘q");
}Chiqish:
⚡ Admin panel🧱 6. Mantiqiy operatorlar: AND, OR, NOT
Bu engine’ning eng kuchli syntax’i.
✔ AND
AND(isAdult, isVerified)Ikkalasi ham true bo‘lsa → true
✔ OR
OR(isAdmin, isModerator)Bittasi true bo‘lsa → true
✔ NOT
NOT(isBanned)🔁 7. Massiv shaklidagi shartlar (nested rules)
Agar shart massiv bo‘lsa, engine u massivni ichki run() sifatida ishlatadi.
run(ctx,
[isAdult, showAdult],
next
);Bu mini-rule yaratish imkonini beradi.
🧠 8. Shartlarni aralashtirib yozish
Mantiqiy operatorlar + obyekt + regex hammasi aralashtirilishi mumkin.
AND(
{ role: "user" },
OR(
ctx => ctx.age > 21,
/^[A-Z]{2}\d+$/ // input format
),
NOT(ctx => ctx.banned)
)Engine bularni mukammal boshqaradi.
💡 9. Shart hasilini boshqarish
Shartlar faqat true/false, lekin ularning ichida istalgan murakkab hisoblash bo‘lishi mumkin.
Misol:
const enoughBalance = ctx => {
ctx.required = 100; // ctx’ni ichida o‘zgartirsa ham bo‘ladi
return ctx.balance >= 100;
};Bu bo‘yicha engine cheklov qo‘ymaydi.
🎯 Xulosa
Rule Engine’da shart yozishning asosiy 9 usuli:
- Oddiy boolean
- Funktsiya
- Asinxron funktsiya
- Regex
- Object matching
- AND
- OR
- NOT
- Massiv (ichki rule)
Shartlar moslashuvchan, kombinatsiyali va engine ularni to‘liq boshqaradi.
5-dars: Funktsiya asosidagi shartlar
Funktsiya asosidagi shartlar — Rule Engine’dagi eng kuchli, eng ko‘p ishlatiladigan va eng moslashuvchan shart turi. Barcha professional qoida tizimlari funksion shartlarga tayangan bo‘ladi.
Bu darsda:
- funktsiya shartlar nima
- qanday ishlaydi
- yaxshi amaliyotlar
- advanced texnikalar hammasini ko‘rib chiqamiz.
🎯 1. Funktsiya sharti nima?
Bu oddiy funksiyadir:
const condition = ctx => {
return ctx.age >= 18;
};Engine buni chaqiradi va qaytgan qiymatni true yoki false sifatida baholaydi.
⚙️ 2. Funktsiya faqat 1 ta argument oladi: ctx
Barcha shartlar bir xil imzoga ega:
(ctx) => true/falsectx — kontekst obyekti bo‘lib, unda:
- foydalanuvchi ma’lumotlari
- input
- holat
- oraliq natijalar
- konfiguratsiyalar
bo‘lishi mumkin.
Bu shartni universal qiladi.
🔥 3. Minimal misol
const isAdmin = { role: "admin" };
const isAdult = ctx => ctx.age >= 18;
const isActive = ctx => ctx.active === true;
const showAdmin = () => console.log("Bu foydalanuvchi admin!");
const showAdult = () => console.log("Foydalanuvchi kattalar!");
const showActive = () => console.log("Foydalanuvchi aktiv!");
run(
{ age: 25, active: true, role: "admin" },
isAdmin, showAdmin,
isAdult, showAdult,
isActive, showActive
);Odatiy JavaScript bilan yozilganda:
const user = { age: 25, active: true, role: "admin" };
const isAdmin = user.role === "admin";
const isAdult = user.age >= 18;
const isActive = user.active === true;
const showAdmin = () => console.log("Bu foydalanuvchi admin!");
const showAdult = () => console.log("Foydalanuvchi kattalar!");
const showActive = () => console.log("Foydalanuvchi aktiv!");
if (isAdmin) {
showAdmin();
} else if (isAdult) {
showAdult();
} else if (isActive) {
showActive();
}Chiqish:
Bu foydalanuvchi admin!⚡ 4. Parametrli shart yaratish (factory pattern)
Bu juda foydali texnika.
const minAge = (n) => (ctx) => ctx.age >= n;
run(ctx,
minAge(21), allowAlcohol
);Bu shartlarni qayta ishlatish uchun ideal.
🧠 5. Bir nechta shartni bitta funksiyaga jamlash
Masalan, foydalanuvchi tekshiruvi:
const canAccess = ctx => {
return ctx.active && ctx.role === "member" && ctx.balance > 0;
};Keyin:
run(ctx,
canAccess, openDashboard
);🔁 6. Funktsiya ichida ctx’ni o‘zgartirish mumkin
const prepare = ctx => {
ctx.fullName = ctx.first + " " + ctx.last;
return true;
};Engine ruxsat beradi, chunki shartlar faqat boolean emas, balki logic bo‘lim ham bo‘lishi mumkin.
🔍 7. Funktsiya ichida murakkab hisoblash
Masalan, u uzun textni tekshirishi mumkin:
const longMessage = ctx => ctx.input.length > 200;Yoki algoritm ishlatadi:
const isPerfectSquare = ctx => {
const x = Math.sqrt(ctx.number);
return x === Math.floor(x);
};Engine buni ham qo‘llab-quvvatlaydi.
🌐 8. Asinxron funksiyalar ham shart bo‘la oladi
Bu engine’ning juda katta afzalligi.
const hasPremium = async ctx => {
const status = await api.userStatus(ctx.id);
return status === "premium";
};
run(ctx,
hasPremium, showPremiumBadge
);Engine await qilib kutadi — hech narsa buzilmaydi.
🧩 9. Funktsiyalarni AND/OR bilan birlashtirish
run(ctx,
AND(
ctx => ctx.active,
ctx => ctx.age > 18,
ctx => ctx.country === "UZ"
), giveAccess
);Bu juda oqilona sintaksis yaratadi.
🏗 10. Yaxshi amaliyotlar (best practices)
✔ Shart funksiyalarni kichik qil Har bir shart 1 vazifa bajarsin.
✔ Nomlash aniq bo‘lsin
isAdmin, isVerified, hasBalance kabi.
✔ Qayta ishlatiladigan shartlar yarat Parametrli shartlar (factory) juda kuchli.
✔ Shart ichida katta logika bo‘lmasin Agar juda murakkab bo‘lsa → alohida modulga ajrat.
✔ async shartlarni faqat kerak bo‘lganda ishlat Tezlikni saqlash uchun.
🧵 11. Real loyihadagi pattern
Masalan, tooltip qoidalari:
const hasSelectedText = ctx => ctx.selection && ctx.selection.length > 0;
const notInsideLink = ctx => !ctx.isInsideLink;
const isTextNode = ctx => ctx.nodeType === "text";
run(ctx,
AND(hasSelectedText, notInsideLink, isTextNode), showTooltip
);Bu professional darajadagi pattern.
📌 Xulosa
Funktsiya asosidagi shartlar:
- eng elastik
- eng ko‘p ishlatiladigan
- eng kuchli
- modulli
- qayta ishlatiladigan
- sinovdan o‘tkazilishi oson
Rule Engine’ning yarmi aynan Funktsiya-shartlarda.
6-dars: Asinxron (Async) shartlar
Asinxron shartlar — Rule Engine’ning eng kuchli mexanizmlaridan biri. Bu sizga API chaqiriqlari, database so‘rovlari, delay, timer, file o‘qish, AI chaqiriq kabi ishlarga asoslangan qoida yaratish imkonini beradi.
Oddiy qoida tizimlari buni eplay olmaydi. Lekin conditionx engine async shartlarni bir xil sintaksisda, muammosiz qo‘llab-quvvatlaydi.
🎯 1. Async shart nima?
Asinxron shart — bu async deb e’lon qilingan va await ishlatadigan shart:
const isPremium = async ctx => {
const data = await fetchUser(ctx.id);
return data.status === "premium";
};Engine uni to‘g‘ri kutadi va qaytgan qiymatga qarab qoidani bajaradi.
⚙️ 2. Oddiy async misol
const delayCheck = async ctx => {
await wait(500); // 0.5 sekund kutish
return ctx.value > 10;
};
run(ctx,
delayCheck, doSomething
);Shart bajarilishi kechiksa ham — engine to‘g‘ri ishlaydi.
🔌 3. API chaqiriqlarida ishlatish
Real ijtimoiy tarmoq misoli:
const checkFollowers = async ctx => {
const res = await api.getFollowers(ctx.userId);
return res.count >= 1000;
};
run(ctx,
checkFollowers, giveInfluencerBadge
);🧠 4. Caching bilan async shart
Asinxron shartlar qayta chaqirilishi mumkin, shuning uchun tezlik muhim.
const hasBalance = (() => {
let cache = null;
return async ctx => {
if (!cache) cache = await api.getBalance(ctx.id);
return cache > 0;
};
})();Bu pattern real loyihada juda ko‘p ishlatiladi.
🧩 5. Async shartlarni AND/OR bilan qo‘shish
Engine AND/OR ichidagi har bir shartni kutadi.
run(ctx,
AND(
async ctx => await api.verify(ctx.id),
async ctx => await api.hasPlan(ctx.id)
),
openDashboard
);⏳ 6. Timeout qo‘shish (professional pattern)
Ba’zi async shartlar juda sekin bo‘lishi mumkin. Biz ularga max timeout berishimiz mumkin.
const withTimeout = (ms, fn) => async ctx => {
return await Promise.race([
fn(ctx),
new Promise(res => setTimeout(() => res(false), ms))
]);
};
run(ctx,
withTimeout(500, async ctx => {
return await api.checkServerHealth();
}),
showServerHealthy
);Bu high-level pattern.
🪝 7. Async shartlar ichida ctx’ni o‘zgartirish
Masalan, backenddan ma’lumot olib kelib kontekstga qo‘shish:
const loadUser = async ctx => {
ctx.user = await api.user(ctx.id);
return !!ctx.user;
};
run(ctx,
loadUser, continueProcess
);Endi barcha keyingi shartlar ctx.user ga ega bo‘ladi.
🔥 8. Async shart + Sync shartlarni aralashtirish
Bu engine’ning katta afzalligi.
run(ctx,
AND(
ctx => ctx.age > 18,
async ctx => {
const subs = await api.subscriptions(ctx.id);
return subs.active;
}
),
allowAccess
);Hech qanday qiyinchilik bo‘lmaydi.
🧵 9. Async shartdan qaytadigan qiymatlar
Asinxron shart faqat boolean qaytarishi kerak. Lekin uni boshqa maqsadlarda ham ishlatish mumkin (side-effect + return true).
const load = async ctx => {
ctx.data = await api.load(ctx.key);
return true; // shart bajarilgan deb hisoblanadi
};Shart ustida yon effekt yaratish — real hayotda juda muhim.
🏗 10. Yaxshi amaliyotlar
✔ Har bir async shart ichida try/catch bo‘lsin
const safeCheck = async ctx => {
try {
return await api.verify(ctx.id);
} catch {
return false;
}
};✔ Async shartlarni minimal qiling Ichiga katta kod tashlamang.
✔ Agar shart tez-tez ishlatilsa — caching qiling
✔ Ketma-ket 5–10 async shart qo‘ymang Aks holda kechikish bo‘ladi.
📌 Xulosa
Async shartlar imkoniyat beradi:
- API bilan ishlashga
- DB dan o‘qishga
- server bilan sinxronlashishga
- murakkab hisoblashlarni bajarishga
- kechikish yoki timeout bilan ishlashga
- real dunyo ma’lumotlari asosida qaror qabul qilishga
Bu Rule Engine’ni professional darajaga olib chiqadi.
7-dars: Regex bilan tekshirish
Regex — bu matnni namunaga qarab tekshirishga imkon beradigan kuchli vosita. conditionx Rule Engine regexlarni birinchi darajali shart sifatida qo‘llab-quvvatlaydi.
Bu degani:
/hello/— aynan shartning o‘zi bo‘lishi mumkin.
🎯 1. Regex shartlar qanday ishlaydi?
Engine regexni ko‘rganda:
cond instanceof RegExpdeb tekshiradi va:
return cond.test(String(ctx.input ?? ""));ya’ni ctx.input ga solishtiradi.
Demak, regex faqat ctx.input ustida ishlaydi.
📌 2. Eng oddiy misol
run({ input: "salom dunyo" },
/salom/, () => console.log("Topildi!")
);Natija: "Topildi!"
🎛 3. Kattaligi farq qilmaydigan (case-insensitive) regex
run({ input: "Hello" },
/hello/i, greet
);i — katta-kichik harflarga sezgirlikni o‘chiradi.
🧩 4. Bir nechta variantni tekshirish
run({ input: "hi" },
/hi|hello|hey/, reply
);| — OR operatori.
🌐 5. To‘liq moslik (exact match)
/^[0-9]+$/Faqat raqamlardan iborat matn:
run({ input: "12345" },
/^[0-9]+$/, acceptNumber
);🔐 6. Maxfiy kod yoki token formatini tekshirish
Masalan, 6 xonali faqat raqamli kod:
/^[0-9]{6}$/Yoki UUID:
/^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i🎫 7. Telefon raqamlarini tekshirish
O‘zbekiston raqami:
/^\+998\d{9}$/Misol:
run({ input: "+998901234567" },
/^\+998\d{9}$/, verifyPhone
);📧 8. Email tekshirish
Oddiy variant:
/^[^\s@]+@[^\s@]+\.[^\s@]+$/🌟 9. AND/OR bilan regexlarni birlashtirish
Regexni AND ichida ishlatish:
run({ input: "hello123" },
AND(
/^hello/,
/123$/
),
process
);OR bilan:
run({ input: "cat" },
OR(/cat/, /dog/), animalFound
);🪝 10. Regex + funksiyaviy shartlar
Regexni funksiya bilan qo‘shish ham mumkin:
run({ input: "admin123", role: "admin" },
AND(
/^admin/,
ctx => ctx.role === "admin"
),
allowAccess
);🚫 11. Regex mos kelmaganda
if (!/hello/.test(ctx.input)) return false;Engine buni avtomatik qiladi.
🔥 12. Regex + async shartlar
Hatto async bilan ham qo‘shib ishlatsa bo‘ladi:
run({ input: "order-123" },
AND(
/^order-\d+$/,
async ctx => await api.checkOrder(ctx.input)
),
processOrder
);📌 Xulosa
Regexlar Rule Engine’da juda kuchli:
- matnni format asosida tekshirish
- token, kod, user input, komandalar
- buyruqlarni parsing qilish
- filtrlar
- soddalashtirilgan DSL yaratish
8-dars: Context obyektiga asoslangan shartlar
Context (ctx) asosidagi shartlar — Rule Engine’dagi eng sodda, eng tez va eng tabiiy ishlaydigan shart turi.
Bu shartlar ctx ichidagi qiymatlarni to‘g‘ridan-to‘g‘ri tekshiradi.
Bu darsda kontekst asosidagi shartlarning ishlash mantig‘i, imkoniyatlari va real loyihadagi qo‘llanilishi bilan tanishamiz.
🎯 1. Context sharti nima?
Context sharti — bu oddiy obyekt:
{ key: value }Engine buni avtomatik ravishda:
ctx[key] === valueformula bo‘yicha tekshiradi.
🔍 2. Eng oddiy misol
run({ role: "admin" },
{ role: "admin" }, showAdminPanel
);Bu yerda:
- shart:
{ role: "admin" } - tekshiruv:
ctx.role === "admin" - natija: true → action bajariladi.
🎛 3. Bir nechta maydonni tekshirish
run(
{ role: "user", active: true },
{ role: "user", active: true },
openDashboard
);Engine har bir k-v juftlikni tekshiradi:
- ctx.role === "user"
- ctx.active === true
hammasi true bo‘lsa shart bajarilgan hisoblanadi.
🧠 4. True/False qaytaruvchi shart emas — obyektning o‘zi shart
Misol:
{ isLoggedIn: true }Bu shart biror funksiyani chaqirishga hojat qoldirmaydi.
📌 5. AND bilan birlashtirish
run(
{ role: "admin", active: true },
AND(
{ role: "admin" },
{ active: true }
),
showAdminPanel
);📌 6. OR bilan birlashtirish
run(
{ mode: "debug" },
OR(
{ mode: "dev" },
{ mode: "debug" }
),
enableLogs
);🔥 7. Object + Regex aralashmasi
Context shartni regex bilan birga ishlatish:
run(
{ type: "command", input: "/start" },
AND(
{ type: "command" },
/^\/start$/
),
startBot
);🚀 8. Object + Function birikmasi
run(
{ role: "user", age: 22 },
AND(
{ role: "user" },
ctx => ctx.age >= 18
),
allowAdultFeatures
);🔎 9. Null yoki undefined qiymatlarni tekshirish
run(
{ selection: null },
{ selection: null },
hidePopup
);Engine bunga ham ruxsat beradi.
🧱 10. Context shartlari juda samarali bo‘lgan joylar
✔ oddiy tekshiruvlar ✔ flaglar ✔ state mashina shartlari ✔ input turi yoki holatini tekshirish ✔ tooltip qoidalari ✔ editor holati (bold, italic…) ✔ foydalanuvchi holati (active, blocked…)
💡 11. E’tibor berilishi kerak bo‘lgan cheklovlar
Context shartlari:
- murakkab logika bajara olmaydi
- async qo‘llamaydi
- qisman moslik emas, to‘liq tenglikni tekshiradi
- nested obyektlarda ishlamaydi:
{ user: { role: "admin" } } // ❌ ishlamaydiAgar chuqur tekshiruv kerak bo‘lsa funksiya yoziladi.
📌 Xulosa
Context asosidagi shartlar — Rule Engine’dagi eng yengil, eng tez va eng sodda shart turi. Ular:
- takror ishlatishda qulay
- sintaksisi juda qisqa
- o‘qilishi oson
- AND/OR bilan juda yaxshi uyg‘unlashadi
- kichik tekshiruvlar uchun ideal
Rule Engine’da professional darajada tezkor shartlar yozish aynan shu asosda quriladi.
9-dars: Mantiqiy operatorlar — AND, OR, NOT
Bu dars Rule Engine’ning yuragi hisoblanadi. AND, OR, NOT — barcha murakkab qoida tizimlarining asosiy mantiqiy bloklari.
conditionx engine’da ular juda qulay sintaksisga ega va funksiya, regex, obyekt, array — hammasi bilan birga ishlaydi.
🎯 1. AND operatori
Ma’nosi:
Barcha shartlar true bo‘lsa → true
Bizning engine’da:
AND(cond1, cond2, cond3...)✔ Misol
run(
{ age: 20, active: true },
AND(
ctx => ctx.age > 18,
{ active: true }
),
allowAccess
);Bu case’da:
ctx.age > 18→ truectx.active === true→ true
Hammasi true → action bajariladi
✔ AND + Regex
AND(
/^hello/,
ctx => ctx.input.length > 5
)✔ AND + async
AND(
ctx => ctx.loggedIn,
async ctx => await api.checkBan(ctx.userId)
)Engine barcha shartlarni ketma-ket await qilib tekshiradi.
🟦 2. OR operatori
Ma’nosi:
Bitta bo‘lsa ham shart true bo‘lsa → true
Sintaksis:
OR(cond1, cond2, cond3...)✔ Misol
run(
{ role: "moderator" },
OR(
{ role: "admin" },
{ role: "moderator" }
),
givePanel
);Agar bittasi mos kelsa kifoya.
✔ OR + Regex
OR(/hi/, /hello/, /hey/)✔ OR + Function
OR(
ctx => ctx.age < 13,
ctx => ctx.role === "child"
)🟥 3. NOT operatori
Ma’nosi:
Shartni teskari qiladi.
NOT(condition)✔ Misol
run(
{ banned: false },
NOT({ banned: true }),
allowLogin
);✔ Regex + NOT
NOT(/forbidden/)✔ Funksiya bilan NOT
NOT(ctx => ctx.age < 18)🧩 4. Operatsiyalarni bir-biri bilan aralashtirish
AND + OR birga
run(
{ role: "user", plan: "pro" },
AND(
OR({ role: "admin" }, { role: "user" }),
OR({ plan: "pro" }, { plan: "premium" })
),
allowFeature
);Bu murakkab, ammo juda tabiy mantiqiy tuzilma.
NOT + AND
AND(
NOT({ banned: true }),
ctx => ctx.active
)NOT + OR
NOT(
OR({ role: "guest" }, { role: "banned" })
)Bu "guest ham emas, banned ham emas" degani.
⚡ 5. Array sifatida shartlar (OR sifatida ishlaydi)
Engine’da:
[ cond1, cond2, cond3 ]bu ham shart bo‘lib texnik jihatdan run(ctx, cond1, action) kabi ishlaydi.
Lekin bu professional foydalanishda kam qo‘llanadi.
🔿 6. Operatorlar chainingi (chuqur kombinatsiya)
AND(
ctx => ctx.isLogged,
OR(
{ role: "admin" },
AND(
{ role: "user" },
NOT({ banned: true })
)
)
)Bu professional qoida tizimiga xos yozuv.
🧠 7. Nega AND/OR/NOT juda muhim?
✔ murakkab biznes mantiqni soddalashtiradi ✔ ko‘p qavatli if-else labirintini yo‘q qiladi ✔ o‘qilishi juda oson ✔ qayta ishlatish imkonini beradi ✔ DSL (domain-specific language) yaratishga zamin yaratadi
Engine asosiy kuchini aynan shundan oladi.
📌 Xulosa
Mantiqiy operatorlar — Rule Engine’ning eng muhim elementi:
| Operator | Ma’nosi | Natija | | -------- | -------------------------- | ------ | | AND | Hammasi true | Va | | OR | Kamida biri true | Yoki | | NOT | True → false, false → true | Emas |
Ular orqali:
- funksiyalar
- regexlar
- obyektlar
- async shartlar
- nested shartlar
hammasi birlashadi.
10-dars: Murakkab shart kombinatsiyalari
Bu dars — Rule Engine’dan maksimal darajada kuchli foydalanish uchun asosiy bosqich. Bu yerda shartlar bir-biri bilan aralashtiriladi:
- Function
- Async function
- Regex
- Object match
- AND / OR / NOT
- Nested (ichma-ich) shartlar
Bu kombinatsiyalar yordamida juda murakkab mantiqni ham 1–2 qatorda ifodalash mumkin.
🔥 1. Function + Object birgalikda
AND(
ctx => ctx.age > 18,
{ verified: true }
)Bu shart:
ctx.age > 18ctx.verified === true
ikkalasi ham true bo‘lsa → ishlaydi.
🔥 2. Regex + Function
AND(
/^hello/i,
ctx => ctx.input.length > 5
)Bu:
- input “hello” bilan boshlanishi
- uzunligi 5 dan katta bo‘lishi
demak 2 bosqichli tekshiruv.
🔥 3. Regex + Object + OR
OR(
/^admin_/,
{ role: "owner" },
{ super: true }
)Kamida bittasi true → shart bajariladi.
🔥 4. Async + Function + AND
AND(
ctx => ctx.loggedIn,
async ctx => await api.checkSubscription(ctx.userId),
async ctx => !(await api.isBanned(ctx.userId))
)Bu professional “auth layer”ga o‘xshaydi:
- login qilingan
- subscription bor
- ban qilinmagan
Barchasi true bo‘lishi kerak.
🔥 5. Nested AND + OR (ko‘p qatlamli)
AND(
ctx => ctx.active,
OR(
{ role: "admin" },
AND(
{ role: "user" },
{ premium: true }
)
)
)Bu murakkab mantiq:
- Foydalanuvchi active va
- (admin yoki (user va premium))
Bu real tizimlarda juda uchraydi.
🔥 6. NOT bilan kuchli kombinatsiya
Blacklisted bo‘lmagan user + role = user
AND(
{ role: "user" },
NOT({ banned: true })
)🔥 7. OR + NOT kombinatsiyasi
OR(
NOT({ banned: true }),
ctx => ctx.role === "moderator"
)Bunda:
- ban bo‘lmaganlar yoki
- moderatorlar
ruxsat oladi.
🔥 8. Function + Array (array → OR sifatida ishlar)
[
ctx => ctx.id === 1,
ctx => ctx.id === 2,
/^VIP/
]Array berilsa engine uni shunday ko‘radi:
OR(cond1, cond2, regex)🔥 9. Murakkab real misol — kirish nazorati
AND(
ctx => ctx.logged,
OR(
{ role: "admin" },
AND(
{ role: "user" },
ctx => ctx.trustScore > 70,
NOT(ctx => ctx.banned)
)
),
NOT(/^temp_/)
)Bu 1 blokda bajariladigan mantiq:
- login qilingan
- admin yoki (user + trustScore > 70 + ban bo‘lmagan)
- username “temp_” bilan boshlanmaydi
Bu professional security rules logikasi.
🔥 10. Super murakkab misol (async + regex + object + nested)
AND(
ctx => ctx.input.length > 0,
OR(
/^cmd_/,
AND(
ctx => ctx.role === "operator",
async ctx => await api.hasPermission(ctx.userId, "EXECUTE_CMD"),
NOT({ suspended: true })
)
)
)Bu bir nechta darajadagi mantiqni 1 joyga jamlaydi.
🔥 11. “Case-like” kombinatsiyalar
Engine yordamida switch yoki “case”larni quyidagidek yozish mumkin:
run(
ctx,
AND(ctx => ctx.x > 10, ctx => ctx.x < 20), () => console.log("10–20"),
/^admin_/, () => console.log("admin user"),
{ vip: true }, () => console.log("VIP"),
);Bu super qulay DSL (Domain Specific Language) yaratadi.
🎯 Xulosa
Murakkab shart kombinatsiyalarining kuchi:
✔ funksiyalar ✔ async funksiyalar ✔ regex ✔ obyekt match ✔ mantiqiy operatorlar ✔ noaniq (dynamic) shartlar ✔ nested konstruktsiyalar
hammasi birga ishlaydi.
11-dars: run() funksiyasining ishlash tamoyili
Bu dars — Rule Engine’ning eng amaliy va eng muhim qismi.
run() butun tizimning "yuragi" bo‘lib, u shartlarni ketma-ket tekshiradi va ularga mos harakatlarni (action) bajaradi.
Keling, qanday ishlashini juda sodda qilib tushuntiramiz.
🧠 1. run() nima qiladi?
run(ctx, condition1, action1, condition2, action2, ...)
ya’ni juftliklar:
shart → action
shart → action
shart → actionrun():
- Har bir shartni tekshiradi
- True bo‘lsa — actionni bajaradi
- Qaysi action nima qaytarishiga qarab davom etadi yoki to‘xtaydi
🔍 2. run() qanday ishlaydi (oddiy tushuntirish)
Har bir juftlik bo‘yicha:
1) Shartni tekshiradi
- funksiya
- async funksiya
- regex
- object
- AND, OR, NOT
- hatto array
hammasini tekshira oladi.
2) Agar shart true bo‘lsa → action bajaradi
3) Actionning qaytishiga qaraydi:
| Action qaytarsa | Ma’nosi |
| ------------------ | --------------------------------------------- |
| "stop" | darhol to‘xtaydi |
| "next" | shu actionni o‘tkazib, keyingi shartga o‘tadi |
| { ... } (object) | ctx ichiga qo‘shadi |
| boshqa value | action bajarilgan hisoblanadi va run tugaydi |
🧱 3. run() ni oddiy misol bilan tushunish
run(
ctx,
ctx => ctx.age > 18,
() => console.log("Katta yoshli"),
ctx => ctx.age > 12,
() => console.log("O‘smir"),
true,
() => console.log("Bola")
);Agar age = 20 bo‘lsa:
- 1-shart true → "Katta yoshli" chiqaradi → run tugaydi
- Keyingilarga o‘tmaydi.
run() birinchi mos kelgan shartni bajaradi → va to‘xtaydi.
Bu juda muhim.
⏹ 4. "stop" – run’ni majburan to‘xtatish
run(
ctx,
ctx => ctx.isAdmin,
() => "stop", // to‘xtatadi
true,
() => console.log("Bu hech qachon ishlamaydi")
);⏭ 5. "next" – actionni o‘tkazib yuborish
Bu juda qulay:
run(
ctx,
ctx => ctx.vip,
() => "next", // shart true, lekin action bajarilmasin
true,
() => console.log("Oddiy action ishladi")
);Shart true, ammo actionni bajarmay ketadi → keyingi shartga o‘tadi.
🔄 6. Context’ni (ctx) yangilash
Agar action object qaytarsa → ctx ichiga qo‘shiladi:
run(
ctx,
ctx => ctx.age > 18,
() => ({ allowed: true })
);Natija:
ctx.allowed === true📌 7. run() ning mantiqiy xulq-atvori
- Eng birinchi mos kelgan shart “g‘olib”
"stop"run’ni to‘xtatadi"next"bosqichni o‘tkazib yuboradi- Action object qaytarsa → ctx yangilanadi
- Agar hech narsa mos kelmasa → run false qaytaradi
🧪 8. Real hayotiy misol
run(
ctx,
AND({ role: "admin" }, NOT({ banned: true })),
() => ({ access: "full" }),
{ role: "user" },
() => ({ access: "limited" }),
true,
() => ({ access: "none" })
);Natijada:
- admin → full access
- user → limited
- boshqalar → none
if-else labirintlaridan xalos bo‘ldik.
🧠 9. Nega run() kuchli?
✔ “case-like” DSL yaratadi ✔ mantiqni juda soddalashtiradi ✔ qayta foydalanish oson ✔ async va sync shartlar bir xil ishlaydi ✔ nested shartlar qo‘llab-quvvatlanadi ✔ context yangilanib boradi
Bu engine’ning eng katta kuchi — run orqali butun mantiq grafik kabi quriladi.
🎯 Xulosa
run() — Rule Engine’dagi eng muhim mashina:
- juftliklar bo‘yicha shartlarni tekshiradi
- mos kelgan actionni bajaradi
- actionning natijalariga qarab to‘xtaydi yoki davom etadi
- contextni o‘zgartiradi
Bu orqali shartli mantiqlarni juda tabiiy, toza va professional ko‘rinishda yozish mumkin.
12-dars: Action funksiyalari va ularning natijalari
Bu darsda Rule Engine ichidagi action funksiyalari qanday ishlashi, ular nimani qaytarishi va run() funksiyasi bu natijalarni qanday talqin qilishini o‘rganamiz.
Action — bu shart TRUE bo‘lganida bajariladigan kod.
action(ctx) — har doim context (ctx) bilan chaqiriladi.
🎯 Action nima?
Action — bu:
- qiymat qaytaruvchi funksiya
- yoki async funksiya
- yoki o‘zi hech narsa qaytarmaydigan oddiy funksiya
Shartga mos kelganda Engine shu actionni bajaradi.
🧠 1. Action’ning asosiy rollari
Action:
- Context’ni o‘zgartirishi mumkin
- Ma’lum signal qaytarishi mumkin (
stop,next) - Mantiqni davom ettirishni yoki to‘xtatishni belgilaydi
- Async yoki oddiy bo‘lishi mumkin
⚙ 2. Action natijalari va ularning ma’nolari
Rule Engine action natijasiga qarab qaror qabul qiladi:
1) "stop" qaytarish
Action:
() => "stop"Bu run’ni darhol to‘xtatadi.
Misol:
run(
ctx,
ctx => ctx.isAdmin,
() => "stop",
true,
() => console.log("Bu hech qachon ishlamaydi")
);Admin bo‘lsa — Engine shu joyda tugaydi.
2) "next" qaytarish
() => "next"Shart TRUE bo‘lsa ham, action bajarilmaydi, Engine keyingi shartga o‘tadi.
Misol:
run(
ctx,
ctx => ctx.vip,
() => "next",
true,
() => console.log("Keyingi action bajarildi")
);VIP bo‘lsa ham → birinchi action o‘tkazib yuboriladi.
3) Object qaytarish → Context ga qo‘shiladi
Agar action object qaytarsa:
() => ({ active: true })Engine buni context ichiga merge qiladi:
Misol:
run(
ctx,
ctx => ctx.logged,
() => ({ lastLogin: Date.now() })
);
console.log(ctx.lastLogin); // mavjud bo‘ladiObject avtomatik qo‘shiladi, massivlar ham qo‘llanadi.
4) Promise (async action)
Agar async bo‘lsa:
async () => {
const data = await fetch();
return { user: data };
}Engine avtomatik kutadi:
- natijani object bo‘lsa — ctx ga qo‘shadi
- string bo‘lsa — signal sifatida ishlatadi
- boshqa qiymat bo‘lsa — shunchaki qaytadi
🧱 3. Action hech narsa qaytarmasa (undefined)
Agar action hech narsa qaytarmasa:
() => { console.log("Hello"); }Bu hisoblanadi: ✔ Action bajarildi ✔ Run shu yerdagina tugaydi ✔ Keyingi shartlarga o‘tmaydi
🔍 4. Action natijasining tahlili (run() ichida)
run() ichida:
if (result === "stop") return true;
if (result === "next") continue;
if (result && typeof result === "object") Object.assign(ctx, result);
return true;Demak:
| Qaytgan qiymat | Engine reaksiyasi |
| ------------------------------------ | -------------------------- |
| "stop" | run tugaydi |
| "next" | action o‘tib ketadi, davom |
| object | ctx ga qo‘shadi, tugaydi |
| undefined / number / string (boshqa) | action tugadi, run tugaydi |
🔥 5. Action’larning amaliy roli
Action yordamida siz:
- logger ishlatishingiz
- auth tekshirishingiz
- back-end dan data chaqirishingiz
- UI uchun tooltip yaratishingiz
- marketing rules
- promo code checker
- anti-fraud tizim
- order routing engine
qurishingiz mumkin.
Rule Engine aynan action orqali “natija beradi”.
🧪 6. Real hayotdan super sodda misol
run(
ctx,
{ step: 1 },
() => ({ message: "Boshlang‘ich step" }),
{ step: 2 },
async () => {
const price = await api.getPrice();
return { price };
},
true,
() => "stop"
);Bu misol:
- step=1 bo‘lsa, konteksga message qo‘shiladi
- step=2 bo‘lsa, API chaqiriladi
- bo‘lmasa — to‘xtatiladi
Boshdan-oxirigacha toza mantiq.
🎯 Xulosa
Action — Rule Engine’ning bajaruvchi qismi bo‘lib:
- mantiqni bajaradi
- context’ni o‘zgartiradi
- async bo‘lishi mumkin
- run oqimini boshqaradi (
stop,next) - object qaytarib contextni boyitadi
Shartlar faqat tekshiradi. Action — ish qiladi.
13-dars: “stop” va “next” boshqaruv oqimi
Bu dars juda muhim, chunki Rule Engine ichida qaysi shartdan keyin to‘xtash yoki davom etishni aynan shu ikkita signal — "stop" va "next" boshqaradi.
Ular Engine’ning mantiqiy oqimini boshqarayotgan mo‘’jizaviy tugmalar!
Keling, har birini SUPER aniq tushuntirib chiqamiz. 🚀🔥
🛑 1. “stop” — Darhol to‘xtatish buyrug‘i
Action shunday qaytsa:
() => "stop"Rule Engine shu joyning o‘zida ishlashni tugatadi.
- keyingi shartlar tekshirilmaydi
- keyingi actionlar bajarilmaydi
- run() funksiyasi
trueqaytaradi - konteksga hech narsa qo‘shilmaydi (agar qaytariladigan object bo‘lmasa)
🔥 Misol:
run(
ctx,
ctx => ctx.admin,
() => "stop",
true,
() => console.log("Bu hech qachon ishlamaydi")
);Agar ctx.admin = true bo‘lsa → Engine shu joyda to‘xtaydi.
“stop” qayerda foydalaniladi?
- Tekshiruvdan o‘tmagan foydalanuvchini bloklash
- Tooltipni bitta shartda to‘xtatish
- Order tekshiruvini yakunlash
- Tezda chiqish (“early exit”)
- Short-circuit biznes qoidalarida
“stop” — bu Engine'ning “STOP” belgili semafori kabi.
➡️ 2. “next” — Keyingi qoidaga o‘tish buyrug‘i
Agar action:
() => "next"qaytarsa:
- shart TRUE bo‘lgan bo‘lsa ham
- action bajarilgan deb hisoblanmaydi
- run() davom etadi, keyingi shartlar tekshiriladi
- context o‘zgarmaydi
🔥 Misol:
run(
ctx,
ctx => ctx.isVIP,
() => "next",
true,
() => console.log("Keyingi qoidaga o‘tdi!")
);VIP bo‘lsa → birinchi action o‘tib ketiladi, ikkinchi action ishlaydi.
“next” qayerda kerak bo‘ladi?
- Ko‘p-stepli tekshirishlar
- “Agar bu shart bo‘lsa o‘tib ket, ammo run to‘xtamasin” deyilgan joylarda
- Filter sifatida ishlaganda
- Bir nechta qoida ketma-ket bajarilishi kerak bo‘lganda
- “Faqat specification uchun, action qilma” degan holatlarda
“next” — bu Engine'ning “Yashil chiroq: YON!” degan tugmasi.
💡 “stop” va “next” farqini yanada aniq qilib ko‘raylik
| Signal | Ma’nosi | Keyingi shartlarga o‘tadimi? | Keyingi action bajariladimi? |
| -------- | ---------------------------------------- | ---------------------------- | ---------------------------- |
| "stop" | Run shu joyda tugaydi | ❌ Yo‘q | ❌ Yo‘q |
| "next" | Actionni o‘tib yuboradi, run davom etadi | ✔️ Ha | ✔️ Ha |
Bu — Rule Engine’ning oqim boshqaruvchi mexanizmi.
🔥 Juda muhim eslatma:
Agar action object qaytarsa:
() => ({ x: 1 })Engine:
- context’ga qo‘shadi
- run tugaydi
"next"yoki"stop"kirmaydi
Bundan:
👉 "next" va "stop" aynan oqim boshqaruviga mo‘ljallangan maxsus qiymatlar.
🧪 Real misol: Tooltip Engine’dagi boshqaruv
run(
ctx,
AND(ctx => ctx.firstVisit, ctx => !ctx.hasTooltipShown),
() => ({ tooltip: "Welcome!" }),
ctx => ctx.user.isBanned,
() => "stop", // Ko‘rsatilmaydi
ctx => ctx.hovered,
() => "next", // Faqat tekshirish uchun
true,
() => ({ tooltip: "Default tooltip" })
);Bu quyidagicha ishlaydi:
- Birinchi shart — tooltip qo‘yadi → run tugaydi
- Agar banned bo‘lsa → “stop” → tugaydi
- Agar hover bo‘lsa → “next” → keyingi qoidaga o‘tadi
- Default tooltip qo‘yiladi
Mana bosqichma-bosqich oqim.
🎯 Xulosa
“stop”
- run butunlay tugaydi
- qoidalar tekshiruvi to‘xtaydi
- actionlar davom etmaydi
- shoshilinch to‘xtash uchun
“next”
- action o‘tib ketiladi
- run davom etadi
- navbatdagi shartga o‘tadi
- faqat filter sifatida ishlatiladigan joylarda
Bu ikkisi Rule Engine’ni o‘ta moslashuvchan qiladi.
14-dars: Contextni o‘zgartirish
Bu dars Rule Engine’ning eng muhim jihatlaridan biri — context (ctx) obyektini dynamic o‘zgartirish jarayonini o‘rganishga bag‘ishlanadi. Context — bu barcha shartlar va action’lar o‘rtasidagi ma’lumot ko‘prigi.
Engine har safar shartni tekshiradi → action bajaradi → action context’ga yangi ma’lumot qo‘shishi, eskitirish yoki o‘zgartirishi mumkin.
🧠 Context nima?
ctx — bu run() ga beriladigan oddiy obyekt:
const ctx = { input: "hello" };
run(ctx, ...rules);U:
- shartlar uchun ma’lumot bazasi
- action natijalarini saqlovchi joy
- keyingi qoidalarga uzatiladigan “holat”
🔧 Action context’ni qanday o‘zgartiradi?
Rule Engine ichida action object qaytarsa:
if (result && typeof result === "object")
Object.assign(ctx, result);Demak:
✔ Object qaytarildi → Context’ga qo‘shiladi
✔ O‘sha joyning o‘zida yangilanadi
✔ Keyingi shartlar yangilangan context bilan ishlaydi
📌 Oddiy misol
run(
ctx,
true,
() => ({ count: 1 }),
ctx => ctx.count === 1,
() => ({ message: "Birga teng!" })
);
console.log(ctx);
// { count: 1, message: "Birga teng!" }Bir action context’ni o‘zgartirsa, keyingisi o‘sha qiymatdan foydalanadi.
🔥 Context orqali ma’lumot to‘plash
Davriy qo‘shish:
run(
ctx,
true,
() => ({ clicks: (ctx.clicks || 0) + 1 })
);Har chaqirilganida:
clicks: 1
clicks: 2
clicks: 3
...Context — state machine sifatida ishlay boshlaydi.
🧩 Context yordamida branch yaratish
run(
ctx,
{ step: 1 },
() => ({ next: 2 }),
ctx => ctx.next === 2,
() => ({ step: 2 })
);Context — “routing engine”ga aylanadi.
⚙ Context bilan async operatsiya
run(
ctx,
true,
async () => {
const user = await api.getUser();
return { user };
}
);Async bo‘lsa ham context yangilanadi. Rule Engine konteksni kutadi.
🎛 Context orqali actionlar zanjiri
Quyidagidek ishlaydi:
condition → action (ctx yangilanadi)
↓
keyingi shart (yangilangan ctx bilan ishlaydi)Misol:
run(
ctx,
ctx => !ctx.token,
() => ({ token: "abc123" }),
ctx => ctx.token,
() => ({ status: "authorized" })
);Natija:
{ token: "abc123", status: "authorized" }🔒 Contextni tozalash, almashtirish, reset
Engine ichida bundan foydalanish mumkin:
() => ({ ctx: {} })Yoki to‘liq reset:
() => {
Object.keys(ctx).forEach(k => delete ctx[k]);
}Lekin odatda tavsiya qilinmaydi — Rule Engine oqimini buzishi mumkin.
➕ Contextga massiv yoki nested object qo‘shish
() => ({
user: {
name: "Ali",
age: 20
}
});Natija to‘liq qo‘shiladi.
Agar faqat qisman yangilamoqchi bo‘lsang:
() => ({
user: {...ctx.user, age: 21}
});⚠ Muhim eslatma
- Action object qaytarganda har doim run shu joyda tugaydi, lekin context yarim yo‘lda qolgani yo‘q — to‘liq qo‘shiladi.
- Faqat
"next"kontekstni o‘zgartirmasdan davom ettiradi.
🎯 Xulosa
Context — Rule Engine yuragi.
U orqali:
- qiymatlar o‘tadi
- shartlar keyingi bosqichga uzatiladi
- action natijasi saqlanadi
- engine ichida holat boshqariladi
- async ma’lumotlar saqlanadi
Context’ni o‘zgartirish — engine’ni real tizimlarda ishlatishning eng kuchli elementi.
15-dars: Amaliy shart yozish namunalar
Bu dars Rule Engine bilan real loyihalarda qanday shartlar yozilishini amaliy misollar orqali o‘rgatadi. Oldingi darslarda biz sintaksisni o‘rgandik — endi ularni amalda qo‘llaymiz.
🎯 Amaliy maqsad
Siz:
- oddiy shart
- mantiqiy operatorli shart
- async shart
- regex sharti
- context bilan shart
- ketma-ket qoidalar
- murakkab biznes mantiqlar
qanday yozilishini bilib olasiz.
1) Oddiy shart + oddiy action
run(
{age: 20},
ctx => ctx.age >= 18,
() => console.log("Kattalar uchun ruxsat berildi")
);Odatiy JavaScript bilan:
let ctx = {
age: 20
}
if (ctx.age >= 18) {
console.log("Kattalar uchun ruxsat berildi")
}Chiqish:
Kattalar uchun ruxsat berildi2) Contextga asoslangan shart
run(
{ role: "admin" },
() => console.log("Admin panelga xush kelibsiz")
);Odatiy JavaScript bilan:
const ctx = { role: "admin" };
if (ctx.role === "admin") {
console.log("Admin panelga xush kelibsiz");
}Chiqish:
Admin panelga xush kelibsizShart obyekt bo‘lganda u ctx[key] === value tarzida tekshiriladi.
3) Regex shartlari
Masalan: emailni tekshirish.
run(
{input: "[email protected]"},
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,
() => console.log("Email formati to‘g‘ri")
);Odatiy JavaScript bilan:
const ctx = { input: "[email protected]" };
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (regex.test(ctx.input)) {
console.log("Email formati to‘g‘ri");
}Chiqish:
Email formati to‘g‘riInput → ctx.input sifatida keladi.
4) Funktsiya qaytargan boolean shart
const ctx = { score: 100 };
run(
ctx,
ctx => ctx.score > 50,
() => ({ level: "pro" })
).then(() => {
console.log(ctx);
});Odatiy JavaScript bilan:
const ctx = { score: 100 };
if (ctx.score > 50) {
ctx.level = "pro";
}
console.log(ctx);Chiqish:
{ score: 100, level: 'pro' }Natijada context ichiga { level: "pro" } qo‘shiladi.
5) Async shart (masalan API’dan tekshirish)
run(
ctx,
async ctx => {
const data = await getUser(ctx.id);
return data.active;
},
() => console.log("Foydalanuvchi aktiv")
);Engine async shartni avtomatik kutadi.
6) AND operatori bilan murakkab shart
run(
ctx,
AND(
ctx => ctx.logged === true,
ctx => ctx.age >= 18
),
() => console.log("Kirish ruxsat")
);7) OR operatori
run(
ctx,
OR(
{ role: "admin" },
{ role: "moderator" }
),
() => console.log("Moderator yoki Admin kirdi")
);8) NOT operatori
run(
ctx,
NOT({ banned: true }),
() => console.log("Foydalanuvchi taqiqlanmagan")
);9) next yordamida shartlarni tekshirish zanjiri
run(
ctx,
ctx => !ctx.logged,
() => "next", // Shunchaki o‘tkazib yuboriladi
ctx => ctx.role === "guest",
() => console.log("GUEST kirishga harakat qildi"),
ctx => ctx.logged,
() => console.log("Logged user")
);10) stop bilan oqimni to‘xtatish
run(
ctx,
ctx => ctx.role === "admin",
() => "stop", // Keyingi shartlar tekshirilmaydi
true,
() => console.log("Bu hech qachon ishlamaydi")
);11) Context'ni action orqali o‘zgartirish
run(
ctx,
ctx => ctx.clicks >= 10,
() => ({ badge: "Gold" })
);
console.log(ctx.badge); // "Gold"12) Shartlar ketma-ketligi (rule chain)
run(
ctx,
ctx => ctx.points >= 1000,
() => ({ rank: "Diamond" }),
ctx => ctx.points >= 500,
() => ({ rank: "Gold" }),
ctx => ctx.points >= 100,
() => ({ rank: "Silver" })
);Foydalanuvchida 1000 dan kam bo‘lsa — pastga tushadi.
13) Murakkab biznes mantiqi: Tooltip ko‘rsatish
Masalan: tooltip faqat:
- user 3 martadan kam bosgan bo‘lsa
- birinchi marta sahifaga kirgan bo‘lsa
- flag yoqilmagan bo‘lsa
run(
ctx,
AND(
ctx => ctx.opens < 3,
ctx => ctx.firstVisit === true,
NOT({ tooltipShown: true })
),
() => ({ showTooltip: true })
);Bu juda real hayotdagi misol.
14) Order routing / qaysi narxni tanlash
run(
ctx,
ctx => ctx.amount > 1000,
() => ({ fee: 1 }),
ctx => ctx.country === "UZ",
() => ({ fee: 2 }),
true,
() => ({ fee: 3 })
);15) Final misol: Multi-step tekshiruvlar
run(
ctx,
ctx => !ctx.logged,
() => ({ message: "Avval login qiling" }),
AND(
ctx => ctx.logged,
ctx => ctx.balance < 0
),
() => ({ message: "Balans manfiy bo‘lmasligi kerak" }),
ctx => ctx.logged,
() => ({ message: "Hammasi OK" })
);🎉 Xulosa
Biz amaliy shartlar orqali quyidagilarni o‘rgandik:
✔ Oddiy shartlar ✔ Regex ✔ Async shartlar ✔ AND / OR / NOT bilan mantiq ✔ Contextni o‘zgartirish ✔ stop / next oqimi ✔ Real hayotdagi misollar: tooltip, routing, auth
Bu darsdan so‘ng siz har qanday biznes qoidani Rule Engine yordamida yozishingiz mumkin.
16-dars: Real loyihalarda qo‘llash misollari
Bu darsda Rule Engine’ni real, amaliy va katta loyihalarda qanday ishlatilishini ko‘rsataman. Har bir misol — haqiqiy tizimlarda qo‘llanilgan yoki qo‘llanishi mumkin bo‘lgan professional pattern.
Rule Engine kichik JS funksiyasi bo‘lishiga qaramay, katta enterprise loyihalarda ham juda foydali modulga aylanishi mumkin.
🏢 1) E-commerce — Promo kod va chegirma qoidalari
E-commerce tizimlarida promo kodlar: vaqtga qarab, bo‘limga qarab, summaga qarab yoki VIP foydalanuvchiga qarab ishlaydi.
Rule Engine bilan promo kod tekshiruvi:
async function test() {
let ctx = {
code: "SALE20",
total: 250,
user: { isVip: false }
};
await run(
ctx,
AND(
c => c.code === "SALE20",
c => c.total >= 200
),
() => ({ discount: 20 }),
AND(
c => c.code === "VIP50",
c => c.user.isVip
),
