npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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.

Readme

🚀 O‘rnatish

npm orqali:

npm install conditionx

Yoki Yarn orqali:

yarn add conditionx

Yoki 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 xabar

Shartlar:

  • bo‘laklarga bo‘lingan
  • oson tahrirlanadi
  • uchinchi shaxs ham osongina tushunadi
  • qayta ishlatiladi

⚙️ Rule Engine qanday ishlaydi?

Uning vazifasi oddiy:

  1. Shartni baholaydi
  2. U mos bo‘lsa — action (amal) bajariladi
  3. Mos bo‘lmasa — keyingi shartga o‘tadi
  4. 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 → ModullarQarorlar → TizimliKod → Toza va muvozanatliKengaytirish → OsonTestlash → 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:

  1. Shartni baholaydi
  2. True → action bajariladi
  3. Action oqimga ta’sir qiladi
  4. 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:

Teng

Funktsiya 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: 1

Bu 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:

  1. Oddiy boolean
  2. Funktsiya
  3. Asinxron funktsiya
  4. Regex
  5. Object matching
  6. AND
  7. OR
  8. NOT
  9. 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/false

ctx — 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 RegExp

deb 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] === value

formula 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" } }  // ❌ ishlamaydi

Agar 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 → true
  • ctx.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 > 18
  • ctx.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:

  1. login qilingan
  2. subscription bor
  3. 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 → action

run():

  1. Har bir shartni tekshiradi
  2. True bo‘lsa — actionni bajaradi
  3. 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:

  1. Context’ni o‘zgartirishi mumkin
  2. Ma’lum signal qaytarishi mumkin (stop, next)
  3. Mantiqni davom ettirishni yoki to‘xtatishni belgilaydi
  4. 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‘ladi

Object 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 true qaytaradi
  • 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:

  1. Birinchi shart — tooltip qo‘yadi → run tugaydi
  2. Agar banned bo‘lsa → “stop” → tugaydi
  3. Agar hover bo‘lsa → “next” → keyingi qoidaga o‘tadi
  4. 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 berildi

2) 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 kelibsiz

Shart 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‘ri

Input → 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
        ),