widget.zip formati
Reliz — bu bitta ZIP arxiv. Uni relizga yuklaysiz, Bito hali birorta baytni ochmasdan turib arxivni tekshiradi va faqat tekshiruv muvaffaqiyatli o'tgandagina saqlaydi. Hisobot darhol sizga qaytadi — har bir xato o'zi buzgan qoidani nomma-nom aytadi.
Kataloglar tuzilishi
widget.zip
├── manifest.json majburiy, arxiv ildizida
├── script.js majburiy, arxiv ildizida
├── style.css ixtiyoriy
├── i18n/
│ ├── uz.json manifestdagi har bir til uchun bitta fayl
│ ├── ru.json
│ └── en.json
├── templates/ ixtiyoriy, nomlar erkin
│ └── card.twig
└── images/ ixtiyoriy
├── logo.png
└── menu.png ixtiyoriy, chap menyu ikonkasimanifest.json va script.js papka ichida emas, ildizda yotishi shart. Papkaning o'zini, ichidagilar o'rniga, arxivlash — yuklashdagi eng ko'p uchraydigan xato.
manifest.json
{
"widget": { "interface_version": 2 },
"bito": {
"schema_version": 1,
"locations": {
"surfaces": ["customer_profile", "card_phone", "list:customers"],
"persistent": false
},
"network": {
"connect_origins": ["https://api.example.com", "wss://events.example.com"]
},
"pipeline_endpoint": "https://api.example.com/bito/pipeline",
"left_menu": {
"widget_page": {
"title_key": "app_title",
"icon": "images/menu.png",
"submenu": {
"deals": { "title_key": "deals" },
"reports": { "title_key": "reports" }
}
},
"saleMain": {
"submenu": { "order_sync": { "title_key": "order_sync" } }
}
}
},
"languages": ["uz", "ru", "en"],
"default_language": "uz"
}| Maydon | Majburiy | Qoidalar |
|---|---|---|
widget.interface_version | Ha | Son bo'lishi kerak. 2 — joriy sahifa ichidagi runtime. |
bito.schema_version | Ha | Son bo'lishi kerak. Joriy qiymat — 1. |
languages | Ha | Til kodlari massivi. Har biri uchun arxivda i18n/<lang>.json bo'lishi shart. |
default_language | Ha | Satr. Foydalanuvchi tili languages ichida bo'lmasa ishlatiladi. |
bito.locations.surfaces | Yo'q | Joylashuv nuqtalari massivi. Har bir band — nomlangan nuqta, list:<page_name> yoki global. Takrorlar rad etiladi. |
bito.locations.persistent | Yo'q | Mantiqiy qiymat. true doimiy, hamisha ulangan slotni yoqadi. surfaces ichida globalni ko'rsatish ham uni yoqadi — ikkala shakl ham hisobga olinadi. |
bito.network.connect_origins | Yo'q | Aniq originlar massivi. Faqat oshkor qilish — pastga qarang. |
bito.pipeline_endpoint | Yo'q | Aniq https:// URL. Buyurtmalar voronkasi widget_action'ni shu yerga yuboradi. |
bito.left_menu | Yo'q | Admin panelning chap menyusidagi sahifalar: vidjetning o'z bo'limi va/yoki mavjud modullardagi submenyu sahifalari. Ilovada vidjet kodi bo'lishi shart; chap menyuga qarang. |
JSON sifatida o'qilmaydigan yoki bu shaklga mos kelmaydigan hamma narsa server xatosi emas, xabarli tekshiruv xatosi hisoblanadi.
connect_origins — oshkor qilish, cheklov emas
DANGER
bito.network.connect_origins kompaniyaga rozilik ekranida ko'rsatiladi va hech qachon texnik jihatdan qo'llanmaydi. Vidjetingizni — yoki uning buzib kirilgan versiyasini — bu ro'yxatda yo'q manzilga murojaat qilishdan hech narsa to'smaydi.
Uni qo'llashning iloji ham yo'q: sahifa darajasidagi CSP butun hujjatga tegishli bo'ladi va bitta skriptga toraytirilmaydi, kodingiz esa host sahifasida ishlaydi. Bu maydonni Bito sizga qo'yayotgan cheklov emas, balki siz kompaniyaga beryotgan deklaratsiya deb biling. Foydalanuvchilaringizga uni "sandbox" deb tasvirlamang.
Yuklashda shakli tekshiriladi, toki rozilik ekranida toza ro'yxat chiqsin:
- faqat aniq
https://yokiwss://origin; - hech qayerda joker belgi bo'lmasin — satrdagi
*darhol rad etishga olib keladi; - "yalang'och" sxema bo'lmasin (
https:); - yo'l, so'rov va fragment bo'lmasin, oxirida slash ham bo'lmasin — satr o'zining origini bo'lib qaytishi kerak.
pipeline_endpoint
Agar kompaniya buyurtmalar voronkasining bosqichiga sizning ilovangiz uchun widget_action turidagi amalni sozlasa, Bito manzilni rozilik berilgan relizingizning manifestidan oladi — kompaniya URL'ni qo'lda kiritmaydi. POST yuboriladi:
{
"event": "pipeline_action",
"db_name": "tenant_db",
"sale_order_id": "6712f0a9c4d1e87b3a0f1122",
"organization_id": "6712f0a9c4d1e87b3a0f1130",
"state_id": "6712f0a9c4d1e87b3a0f1140",
"client_id": "69c50a2d50f7b939923a469b"
}Yuklash paytida faqat shakl tekshiriladi: bu aniq https:// URL bo'lishi kerak. Yuborish paytida manzil qaytadan tekshiriladi — HTTPS bo'lmagan, loopback, xususiy va link-local manzillar rad etiladi, so'rovda esa qattiq taymaut bor.
Chap menyu
bito.left_menu o'rnatilgan vidjetga admin panelning chap menyusida o'z sahifalarini beradi. U amoCRM'ning left_menu va initMenuPage callback'i namunasida qurilgan. Menyu bandlari va sahifa sarlavhasini Bito chizadi; sahifa mazmuni esa vidjetingiz chizgan narsa. Bunday har bir sahifa widget_page nuqtasida ulanadi.
bito.left_menu avvalgi bito.settings_page va bito.menu maydonlari o'rnini egallaydi. Ikkalasi ham olib tashlangan: ulardan birortasini hali ham e'lon qilgan manifest left_menuga ishora qiluvchi xabar bilan rad etiladi.
left_menuning har bir kaliti — blok: widget_page yoki modul kaliti.
| Blok | Maydonlar | Qoidalar |
|---|---|---|
widget_page | title_key (majburiy), icon, submenu | Vidjetning o'z yuqori darajali bo'limi. submenu bo'lmasa bitta sahifa; submenuda ko'pi bilan 10 ta band. |
| modul kaliti | submenu (majburiy) | O'sha modulning Kengaytmalar guruhiga qo'shiladigan 1 tadan 3 tagacha sahifa. title_key va icon rad etiladi — modul o'z nomi va ikonkasini saqlaydi. |
Modul kaliti quyidagilardan biri bo'lishi shart, boshqa har qanday kalit rad etiladi. Prefiks — sahifa URL'ining boshi.
| Modul kaliti | URL prefiksi |
|---|---|
saleMain | /sale |
customerMain | /customer |
distributionMain | /distribution |
logisticsOrder | /logistics |
supplyMain | /supply |
warehouseMain | /warehouse |
financeMain | /finance |
hrMain | /hr |
integrationMain | /integration |
manufacturingMain | /manufacturing |
referenceMain | /reference |
toolsMain | /tools |
submenu — obyekt: kalit subband kodi, qiymat esa { "title_key": "..." }. Subband kodi ^[a-z][a-z0-9_]{1,31}$ga mos bo'lishi kerak — kichik lotin harfi, keyin 1 dan 31 tagacha kichik harf, raqam yoki pastki chiziq. Bandlar siz e'lon qilgan tartibda ko'rsatiladi.
Sarlavhalar
Har bir title_key i18n/<default_language>.jsonda bo'lishi shart, aks holda yuklash rad etiladi. Sarlavhalar yuklash paytida arxivdan olinadi, shuning uchun menyu matni ko'rib chiqilgan paketdan chetga chiqmaydi. Ko'rsatishda har bir sarlavha foydalanuvchi tilidagi bundle'dan olinadi; u yerda kalit bo'lmasa default_language qiymati ishlatiladi.
Ikonka
icon ixtiyoriy va faqat widget_pageda ruxsat etiladi. Quyidagi shartlar bajarilmasa, yuklash rad etiladi:
- arxivdagi
images/ichidagi,.pngbilan tugaydigan faylga yo'l; - hajmi ko'pi bilan 16 KB (16 384 bayt) bo'lgan PNG fayl;
- kvadrat, har bir tomoni 48 dan 128 px gacha;
- alfa-kanalli (PNG rang turi 4 — kulrang + alfa, yoki 6 — RGBA).
Bito ikonkaning faqat shaklidan foydalanadi. PNG'ning alfa-kanali niqob sifatida qo'llanadi va menyuning joriy mavzu rangi bilan bo'yaladi, shuning uchun ikonka yorug' va qorong'i rejimga, hover va faol holatga moslashadi; o'z ranglaringiz hech qachon ko'rinmaydi. Shaffof fonda bitta glif chizing. Ikonka bo'lmasa, bandda Bitoning standart kengaytma glifi ko'rsatiladi.
Vidjet kodi va URL'lar
Menyu URL'laridagi {widget_code} — ilovaning vidjet kodi, ya'ni Mening ilovalarimda tanlab band qilinadigan system_id (FAQga qarang). Ilovada kod bo'lmasa (masalan, shaxsiy vidjetda) uning o'rniga client_id ishlatiladi: /widget/{client_id}/{subitem}.
| Sahifa | URL | location |
|---|---|---|
Submenyusiz widget_page | /widget/{widget_code} | widget_page |
widget_page submenyu bandi | /widget/{widget_code}/{subitem} | widget_page |
| Modul submenyu bandi | {prefix}/widget/{widget_code}/{subitem}, masalan /sale/widget/acme_crm/order_sync | modul kaliti, masalan saleMain |
Manifestda e'lon qilinmagan blok yoki subband URL'i vidjet o'rniga "mavjud emas" xabarini ko'rsatadi. Modul sahifasiga doim subband kodi kerak. Qaysi sahifa ochilganini vidjet initMenuPage va bito.context.menudan biladi.
Ko'rinish va ruxsatlar
- Menyu ko'pi bilan beshta vidjetning
widget_pagebo'limini ko'rsatadi; qolgan vidjetlarning bo'limlari ko'rinmaydi. Modul bandlariga bu cheklov ta'sir qilmaydi. - Menyu bandlari va sahifalar kompaniyaning har bir foydalanuvchisiga ko'rsatiladi; Bito ularni rol bo'yicha filtrlamaydi. Har bir foydalanuvchi nimani ko'rishi va qilishi mumkinligini vidjetingiz o'zi hal qiladi.
- Har bir
bito.ajaxchaqiruviga Bito RBAC baribir qo'llanadi, shuning uchun sahifa tizimga kirgan foydalanuvchining o'z huquqlaridan tashqaridagi narsani o'qiy yoki o'zgartira olmaydi. - Bandlar ilova o'rnatilgach paydo bo'ladi. Kodingiz sahifada faqat kompaniya relizga rozilik bergandan keyin ishlaydi — boshqa har qanday joylashuv nuqtasidagi kabi.
amoCRM'dan farqlari
- Sarlavha maydoni —
title_key(i18n kaliti). sortyo'q: e'lon qilish tartibi — ko'rsatish tartibi.is_hiddenyo'q.- Ikonka — chizilganicha ko'rsatiladigan SVG emas, shakl sifatida ishlatiladigan va Bito mavzu ranglarida bo'yaladigan PNG.
- Modul kalitlari Bitoning o'ziniki, ular yuqorida keltirilgan.
Til lug'atlari
Tekis JSON obyekt: kalit → satr. Bito ulanish paytida serverda bitta lug'atni tanlaydi: agar manifestda e'lon qilingan bo'lsa foydalanuvchi tilini, aks holda default_language'ni. Vidjet faqat o'shani oladi — bito.i18n() orqali.
{
"title": "Qo'ng'iroqlar tarixi",
"empty": "Hozircha hech nima yo'q",
"greeting": "Assalomu alaykum, {{name}}"
}JSON sifatida noto'g'ri lug'at logga yoziladi va bo'sh deb hisoblanadi — vidjet baribir ulanadi, har bir kalit esa o'zini qaytaradi.
templates/
templates/ ichidagi har bir fayl mount javobiga qo'shiladi va templates/ prefiksidan keyingi yo'li bo'yicha nomlanadi: templates/card.twig — bu card.twig. Render — ikki jingalak qavs ichidagi oddiy almashtirish, boshqa hech nima: na sikl, na shart, na filtr. .twig kengaytmasi tanishlik uchun ruxsat etilgan; bu Twig dvigateli emas.
style.css
Fayl bo'lsa, vidjet ishlab turgan vaqtda host hujjatiga <link> sifatida ulanadi va uzilganda olib tashlanadi. U hech qanday doiraga cheklanmagan: yalang'och .card { ... } qoidasi admin panelni ham qayta bo'yaydi. Har bir selektorga o'z prefiksingizni qo'ying.
script.js
AMD modul. Qarang: CustomWidget hayotiy sikli.
Cheklovlar
Bularning barchasi ZIP markaziy katalogi bo'yicha, hech narsa ochilmasdan oldin tekshiriladi, shu sababli zip-bomba ochilmasdan turib rad etiladi.
| Cheklov | Qiymat |
|---|---|
| Siqilgan arxiv | 10 MiB (10 485 760 bayt) |
| Umumiy siqilmagan hajm | 50 MiB (52 428 800 bayt) |
| Bitta fayl, siqilmagan holda | 5 MiB (5 242 880 bayt) |
| Yozuvlar soni | 1000 |
| Ochilish nisbati, har bir yozuv uchun | 100:1 |
Yozuv nima uchun rad etiladi
| Qoida | Tafsilot |
|---|---|
| Mutlaq yo'llar | Boshidagi / yoki har qanday mutlaq yo'l |
| Chegaradan chiqish | Yo'lning .. bo'lagi |
| Teskari slash | Yozuv nomida \ uchrashi |
| Symlinklar | Arxiv qaysi OS'ni da'vo qilishidan qat'i nazar, shartsiz rad etiladi |
| Shifrlangan yozuvlar | Parol bilan himoyalangan yozuvlar qabul qilinmaydi |
| Ichma-ich arxivlar | .zip .rar .7z .tar .gz .tgz .bz2 |
| Bajarish biti | Unix 0o111 rejim bitlaridan biri qo'yilgan bo'lsa |
| Takroriy yo'llar | Bir xil yozuv nomi ikki marta |
| Noma'lum kengaytma | Quyidagi ro'yxatda yo'q hamma narsa |
| Noto'g'ri matn kodlash | UTF-8 bo'lmagan matn fayli |
| Rasm bo'lmagan rasm | PNG, JPEG va WebP sehrli baytlar bo'yicha tekshiriladi; kengaytmaga ishonilmaydi |
Ruxsat etilgan kengaytmalar: .js .json .css .html .twig .txt .png .jpg .jpeg .webp .woff2
Kontent turlari serverda aynan shu kengaytmadan belgilanadi, arxiv yoki yuklash so'rovi da'vo qilgan narsadan emas.
Tekshiruv hisoboti
upload hisobot bilan javob beradi va u tekshiruv o'tgan-o'tmaganidan qat'i nazar relizda saqlanadi:
{
"ok": false,
"errors": [
"Extension not allowed: vendor/lib.map",
"Missing i18n/ru.json declared in manifest.json"
],
"entries": 14,
"uncompressed_bytes": 189342
}ok qiymati true bo'lganda hisobot o'qilgan manifestni ham olib keladi. Saqlangan hisobot ok demaguncha relizni tekshiruvga yuborib bo'lmaydi.