Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. CLI'ning yo'li
- 2.1 Buyruqdan exit kodgacha
- 2.2 valyuta da qayerda nima
- 3. Shebang va bin
- 3.1 Shebang
- 3.2 bin maydoni va shim'lar
- 3.3 npm link — ishlab chiqishda sinash
- 4. Argumentlar: parseArgs
- 4.1 process.argv dan bayroqlargacha
- 4.2 Manfiy son va --
- 5. stdout va stderr
- 5.1 Qoida
- 5.2 EPIPE: o'quvchi ketib qolsa
- 6. Exit kodlar
- 6.1 Kelishuv
- 6.2 process.exitCode, process.exit() emas
- 7. Foydalanuvchi bilan kelishuvlar
- 7.1 --help va --version
- 7.2 Sozlash ustuvorligi
- 7.3 Ranglar va TTY
- 8. CLI qadami: anatomiya tekshiruvi (holat 52 ga tayyorgarlik)
- 9. Ko'p uchraydigan xatolar
- 9.1 Natijani console.error ga, xatoni console.log ga
- 9.2 Har qanday xatoda exit 1
- 9.3 Stek bilan yiqilish
- 9.4 Shebang'siz bin
- 9.5 Interaktiv savol quvurda
- 10. Mashqlar
- 1-mashq (oson): qaysi oqim, qaysi kod?
- 2-mashq (o'rta): o'zbekcha argument xatolari
- 3-mashq (qiyin): sinab bo'ladigan mini-CLI
- 4-mashq: CLI qadami — EPIPE himoyasi (tajriba)
- 11. Real ishda
- Xulosa
- Manbalar
Node.js CLI anatomiyasi: shebang, bin, parseArgs, stdout/stderr va exit kodlar
Qisqacha: Yaxshi CLI — uchta shartnomani bajaradigan dastur: argument oladi (
util.parseArgs), natijani stdout'ga, qolgan hamma narsani stderr'ga yozadi va to'g'ri exit kod qaytaradi (0 — muvaffaqiyat, 1 — ish vaqtidagi xato, 2 — noto'g'ri foydalanish). Uni buyruq sifatida chaqirish uchun faylning birinchi qatori#!/usr/bin/env node(shebang) vapackage.jsondabinmaydoni kerak. Shu qoidalar bajarilsa, dastur quvurlarda (| head), skriptlarda va CI'da odam aralashuvisiz ishlaydi.
Bu darsda
- CLI'ning yo'lini terminaldan
main()gacha va qaytib exit kodgacha chizib bera olasiz. - Shebang,
binmaydoni va npm yaratadigan Windows shim'lari nima qilishini tushuntirasiz. util.parseArgsning qoidalarini, jumladan manfiy son va--tuzog'ini bilasiz.- stdout va stderr'ni to'g'ri ajratasiz va
EPIPEqulashini oldini olasiz. --help,--version, exit kodlar va sozlash ustuvorligi bo'yicha umumiy kelishuvlarni qo'llaysiz.
Oldin bilishingiz kerak: process obyekti: argv, env, exit kodlari, util moduli, readline va terminal, O'z npm paketingizni nashr qilish.
1. Nega bu kerak?
Siz har kuni CLI ishlatasiz: git, npm, node, tsc. Ular bir-biriga o'xshaydi: --help yordam beradi, xato bo'lsa qizil xabar va to'xtash, natijani | bilan boshqa dasturga uzatish mumkin. Bu o'xshashlik tasodif emas — o'nlab yillik kelishuvlar (conventions) natijasi.
valyuta ni qurish davomida bu kelishuvlarni bittalab qo'shdingiz: process darsida exit kodlar, util darsida parseArgs, readline darsida TTY, npm paket darsida bin. Bu dars — ularni bitta rasmga yig'adi. Yangi kod kam, lekin har qismning "nega"si aniq bo'ladi.
O'xshatish: avtomobil. Rul, pedallar, chiroqlar — har mashinada bir joyda. Yangi mashinaga o'tirgan haydovchi qo'llanmasiz yuradi. CLI ham shunday: kelishuvlarga amal qilsangiz, foydalanuvchi valyuta --help ni o'qimasdan ham ko'p narsani taxmin qiladi.
2. CLI'ning yo'li
2.1 Buyruqdan exit kodgacha
valyuta kurs USD -f csv | head -2 yozilganda nima bo'ladi:
flowchart TD
A["Shell: valyuta kurs USD -f csv"] --> B["PATH'dan valyuta topiladi"]
B --> C["shebang yoki .cmd shim: node dist/bin.js"]
C --> D["process.argv"]
D --> E["parseArgs: bayroqlar va so'zlar"]
E --> F["main(): ish"]
F --> G["stdout: natija → head"]
F --> H["stderr: ogohlantirish → ekran"]
F --> I["exit kod → shell"]Nimaga qarang: chiqish uchta kanal — stdout, stderr va exit kod. Ularning har biri boshqa "o'quvchi" uchun: stdout — keyingi dastur yoki fayl, stderr — odam, exit kod — skript va CI.
2.2 valyuta da qayerda nima
| Bo'lak | Fayl | Qaysi darsda |
|---|---|---|
Shebang, SIGINT, process.exitCode |
src/bin.ts |
process, ESM |
parseArgs, yordam matni, buyruqlar |
src/cli.ts |
util |
I/O siz mantiq (bajar) |
src/buyruq.ts |
readline |
bin, files, engines |
package.json |
npm paket |
Muhim ajratish: bin.ts — yon ta'sirli kirish nuqtasi (jarayonga tegadi), cli.ts dagi main(argv, env) esa faqat son qaytaradi. Shuning uchun testlar main() ni to'g'ridan chaqira oladi va kutubxona sifatida import qilinganda hech narsa ishga tushib ketmaydi.
3. Shebang va bin
3.1 Shebang
Yakuniy dist/bin.js ning birinchi qatori:
#!/usr/bin/env nodeShebang (#! — "hash-bang") — Linux va macOS yadrosi uchun ko'rsatma: "bu faylni qaysi dastur bilan ochish kerak". /usr/bin/env node — "PATH'dan node ni top". To'g'ridan /usr/bin/node yozilmaydi: Node har kompyuterda boshqa joyda (nvm, Homebrew, fnm). JavaScript uchun bu qator izoh hisoblanadi — Node uni tashlab ketadi.
Windows yadrosi shebang'ni o'qimaydi. U yerda ishni npm bajaradi (keyingi bo'lim).
3.2 bin maydoni va shim'lar
package.json da:
"bin": {
"valyuta": "dist/bin.js"
}"Bu paket o'rnatilganda valyuta buyrug'i paydo bo'lsin va dist/bin.js ni ishga tushirsin". O'rnatishda npm node_modules/.bin/ ga uchta fayl yozadi (kanon, Windows): valyuta (bash uchun), valyuta.cmd (cmd uchun), valyuta.ps1 (PowerShell uchun). .cmd ning asosiy qatori:
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\valyuta\dist\bin.js" %*Bu yerda %_prog% — node, %* — hamma argumentlar. Ya'ni Windows'da shim "shebang'ning ishini" qo'lda qiladi. Linux'da npm faylni bajariladigan qiladi (chmod +x) va .bin/valyuta ga havola (symlink) yaratadi — hujjat bo'yicha, biz Linux'da sinamadik.
Diqqat: Shebang'ni unutish Windows'da ham sezilmaydigan xato emas. Kanon Workspaces tajribasida shebang'siz
cli.tsbilan shunday bo'ldi: bash shim faylni shell skript deb bajardi vaimport: command not foundxatosi chiqdi;npx valyutaesa 2 daqiqadan ko'p osilib qoldi. Saboq:binfaylida shebang shart.
3.3 npm link — ishlab chiqishda sinash
Har o'zgarishdan keyin npm pack va o'rnatish (npm paket darsidagidek) — sekin. npm link loyiha papkasida global havola yaratadi: valyuta buyrug'i to'g'ridan sizning papkangizga ishora qiladi, npm run build dan keyin o'zgarish darhol ko'rinadi. Olib tashlash — npm unlink -g.
Kanonda npm link ishlatilmadi: u global papkaga yozadi, zavod qoidasi esa global o'rnatishni taqiqlaydi. Uning o'rniga npm pack + boshqa papkaga npm i — bu foydalanuvchi aynan nimani olishini ham sinaydi. O'z kompyuteringizda npm link dan bemalol foydalaning. Yana bir yo'l — global hech narsa yozmaydigan node dist/bin.js kurs USD yoki npm run start -- kurs USD (--watch va node --run).
Tekshirib ko'ring:
binfaylidist/bin.tsemas,dist/bin.js. Nega.tsga qaratilmaydi, axir Node 24.tsni ishga tushiradi?
Javob
Node node_modules ichidagi fayllarda type stripping qilmaydi — kanon buni sinagan: ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING (npm paket darsida). Va tezlik: dist/bin.js 103 ms, src/bin.ts 164 ms (TypeScript'ni to'g'ridan ishga tushirish). Paketga build qilingan JS boradi.
4. Argumentlar: parseArgs
4.1 process.argv dan bayroqlargacha
process.argv — oddiy satrlar massivi: [node yo'li, skript yo'li, ...siz yozganlar]. Uni qo'lda tahlil qilish — -f csv, --format=csv, -fcsv hammasini bilish degani. node:util dagi parseArgs buni qiladi. Kanondagi sozlamaga yaqin misol:
import { parseArgs } from "node:util";
const options = {
format: { type: "string", short: "f", default: "jadval" },
sana: { type: "string", short: "s" },
offline: { type: "boolean", default: false },
};
function ajrat(args) {
try {
const { values, positionals } = parseArgs({
args, options, allowPositionals: true, strict: true,
});
console.log(JSON.stringify({ ...values }), positionals);
} catch (x) {
console.log(x.code);
}
}
ajrat(["kurs", "USD", "EUR", "-f", "csv"]);
ajrat(["kurs", "--sana=2026-10-01", "--offline"]);
ajrat(["-fcsv", "kurs"]);
ajrat(["kurs", "--bayroq"]);
ajrat(["kurs", "--format"]);
ajrat(["kurs", "--offline=ha"]);Konsolda:
{"format":"csv","offline":false} [ 'kurs', 'USD', 'EUR' ]
{"sana":"2026-10-01","offline":true,"format":"jadval"} [ 'kurs' ]
{"format":"csv","offline":false} [ 'kurs' ]
ERR_PARSE_ARGS_UNKNOWN_OPTION
ERR_PARSE_ARGS_INVALID_OPTION_VALUE
ERR_PARSE_ARGS_INVALID_OPTION_VALUEQoidalar:
-f csv,--format csv,--format=csv,-fcsv— hammasi bir xil.defaultfaqat bayroq berilmaganda.sanadadefaultyo'q — berilmasa, natijada kalit umuman yo'q.strict: true— noma'lum bayroq (--bayroq), qiymatsiz satr bayrog'i (--format) va qiymatli boolean (--offline=ha) xato beradi. Bu yaxshi:--ofline(xato yozilgan) jim o'tib ketmaydi.allowPositionals: true— bayroq bo'lmagan so'zlar (kurs,USD)positionalsga yig'iladi.
parseArgs faqat turni tekshiradi: --sana=ertaga ni ham qabul qiladi. Ma'noni (sana to'g'rimi) dastur o'zi tekshiradi — valyuta da bu sananiTekshir (exit 2).
4.2 Manfiy son va --
Haqiqiy topilma: valyuta -5 USD ishlamaydi. Biz yakuniy holatda sinadik:
$ valyuta -5 USD
Xato: Unknown option '-5'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "-5"
[exit 2]
$ valyuta -- -5 USD
-5.00 USD = -59 515.75 UZS
[exit 0]Tarjimasi: "noma'lum bayroq -5". Xabar maslahat ham beradi. Minus bilan boshlanadigan oddiy argumentni -- dan keyin yozing. parseArgs uchun -5 — qisqa bayroq (-f kabi). -- — umumiy kelishuv: "bundan keyin bayroq yo'q, hammasi oddiy so'z". npm run start -- kurs USD dagi -- ham shu ma'noda: "keyingilari npm'niki emas".
Manfiy valyuta miqdori kam kerak bo'ladi, lekin xabar to'g'ri yo'lni o'zi ko'rsatadi — shuning uchun kanon buni qoldirdi.
Tekshirib ko'ring:
parseArgsstrict: falsebilan ishlatilsa,--ofline(bittaf) nima bo'ladi?
Javob
Xato bermaydi: noma'lum bayroq values.ofline = true sifatida qo'shiladi, values.offline esa false qoladi. Dastur jim internetga chiqadi — foydalanuvchi esa oflayn deb o'ylaydi. CLI uchun strict: true va noma'lum bayroqda exit 2 — xavfsizroq.
5. stdout va stderr
5.1 Qoida
stdout (standart chiqish) — dasturning natijasi: jadval, CSV, JSON. stderr (standart xato oqimi) — qolgan hamma narsa: ogohlantirish, xato, jarayon ko'rsatkichi, debug. Sabab — quvur faqat stdout'ni uzatadi. Yakuniy valyuta da (oflayn rejim, biz ishga tushirdik):
$ valyuta kurs USD -f csv
Ogohlantirish: offline rejim — saqlangan namuna kurslar (fixtures/) ishlatildi
sana,kod,nomi,nominal,kurs,farq
2026-10-23,USD,AQSH dollari,1,11903.15,-62.36
$ valyuta kurs all -f csv 2>/dev/null | head -3
sana,kod,nomi,nominal,kurs,farq
2026-10-23,USD,AQSH dollari,1,11903.15,-62.36
2026-10-23,EUR,EVRO,1,13329.15,-108.12Birinchi buyruqda ekranda ikkala oqim aralash ko'rinadi. Ikkinchisida 2>/dev/null stderr'ni tashladi (PowerShell'da 2>$null), head faqat toza CSV oldi. Agar "Ogohlantirish" stdout'ga yozilganida, kurslar.csv fayli birinchi qatori buzilgan holda yaratilardi va Excel uni noto'g'ri ochardi.
5.2 EPIPE: o'quvchi ketib qolsa
Biz kutmagan tuzoq. 2.3 MB CSV ni bitta process.stdout.write bilan yozadigan dasturni | head -1 ga uladik:
const qator = "2026-10-23,USD,AQSH dollari,1,11903.15,-62.36\n";
process.stdout.write(qator.repeat(50_000)); // ~2.3 MB2026-10-23,USD,AQSH dollari,1,11903.15,-62.36
node:events:505
throw er; // Unhandled 'error' event
^
Error: EPIPE: broken pipe, writeUch marta sinadik — har safar exit 1. head bitta qator olib yopildi, Node esa yopiq quvurga yozishda davom etdi. EPIPE (broken pipe — uzilgan quvur) — "o'qiydigan tomon yo'q". Foydalanuvchi uchun bu xato emas: u head bilan atayin kamroq so'radi. Lekin dastur qo'rqinchli stek bilan yiqildi.
Qizig'i: xuddi shu hajmni console.log bilan qatorma-qator yozgan dastur yiqilmadi (exit 0) — console o'z oqim xatolarini e'tiborsiz qoldiradi. process.stdout.write esa yo'q.
Tuzatish — stdout xatosini ushlash:
process.stdout.on("error", (xato) => {
// o'quvchi (head, less) quvurni yopdi — jim chiqamiz
if (xato.code === "EPIPE") process.exit(0);
throw xato;
});Shu bilan uch marta — exit 0, stek yo'q. Bu ishlovchi valyuta kanoniga kirmagan — u faqat mashq. Sababi: uning chiqishi kichik (74 qatorlik kurs all -f csv | head -2 muammosiz o'tdi), katta chiqish faqat tarix buyrug'ida. Uni katta oraliq bilan | head ga ulash — kanonda sinalmagan. Mashqda shu ishlovchini qo'shib ko'rasiz.
Maslahat: Dasturingiz natijasini
| head -1ga ulab sinang. Bu ikki narsani bir zumda tekshiradi: stdout'da ortiqcha matn yo'qligini vaEPIPEga chidamliligini.
6. Exit kodlar
6.1 Kelishuv
| Kod | Ma'nosi | valyuta da misol |
|---|---|---|
| 0 | Muvaffaqiyat | valyuta kurs USD |
| 1 | Ish vaqtidagi xato | tarmoq va kesh yo'q, fayl o'qilmadi |
| 2 | Noto'g'ri foydalanish | --bayroq, XYZ valyuta, 2026-13-45 sana |
| 130 | Ctrl+C (128 + SIGINT raqami 2) | uzun tarix paytida to'xtatish |
Biz sinagan chiqishlar:
$ valyuta -s 2026-13-45 kurs USD
Xato: Sana YYYY-MM-DD ko'rinishida va haqiqiy bo'lishi kerak: 2026-13-45
[exit 2]
$ valyuta kurs USD 2>/dev/null
2026-10-23 holatiga (fixture)
USD 1 11 903.15 -62.36 AQSH dollari
[exit 0]Nega 1 va 2 ni ajratish kerak? Skript uchun javob boshqacha: 1 — "keyinroq qayta urin" (tarmoq tiklanar), 2 — "qayta urinma, buyruq noto'g'ri". CI'da bu farq "flaky test" va "buzilgan konfiguratsiya" farqi.
6.2 process.exitCode, process.exit() emas
bin.ts oxirida:
const argv = process.argv.slice(2);
process.exitCode = await main(argv, process.env, bekor.signal);process.exit(kod) — darhol to'xtatish: navbatdagi ish, yozilmagan chiqish, finally bloklari — hammasi tashlanadi. Node hujjati ogohlantiradi: stdout'ga asinxron yozilayotgan ma'lumot yo'qolishi mumkin. Biz Windows'da 2.3 MB ni | wc -c ga yozib, keyin process.exit(0) qildik — uch marta ham 2 300 000 bayt yetib keldi. Bu mashinada yo'qotish kuzatmadik. Sababi hujjatning o'zida: Windows'da quvurga yozish sinxron, Linux va macOS'da esa asinxron (terminalda — aksincha). Demak Linux quvurida xuddi shu kod ma'lumot yo'qotishi mumkin — biz Linux'da sinamadik. process.exitCode = kod esa "tugaganingda shu kod bilan chiq" degani — Node hamma ishni tugatib chiqadi. valyuta da process.exit() faqat ikkinchi Ctrl+C da.
7. Foydalanuvchi bilan kelishuvlar
7.1 --help va --version
-h,--help— yordam stdout'ga, exit 0. U so'ralgan natija.-v,--version— faqat versiya raqami, bitta qator (1.0.0). Skriptlar uni o'qiydi, ortiqcha so'z yozmang.- Xatoda — qisqa xabar va yordam stderr'ga, exit 2.
- Argumentsiz chaqiruv —
valyutayordamni chiqaradi va exit 2 beradi: "nima qilishni aytmadingiz".
valyuta --bayroq ning haqiqiy chiqishi — birinchi qatorda Xato: Unknown option '--bayroq'…, keyin bo'sh qator va to'liq yordam matni, exit 2. Xabarning o'zi inglizcha — u parseArgs dan keladi. O'zbekcha qilish uchun x.code bo'yicha o'z matningizni yozish kerak; kanon buni qilmadi — mashq sifatida qoldi.
7.2 Sozlash ustuvorligi
valyuta ni uch joydan sozlash mumkin. Kelishuv — yaqinroq yutadi:
flowchart LR
A["Bayroq: --offline"] --> B["Muhit: VALYUTA_OFFLINE=1"]
B --> C["Fayl: config.json"]
C --> D["Sukut qiymati"]Chapdagi ustun. Bayroq — shu bitta chaqiruv uchun, muhit o'zgaruvchisi — shu terminal sessiyasi yoki CI uchun, fayl — doimiy odat uchun. valyuta da config.json faqat sukut valyutalar ro'yxatini beradi, VALYUTA_OFFLINE=1 va --offline bir xil ishlaydi.
7.3 Ranglar va TTY
Rang — faqat odam ko'radigan joyda. valyuta jadvaldagi farqni util.styleText bilan bo'yaydi; u o'zi tekshiradi: stdout TTY emas yoki NO_COLOR o'rnatilgan bo'lsa — rangsiz (readline va terminal darsidagi isTTY). CSV va JSON hech qachon rangli emas. --rangsiz bayrog'i — qo'lda o'chirish. Batafsil — Interaktiv CLI darsida.
8. CLI qadami: anatomiya tekshiruvi (holat 52 ga tayyorgarlik)
Bu darsda kod yozilmaydi: kanon anatomiyaning hamma qismini holatlar 08–46 da allaqachon qurgan. Shu yerda ro'yxat bo'yicha o'z valyuta ingizni tekshiring:
| Tekshiruv | Kutilgan |
|---|---|
head -1 dist/bin.js |
#!/usr/bin/env node |
valyuta --version |
bitta qator, package.json dagi versiya |
valyuta --bayroq; echo $? |
stderr'da xato + yordam, 2 |
valyuta kurs USD 2>/dev/null |
faqat jadval |
valyuta kurs all -f csv | head -1 |
sana,kod,nomi,nominal,kurs,farq |
valyuta -- -5 USD |
manfiy miqdor ishlaydi |
Holat 52 ning commiti (jarayon ko'rsatkichi) Interaktiv CLI darsida. Hozircha commit qilmang — o'zgarish yo'q.
Raqamlar: holat 52 da sovuq start --help 94 ms, kurs USD 103 ms (tekshiruv-52.txt, bo'sh Node 73 ms). Anatomiya qismlarining hammasi birga ~20–30 ms "qo'shadi" — bu yaxshi CLI'ning narxi.
9. Ko'p uchraydigan xatolar
9.1 Natijani console.error ga, xatoni console.log ga
Teskari ajratish — eng ko'p uchraydigan xato. Belgisi: > fayl.csv da xabar qatorlari bor, yoki xato skriptga "natija" bo'lib ketadi. Qoida: "buni keyingi dastur o'qiydimi?" — ha bo'lsa stdout.
9.2 Har qanday xatoda exit 1
throw qilib yuborilgan xato Node'da exit 1 beradi — foydalanuvchi xatosi ham, tarmoq xatosi ham bir xil. Skript farqlay olmaydi. Foydalanuvchi xatosi uchun alohida klass (FoydalanishXatosi) va exit 2.
9.3 Stek bilan yiqilish
Error: EPIPE: broken pipe, writeyoki TypeError: Cannot read properties of undefined — foydalanuvchi uchun qo'rqinchli. CLI kutilgan xatolarni ushlab, bir qatorlik xabar berishi kerak; to'liq stek — faqat NODE_DEBUG yoki --verbose bilan.
9.4 Shebang'siz bin
bash shim (Git Bash yoki Linux) faylni shell skript deb bajaradi — import: command not found; kanon tajribasida npx valyuta Git Bash'da osilib ham qoldi (Workspaces darsi). dist/bin.js ning birinchi qatorini tekshiring — tsc shebang'ni manbadan saqlaydi.
9.5 Interaktiv savol quvurda
Dastur stdin dan javob kutadi, lekin skriptda hech kim javob bermaydi — CI abadiy osilib qoladi. isTTY bo'lmasa — savol bermang, bayroq yoki xato bilan to'xtang (readline).
10. Mashqlar
Mashqlar kurs/mashqlar/24/50-cli-anatomiya/ da.
1-mashq (oson): qaysi oqim, qaysi kod?
Har holat uchun yozing: matn qaysi oqimga (stdout/stderr) va exit kod nechchi.
valyuta 100 USDnatijasi:100.00 USD = 1 190 315.00 UZSOgohlantirish: offline rejim …valyuta kurs XYZ—Xato: Noma'lum valyuta: XYZ- Tarmoq ham, kesh ham yo'q —
Xato: fetch failed valyuta --help
Yechim
- stdout, 0 — so'ralgan natija.
- stderr — natija emas, xabar; exit kod 0 (ish bajarildi).
- stderr, 2 — foydalanuvchi noma'lum kod berdi.
- stderr, 1 — buyruq to'g'ri, lekin ish vaqtida muammo; keyinroq qayta urinish mumkin.
- stdout, 0 — yordam so'ralgan, demak bu natija.
2-mashq (o'rta): o'zbekcha argument xatolari
argumentlarniOl(args) funksiyasini yozing. U parseArgs ni strict: true bilan chaqirsin (bayroqlar: format — satr, -f; offline — boolean). Muvaffaqiyatda { kod: 0, values, positionals }, xatoda { kod: 2, xabar } qaytarsin. Xabar o'zbekcha: ERR_PARSE_ARGS_UNKNOWN_OPTION uchun Noma'lum bayroq, ERR_PARSE_ARGS_INVALID_OPTION_VALUE uchun Bayroq qiymati noto'g'ri, qolganlari uchun asl xabar. Bayroq nomini xato matnidan oling: u bittalik qo'shtirnoq ichida birinchi keladi. Yordam: /'([^']+)'/.exec(matn) (RegExp asoslari). To'rt holatni sinang: kurs -f csv, --bayroq, --format, --offline=ha.
Yechim
import { parseArgs } from "node:util";
const XABARLAR = {
ERR_PARSE_ARGS_UNKNOWN_OPTION: "Noma'lum bayroq",
ERR_PARSE_ARGS_INVALID_OPTION_VALUE: "Bayroq qiymati noto'g'ri",
};
function argumentlarniOl(args) {
try {
const { values, positionals } = parseArgs({
args,
options: {
format: { type: "string", short: "f" },
offline: { type: "boolean" },
},
allowPositionals: true,
strict: true,
});
return { kod: 0, values, positionals };
} catch (x) {
const sarlavha = XABARLAR[x.code];
if (!sarlavha) return { kod: 2, xabar: x.message };
const bayroq = /'([^']+)'/.exec(x.message)?.[1] ?? "?";
return { kod: 2, xabar: `${sarlavha}: ${bayroq}` };
}
}
for (const args of [
["kurs", "-f", "csv"],
["--bayroq"],
["--format"],
["--offline=ha"],
]) {
const n = argumentlarniOl(args);
console.log(n.kod, n.xabar ?? JSON.stringify({ ...n.values }));
}Konsolda:
0 {"format":"csv"}
2 Noma'lum bayroq: --bayroq
2 Bayroq qiymati noto'g'ri: -f, --format <value>
2 Bayroq qiymati noto'g'ri: --offlineUchinchi qatorga qarang: parseArgs xabarida bayroq '-f, --format <value>' ko'rinishida — biz uni o'zgartirmadik, foydalanuvchiga qaysi bayroq ekani baribir aniq. Xato kodi (x.code) bo'yicha ishlash — xabar matnidan ko'ra ishonchliroq: kod o'zgarmaydi, matn Node versiyasi bilan o'zgarishi mumkin.
3-mashq (qiyin): sinab bo'ladigan mini-CLI
main(argv) funksiyasini yozing — u hech narsani o'zi chiqarmaydi, { stdout, stderr, kod } qaytaradi. Buyruq: narx <miqdor> [--valyuta KOD] — so'mni valyutaga aylantiradi (USD — 11903.15, EUR — 13329.15; sukut USD), natija ikki xona aniqlikda. Xatolar: argument yo'q yoki son emas — kod: 2; noma'lum valyuta — kod: 2; --help — yordam stdout'ga, kod: 0. Keyin "haqiqiy chiqish" qiluvchi kichik ishgaTushir(argv) yozing: stdout ni console.log, stderr ni console.error bilan chiqarsin va kodni qaytarsin. To'rt chaqiruvni sinang. Yordam: Number(x) va Number.isFinite (Number turi).
Yechim
import { parseArgs } from "node:util";
const KURS = { USD: 11903.15, EUR: 13329.15 };
const YORDAM = "Foydalanish: narx <so'm> [--valyuta USD|EUR]";
function main(argv) {
let a;
try {
a = parseArgs({
args: argv,
options: {
valyuta: { type: "string", default: "USD" },
help: { type: "boolean", default: false },
},
allowPositionals: true,
});
} catch (x) {
return { stdout: "", stderr: x.message, kod: 2 };
}
if (a.values.help) return { stdout: YORDAM, stderr: "", kod: 0 };
const som = Number(a.positionals[0]);
if (a.positionals.length === 0 || !Number.isFinite(som)) {
const stderr = `Xato: son kerak\n${YORDAM}`;
return { stdout: "", stderr, kod: 2 };
}
const kod = a.values.valyuta.toUpperCase();
if (!(kod in KURS)) {
const stderr = `Xato: noma'lum valyuta ${kod}`;
return { stdout: "", stderr, kod: 2 };
}
const natija = (som / KURS[kod]).toFixed(2);
const stdout = `${som} UZS = ${natija} ${kod}`;
return { stdout, stderr: "", kod: 0 };
}
function ishgaTushir(argv) {
const n = main(argv);
if (n.stdout) console.log(n.stdout);
if (n.stderr) console.error(n.stderr);
return n.kod;
}
console.log("kod:", ishgaTushir(["1000000"]));
console.log("kod:", ishgaTushir(["1000000", "--valyuta", "eur"]));
console.log("kod:", ishgaTushir(["ming"]));
console.log("kod:", ishgaTushir(["5", "--valyuta", "XYZ"]));Konsolda:
1000000 UZS = 84.01 USD
kod: 0
1000000 UZS = 75.02 EUR
kod: 0
Xato: son kerak
Foydalanish: narx <so'm> [--valyuta USD|EUR]
kod: 2
Xato: noma'lum valyuta XYZ
kod: 2Ajratish (main — toza, ishgaTushir — yon ta'sirli) valyuta dagi cli.ts / bin.ts bo'linishining kichik nusxasi. main ni node:test bilan bemalol sinash mumkin: jarayon ishga tushirish shart emas. Haqiqiy faylda oxirgi qator process.exitCode = ishgaTushir(process.argv.slice(2)) bo'ladi.
4-mashq: CLI qadami — EPIPE himoyasi (tajriba)
O'z valyuta ingizda src/bin.ts ga «EPIPE» bo'limidagi ishlovchini qo'shing va valyuta kurs all -f csv | head -1 hamda katta oraliqli valyuta tarix USD --dan 2025-01-01 -f csv | head -1 ni avval ishlovchisiz, keyin ishlovchi bilan sinang. Exit kodni echo ${PIPESTATUS[0]} (Git Bash) bilan ko'ring. Bu tajriba — kanonda bunday ishlovchi yo'q, shuning uchun commit qilmang.
Yechim
Kutilgan manzara: kichik chiqishda (kurs all) farq yo'q — 74 qator head yopilishidan oldin yozib bo'linadi (biz shunday ko'rdik, exit 0). Katta tarix da ishlovchisiz EPIPE bo'lishi mumkin: pipeline xatoni main() ga qaytaradi va siz Xato: …EPIPE… va exit 1 ko'rasiz. Ishlovchi bilan — jim chiqish, exit 0. Bu holat kanonda sinalmagan — tajriba natijangizni yozib qo'ying. tarix tarmoq talab qiladi (oflayn rejimda faqat keshdagi kunlar bor).
11. Real ishda
- clig.dev — "Command Line Interface Guidelines", CLI kelishuvlari bo'yicha ochiq qo'llanma. Undagi qoidalar (stdout/stderr, exit kod,
--help,NO_COLOR) shu darsdagi bilan bir xil. - CI va skriptlar: GitHub Actions har qadamning exit kodiga qaraydi — 0 bo'lmasa to'xtaydi. Noto'g'ri exit kod — "yashil, lekin buzilgan" pipeline.
- Kasb asboblari:
gh,vercel,prisma,eslint— hammasi shu anatomiyada. Ularning--helpiga endi boshqa ko'z bilan qaraysiz: qaysi kelishuvni qanday bajargan. - Intervyu: "stdout va stderr farqi?", "exit kod 2 nimani bildiradi?", "nega
process.exit()emas,exitCode?" — CLI va DevOps lavozimlarida tez-tez so'raladi.
Xulosa
- CLI'ning uchta chiqish kanali: stdout — natija, stderr — xabarlar, exit kod — skript uchun signal.
- Shebang
#!/usr/bin/env nodeLinux/macOS uchun, Windows'da npm.cmd/.ps1shim yozadi; shebang'sizbinbuziladi. parseArgs+strict: true: noma'lum bayroq xato;-5kabi manfiy son uchun--.- Katta chiqishni
| headga ulagandaEPIPE—process.stdout.on("error")bilan jim chiqish. - Exit kodlar: 0, 1 (ish vaqti), 2 (foydalanish), 130 (Ctrl+C);
process.exitCode—process.exit()emas. - Kelishuvlar:
--helpstdout'ga,--versionbitta qator, sozlash ustuvorligi bayroq → env → fayl → sukut.
Keyingi dars: Commander bilan buyruqlar tizimi — sub-buyruqlar, avtomatik yordam va tekshiruvni kutubxonaga topshirish: valyuta ning Commander nusxasi va nega u kanonga kirmadi.
Manbalar
- Node.js hujjati —
util.parseArgs: https://nodejs.org/api/util.html#utilparseargsconfig - Node.js hujjati — process:
exitCode,exit(), stdout/stderr eslatmasi: https://nodejs.org/api/process.html - npm hujjati —
package.jsonbinmaydoni: https://docs.npmjs.com/cli/v11/configuring-npm/package-json#bin - npm hujjati —
npm link: https://docs.npmjs.com/cli/v11/commands/npm-link - Command Line Interface Guidelines: https://clig.dev
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!