Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Nega npm'ga .ts emas, JS chiqariladi
- 2.1 Tajriba: .ts bin'li paket
- 2.2 Build zanjiri
- 2.3 tsconfig.build.json: faqat build uchun sozlama
- 3. dist/ ichida nima bor
- 3.1 Uch xil fayl
- 3.2 .d.ts ichiga qarash
- 3.3 tsc dan boshqa yo'l: tsup va tsdown
- 4. npm pack: qadoqni ochib ko'rish
- 4.1 Arxivni yig'ish
- 4.2 Boshqa papkaga o'rnatish
- 4.3 Ikki xil sinov: buyruq va kutubxona
- 5. Nom, scope va --access public
- 5.1 Nom band bo'lmasin
- 5.2 Biz ishga tushirdik: scope'li nom
- 5.3 --access public
- 6. Haqiqiy nashr: hisob, 2FA va trusted publishing
- 6.1 Qo'lda nashr
- 6.2 Trusted publishing (OIDC)
- 7. Versiyalar hayoti: npm version, changesets, deprecate
- 7.1 npm version
- 7.2 changesets
- 7.3 Xato versiya chiqdi: deprecate, unpublish emas
- 8. Nashrdan oldin avtomatik tekshiruv
- 8.1 publint
- 8.2 Are The Types Wrong?
- 9. CLI qadami: holat 12 ni qadoqlab sinash
- 10. Ko'p uchraydigan xatolar
- 11. Mashqlar
- 1-mashq (oson): arxivda nima bor?
- 2-mashq (o'rta): nashrga tayyormi?
- 3-mashq (qiyin): o'z paketingizni qadoqlang
- 4-mashq: CLI qadami
- 12. Real ishda
- Xulosa
- Manbalar
npm paket nashr qilish: build, .d.ts, npm pack va scope bilan
Qisqacha: npm'ga manba kod emas, tayyor JS chiqariladi:
tscsrc/*.tsdandist/ga.js,.d.ts(tiplar) va.mapyozadi. Nashrdan oldin paketninpm packbilan arxivga yig'ib, boshqa papkaga o'rnatib sinaysiz — foydalanuvchi aynan shu arxivni oladi. Nom band bo'lmasligi uchun scope ishlatiladi (@login/valyuta, birinchi nashr--access publicbilan). Haqiqiynpm publishuchun hisob, 2FA yoki trusted publishing kerak; noto'g'ri versiyani o'chirish emas,npm deprecateqilinadi.
Bu darsda
.tspaket neganode_modulesichida ishlamasligini haqiqiy xato bilan ko'rasiz va build zanjirini tushuntira olasiz.dist/ichidagi.js,.d.ts,.mapfayllar nima uchun kerakligini bilasiz.- Paketni
npm packbilan yig'ib, boshqa loyihaga o'rnatib,npxvaimportbilan sinay olasiz. - Scope,
--access public,publishConfig, 2FA, trusted publishing (OIDC),npm deprecateva changesets nima ekanini bilasiz. publintva "Are The Types Wrong?" vositalari bilan paketni nashrdan oldin tekshira olasiz.
Oldin bilishingiz kerak: package.json IV: kirish nuqtalari, Semver va versiya diapazonlari, Ta'minot zanjiri xavfsizligi, CJS va ESM birga, Workspaces va monorepo asoslari.
1. Nega bu kerak?
O'tgan darsda valyuta ni ikki paketga bo'lib ko'rdik va bitta paket qoldirdik. CJS va ESM darsida esa unga bin, exports va files qo'shgan edik. Endi valyuta — boshqalar o'rnatadigan paket bo'lishga tayyor. Do'stingiz Toshkentdagi kompyuterida npx @login/valyuta 100 USD yozsa, unga sizning kodingiz kelishi kerak.
Bu yerda yangi muammo paydo bo'ladi. Sizning kompyuteringizda node src/bin.ts ishlaydi. Do'stingizning kompyuterida esa — ishlamasligi mumkin. Foydalanuvchi src/ ni emas, siz yig'gan arxivni oladi. Arxivga nima tushdi, u qayerda ochildi, qaysi Node'da ishga tushdi — bularning hammasi sizning qo'lingizdan chiqadi.
O'xshatish: non zavodi. Xamir (manba kod) zavodda qoladi. Do'konga esa yopilgan, qadoqlangan, yorlig'i yopishtirilgan non boradi. Qadoqni ochib ko'rmasdan do'konga jo'natish — xato. Bu darsda biz "qadoq" ni (.tgz arxiv) yasaymiz, ochib tekshiramiz, keyin qanday jo'natilishini o'rganamiz.
Bir narsani oldindan halol aytamiz. Kanon tajribasida haqiqiy npmjs.com ga nashr qilinmadi: buning uchun hisob va kalit kerak, kurs esa birovning nomidan hisob ochmaydi. Biz hamma narsani npm pack va npm publish --dry-run bilan sinadik. Haqiqiy npm publish ni siz o'zingiz, o'z hisobingiz bilan qilasiz — buyruqlari pastda.
2. Nega npm'ga .ts emas, JS chiqariladi
2.1 Tajriba: .ts bin'li paket
Workspaces darsida workspace ichidagi .ts fayl type stripping bilan ishladi. Kanon yana bir tajriba qildi: bin to'g'ridan-to'g'ri cli.ts ga qaratilgan paketni npm pack qilib, boshqa papkaga o'rnatdi. Paket ichidagi fayl node_modules da yotibdi. Natija:
Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]: Stripping types is currently unsupported for files under node_modules, for "file:///C:/Users/…/ilova/node_modules/tsbin/cli.ts"Tarjimasi: "node_modules ostidagi fayllar uchun tiplarni o'chirish hozircha qo'llab-quvvatlanmaydi". Bu tasodif emas, Node'ning ataylab qilingan qarori. Paket muallifi qaysi TypeScript sozlamalari bilan yozganini Node bilmaydi. Shuning uchun begona .ts ni bajarmaydi.
Workspace'da nega ishladi? Chunki u yerda node_modules/@valyuta/core — Windows'da junction, ya'ni haqiqiy fayl node_modules dan tashqarida yotardi. Node haqiqiy yo'lga qaraydi.
Xulosa bitta: npm'ga faqat JS chiqariladi. TypeScript — sizning ish quroliz, foydalanuvchiga tayyor mahsulot boradi.
2.2 Build zanjiri
Butun yo'lni bitta rasmda ko'ring. Chapda — sizning kompyuteringiz, o'ngda — foydalanuvchiniki:
flowchart LR
A["src/*.ts"] -->|tsc| B["dist/: .js .d.ts .map"]
B -->|npm pack| C["login-valyuta-0.2.0.tgz"]
C -->|npm publish| D[("npm registr")]
D -->|npm i| E["node_modules/@login/valyuta"]
C -.->|"sinov: npm i ../x.tgz"| ENuqtali chiziqqa e'tibor bering: biz registrni chetlab o'tamiz va arxivni to'g'ridan o'rnatamiz. Foydalanuvchi oladigan narsa baribir o'sha arxiv — shuning uchun sinov halol.
2.3 tsconfig.build.json: faqat build uchun sozlama
valyuta da ikkita tsconfig bor. Asosiysi (tsconfig.json) — tekshiruv uchun: noEmit: true, allowImportingTsExtensions: true. Build uchun alohida fayl uni kengaytiradi:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"allowImportingTsExtensions": false,
"rewriteRelativeImportExtensions": true,
"rootDir": "src",
"outDir": "dist",
"declaration": true,
"sourceMap": true
},
"include": ["src"]
}| Kalit | Nima qiladi |
|---|---|
rewriteRelativeImportExtensions |
import "./cli.ts" ni JS'da "./cli.js" ga o'zgartiradi |
rootDir / outDir |
src/kurs.ts → dist/kurs.js (papka tuzilmasi saqlanadi) |
declaration |
har .js yonida .d.ts — tiplar |
sourceMap |
.js.map — xato izi .ts qatoriga ishora qiladi |
include: ["src"] |
testlar (test/) build'ga tushmaydi |
package.json da ikkita skript bu faylni ishlatadi:
{
"build": "tsc -p tsconfig.build.json",
"prepack": "npm run build"
}prepack — lifecycle skript (scripts chuqur). U npm pack va npm publish dan oldin avtomatik ishlaydi. Natijada eski dist/ ni nashr qilib yuborish xavfi yo'qoladi: arxiv har safar yangi build'dan yig'iladi.
Tekshirib ko'ring:
prepackbo'lmasa va sizsrc/kurs.tsni o'zgartirib, darholnpm publishqilsangiz, foydalanuvchiga nima boradi?
Javob
Eski kod. npm publish dist/ papkasini qanday bo'lsa, shunday arxivga soladi — oxirgi npm run build qachon bo'lgan bo'lsa, o'sha holat. src/ dagi o'zgarish foydalanuvchiga bormaydi. prepack aynan shu xatoga qarshi.
3. dist/ ichida nima bor
3.1 Uch xil fayl
Biz holat 12 ni scratch papkada build qildik. dist/ ichida har modul uchun uchta fayl chiqdi:
bin.d.ts bin.js bin.js.map
cli.d.ts cli.js cli.js.map
index.d.ts index.js index.js.map
kurs.d.ts kurs.js kurs.js.map
manba.d.ts manba.js manba.js.map.js— Node bajaradigan kod. Tiplar o'chirilgan,./cli.tsimportlari./cli.jsga aylangan..d.ts— tip e'loni fayli (declaration file): faqat tiplar, kod yo'q. O'xshatish — dori qutisidagi yo'riqnoma: dorining o'zi emas, lekin qanday ichishni aytadi. Foydalanuvchining muharriri shu fayldan avtomatik to'ldirish va xatolarni oladi..js.map— source map (Source map'lar). Xato izidist/kurs.js:40emas,src/kurs.ts:52ni ko'rsatishi uchun.
dist/bin.js ning birinchi qatori — shebang. tsc uni src/bin.ts dan o'zgartirmasdan ko'chiradi:
#!/usr/bin/env node
// Kirish nuqtasi (package.json "bin"): signal, exit kod. Mantiq — cli.ts da
import { main } from "./cli.js";Shebang'siz bin fayl Linux va macOS'da shell skript deb bajariladi. Workspaces tajribasida aynan shunday xato topilgan edi (import: command not found).
3.2 .d.ts ichiga qarash
dist/kurs.d.ts ning boshi:
export interface Kurs {
kod: string;
nomi: string;
nominal: number;
kurs: number;
farq: number;
sana: string;
}
export declare const SOM: Kurs;
export declare function konvert(miqdor: number, dan: Kurs, ga: Kurs): number;
/** 11903.15 → "11 903.15" (minglik — bo'sh joy, kasr — nuqta, 2 xona) */
export declare function sonniYoz(n: number, xona?: number): string;declare — "bu nom mavjud, uning kodi boshqa joyda (.js da)". JSDoc izohlari ham saqlanadi: foydalanuvchi sonniYoz ustiga sichqonchani olib borsa, shu izohni ko'radi.
Bir qiziq joy: dist/index.d.ts ichida import yo'li "./kurs.ts" bo'lib qoldi — rewriteRelativeImportExtensions faqat .js ni o'zgartiradi. Bu xato emasmi? Biz tekshirdik: o'rnatilgan paketni boshqa loyihada tsc 6.0.3 bilan tekshirdik. TypeScript ./kurs.ts ni ./kurs.d.ts ga moslab topdi va tip xatosini to'g'ri ushladi:
ishlat.ts(6,9): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.Bu konvert("100", usd, SOM) qatoriga berilgan xato. Demak tiplar foydalanuvchiga yetib boradi.
Tekshirib ko'ring: Foydalanuvchi oddiy JavaScript yozadi, TypeScript ishlatmaydi.
.d.tsunga foyda beradimi?
Javob
Ha. VS Code JS fayllarda ham .d.ts dan foydalanadi: avtomatik to'ldirish, parametr nomlari, JSDoc izohlari ko'rinadi. Tip xatolarini esa faqat // @ts-check yoki TypeScript bilan ko'radi.
3.3 tsc dan boshqa yo'l: tsup va tsdown
Kutubxonalar ko'pincha tsc o'rniga bundler asosidagi build vositasini ishlatadi. Ular bir nechta faylni bitta faylga yig'adi, ESM va CJS ni birdaniga chiqara oladi, .d.ts ni ham yig'adi:
| Vosita | 2026-10-23 holatiga versiya | Asosi |
|---|---|---|
tsc |
typescript 6.0.3 | TypeScript kompilyatori, bundle qilmaydi |
| tsup | 9.0.0 | esbuild |
| tsdown | 0.23.1 | Rolldown (bundlerlar 2026) |
valyuta uchun tsc yetarli: prod bog'liqlik 0, faqat ESM, fayllar kichik. Ikki formatli (dual) paket chiqarish kerak bo'lsa — tsup yoki tsdown tanlanadi. Lekin dual package hazard ni eslang: ikki nusxa — ikki xil holat. Node 24 da CJS loyiha ESM paketni require qila oladi (CJS va ESM birga), shuning uchun yangi paket uchun faqat ESM chiqarish odatiy tanlovga aylanmoqda. Bu vositalarni biz kanonda o'rnatmadik — versiyalar npm view dan.
4. npm pack: qadoqni ochib ko'rish
4.1 Arxivni yig'ish
npm pack — npm publish ning "jo'natmaydigan" egizagi. U paketni aynan nashr qilinadigan .tgz arxivga yig'adi va papkada qoldiradi. Kanon natijasi (holat 12, nom hali valyuta):
npm packfilename: valyuta-0.2.0.tgz
package size: 10.1 kB
unpacked size: 40.9 kB
shasum: 01ecaa4b3508b9ef9c0e95e5d64117a3ab05f28e
integrity: sha512-M9uPtrCmC7LFx[...]rYI0K7hGn8mhg==
total files: 17Chiqishdan oldin prepack ishlaydi — tsc build qiladi. 17 fayl: dist/ dagi 15 ta, fixture va package.json. src/, test/, tsconfig* yo'q — buni files: ["dist", "fixtures"] ta'minlaydi (kirish nuqtalari).
shasum va integrity — arxivning hash'i. npm o'rnatishda aynan shu bilan arxiv yo'lda buzilmaganini tekshiradi (lock-fayllar).
4.2 Boshqa papkaga o'rnatish
Endi foydalanuvchi bo'lamiz. Butunlay boshqa papka, yangi loyiha:
mkdir ilova && cd ilova
npm init -y
npm i ../valyuta/valyuta-0.2.0.tgzadded 1 package, and audited 2 packages in 2s
found 0 vulnerabilities"1 package" — valyuta ning prod bog'liqligi yo'q. Uni o'rnatgan odam boshqa hech narsa yuklamaydi. Bu — kanonning ataylab qilingan qarori.
npm Windows'da node_modules/.bin/ ga bitta buyruq uchun uchta "shim" (kichik ishga tushiruvchi fayl) yozadi:
valyuta
valyuta.cmd
valyuta.ps1Birinchisi — Git Bash va Linux uchun, .cmd — oddiy Windows terminali uchun, .ps1 — PowerShell uchun. Linux va macOS'da esa bitta symlink bo'ladi (hujjat bo'yicha; kanonda Linux sinalmagan).
4.3 Ikki xil sinov: buyruq va kutubxona
Paketning ikki yuzi bor — CLI (bin) va kutubxona (exports). Ikkalasini ham sinaymiz:
VALYUTA_OFFLINE=1 npx valyuta 100 USD100.00 USD = 1 190 315.00 UZSnode -e 'import("valyuta").then((m) => console.log(Object.keys(m)))'Biz ishga tushirdik (scope'li nom bilan, keyingi bo'limda) — 9 ta eksport keldi:
API, SOM, apidanOl, birlikKursi, fixturedanOl, konvert, royxatniOqi, sonniYoz, yozuvniOqiCommonJS loyiha ham ishlata oladimi? eski.cjs faylida require bilan sinadik:
function 9typeof v.konvert — function, eksportlar soni — 9. Node 24 da require(esm) sukut bo'yicha yoqilgan (CJS va ESM birga). bin.ts dagi top-level await kutubxona kirishiga (index.ts) tushmagani uchun shunday bo'ldi.
Diqqat: sinovni loyihaning o'z papkasida qilmang. U yerda
src/,node_modules/va boshqa fayllar bor — arxivda yo'q fayl tasodifan topilib, "ishlayapti" deb aldaydi. Faqat boshqa papka halol javob beradi.
Tekshirib ko'ring:
filesdan"fixtures"ni olib tashlasangiz,npm packqancha fayl ko'rsatadi vaVALYUTA_OFFLINE=1 npx valyuta 100 USDnima bo'ladi?
Javob
16 fayl — fixture arxivga tushmaydi. Offline rejim fixture faylni o'qiydi, u yo'q — ENOENT xatosi bilan yiqiladi. Sizning loyihangizda fayl turgani uchun bu xato faqat boshqa papkadagi sinovda ko'rinadi.
5. Nom, scope va --access public
5.1 Nom band bo'lmasin
npm'da nom — global va yagona: bitta nom, bitta egasi. Kanon 2026-10-23 da tekshirdi:
npm view valyutanpm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/valyuta - Not found404 — nom bo'sh. Lekin kursni minglab odam o'qiydi va hammasi bitta valyuta ni ola olmaydi. Shuning uchun sizga scope tavsiya qilinadi: @login/valyuta, bunda login — npmjs.com dagi foydalanuvchi nomingiz. Scope'ni .npmrc darsida ko'rgansiz: @ bilan boshlanadigan nomlar fazosi. Har foydalanuvchining scope'i o'ziniki — u yerda nom to'qnashuvi bo'lmaydi.
5.2 Biz ishga tushirdik: scope'li nom
Holat 12 nusxasida nomni o'zgartirdik va arxiv yig'dik:
npm pkg set name=@login/valyuta
npm packnpm notice name: @login/valyuta
npm notice version: 0.2.0
npm notice filename: login-valyuta-0.2.0.tgz
npm notice package size: 10.1 kB
npm notice total files: 17Arxiv nomida @ va / yo'q — fayl nomida ular bo'lmaydi, shuning uchun login-valyuta. Hajm o'sha, lekin shasum boshqa chiqdi (719e41b8…) — package.json ichidagi nom o'zgardi.
5.3 --access public
Scope'li paket sukut bo'yicha yopiq (restricted) hisoblanadi. Yopiq paket — npm'ning pullik imkoniyati. Bepul hisobda birinchi nashrni ochiq qilish kerak. Biz --dry-run bilan ikkalasini solishtirdik (bo'sh .npmrc bilan — hech qanday hisob ulanmagan):
npm publish --dry-runnpm warn publish This command requires you to be logged in to https://registry.npmjs.org/ (dry-run)
npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)
+ @login/valyuta@0.2.0npm publish --dry-run --access publicnpm warn publish This command requires you to be logged in to https://registry.npmjs.org/ (dry-run)
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access (dry-run)
+ @login/valyuta@0.2.0Farq — default access va public access. Birinchi qator: "bu buyruq uchun tizimga kirgan bo'lishingiz kerak" — dry-run baribir ishladi, lekin haqiqiy nashr shu joyda to'xtardi.
Har safar --access public yozmaslik uchun uni package.json ga yozib qo'yish mumkin:
{
"publishConfig": {
"access": "public"
}
}publishConfig — faqat nashr paytida qo'llanadigan sozlamalar. Unga tag yoki boshqa registry ham yozish mumkin.
Tekshirib ko'ring: Nima uchun scope'siz
valyutauchun--access publickerak emas edi?
Javob
Scope'siz paketlar har doim ochiq — yopiq bo'la olmaydi. "Yopiq" tanlovi faqat scope'li paketlarda bor, shuning uchun ularda sukut bo'yicha xavfsiz tomoni (yopiq) olinadi.
6. Haqiqiy nashr: hisob, 2FA va trusted publishing
Bu bo'lim hujjat bo'yicha — biz bajarmadik. Siz o'z hisobingiz bilan qilasiz.
6.1 Qo'lda nashr
npm login
npm publish --access publicnpm login brauzerni ochadi, siz npmjs.com da kirasiz. Hisobda 2FA (ikki bosqichli tasdiq) yoqilgan bo'lsa, nashrda qo'shimcha tasdiq so'raladi. 2FA — parolingiz o'g'irlansa ham, paketingizga zararli versiya chiqarib bo'lmasligi uchun.
Nega bu muhim? Ta'minot zanjiri darsida 2025-yil "Shai-Hulud" hujumini ko'rgansiz: o'g'irlangan npm tokenlar orqali yuzlab paketga zararli versiya chiqarildi. Token — parol o'rnida ishlatiladigan maxfiy satr: kim uni qo'lga kiritsa, sizning nomingizdan nashr qiladi. Hujumdan keyin GitHub (npm egasi) nashr qoidalarini qattiqlashtirdi:
| Sana | Nima o'zgardi (GitHub e'lonlari bo'yicha) |
|---|---|
| 2025-09-22 | reja e'lon qilindi: nashr faqat 2FA bilan, qisqa muddatli token yoki trusted publishing orqali |
| 2025-10 / 11 | yozish huquqli yangi tokenlar — sukut 7 kun, ko'pi bilan 90 kun; eski (classic) token yaratish o'chirildi |
| 2025-12-09 | hamma classic tokenlar butunlay bekor qilindi; npm login endi 2 soatlik seans beradi |
Bu qoidalar hali ham o'zgarib turadi (2026-10 holatiga). Nashrdan oldin npm hujjatini o'qing — kursdagi jadval faqat yo'nalishni ko'rsatadi.
6.2 Trusted publishing (OIDC)
Eng xavfsiz yo'l — kompyuteringizda umuman token saqlamaslik. Trusted publishing (ta'minot zanjiri darsida tanishgansiz) quyidagicha ishlaydi:
- npmjs.com da paket sozlamasiga yozasiz: "bu paketni faqat
login/valyutarepozitoriysidaginashr.ymlworkflow nashr qila oladi". - GitHub Actions ishga tushganda GitHub o'sha workflow uchun qisqa muddatli imzolangan guvohnoma beradi (OIDC — OpenID Connect, "men aynan shu repodagi shu workflow'man" degan raqamli hujjat).
- npm guvohnomani tekshiradi va bitta nashrga ruxsat beradi. Saqlanadigan, o'g'irlanadigan token yo'q.
Bonus: shunday nashr qilingan paketga npm avtomatik provenance (kelib chiqish guvohnomasi) qo'shadi — "bu arxiv aynan shu commit'dan, shu workflow'da yig'ilgan" degan ochiq yozuv. Shart: repozitoriy ham, paket ham ochiq (public) bo'lishi kerak. Trusted publishing'siz ham CI'da npm publish --provenance bilan shu yozuvni olish mumkin. Workflow'ning kerakli qismi (npm hujjatidagi namuna asosida; bizda push qilinmagan va ishlamagan):
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm publish --access publicid-token: write — GitHub'ga OIDC guvohnomasini yaratishga ruxsat. npm hujjatiga ko'ra trusted publishing npm CLI 11.5.1+ va Node 22.14.0+ ni talab qiladi; bizning Node 24.21.0 va npm 11.19.0 mos. Ishlaydigan joylar: GitHub Actions, GitLab CI/CD, CircleCI (bulutdagi runner'lar; o'z serveringizdagi runner hali yo'q). Trusted publishing yoqilgach, npm paket sozlamasida tokenli nashrni butunlay taqiqlashni tavsiya qiladi ("Require two-factor authentication and disallow tokens").
7. Versiyalar hayoti: npm version, changesets, deprecate
7.1 npm version
Har nashr — yangi versiya: bir versiyani ikki marta nashr qilib bo'lmaydi. Semver qoidasi bo'yicha raqamni npm version oshiradi:
npm version patch --no-git-tag-versionv0.2.1--no-git-tag-version — faqat package.json ni o'zgartiradi. U bo'lmasa, npm git commit va v0.2.1 tegini ham yaratadi (repo toza bo'lishi shart).
7.2 changesets
Bir necha odam ishlaydigan loyihada "qaysi o'zgarish qaysi versiyaga" savoli murakkablashadi. changesets (@changesets/cli, 2026-10-23 holatiga 3.0.3) har PR'da kichik markdown fayl qoldirishni so'raydi: "patch: kesh xatosi tuzatildi". Nashr paytida u fayllarni yig'ib, versiyani oshiradi va CHANGELOG.md yozadi. Monorepo'larda ayniqsa ko'p ishlatiladi. Bizning bitta paketli valyuta uchun npm version yetarli — changesets kanonda ishlatilmadi.
7.3 Xato versiya chiqdi: deprecate, unpublish emas
Faraz qiling, 0.2.1 da konvert noto'g'ri hisoblaydi. Uni o'chirib tashlash kerakmi? Yo'q. npm unpublish ni qattiq cheklaydi. Hujjat bo'yicha birinchi 72 soatda o'chirish mumkin. Keyin — faqat paketga hech kim bog'lanmagan, o'tgan haftada 300 dan kam yuklangan va egasi bitta bo'lsa. Sababi — 2016-yildagi left-pad voqeasi: bitta kichik paket o'chirilgani minglab loyiha build'ini buzgan edi.
To'g'ri yo'l — tuzatilgan 0.2.2 ni chiqarish va eskisini deprecate (eskirgan deb belgilash) qilish:
npm deprecate @login/valyuta@0.2.1 "xato; 0.2.2 ga yangilang"Shundan keyin 0.2.1 ni o'rnatgan har kishi npm warn deprecated ogohlantirishini ko'radi. Paket o'chmaydi, lekin odamlar ogohlantiriladi.
8. Nashrdan oldin avtomatik tekshiruv
8.1 publint
publint — package.json va arxiv tarkibini tekshiradigan vosita: exports dagi fayl arxivda bormi, types to'g'ri joydami. Holat 12 nusxasida ishga tushirdik:
npx publint@0.3.25Running publint v0.3.25 for @login/valyuta...
Packing files with `npm pack`...
Linting...
All good!8.2 Are The Types Wrong?
@arethetypeswrong/cli (attw) tiplarni turli moduleResolution rejimlarida tekshiradi. Natija qiziqroq chiqdi:
npx @arethetypeswrong/cli@0.18.5 --pack . --format table-flipped"@login/valyuta" node10: 💀 Resolution failed
"@login/valyuta" node16 (from CJS): ⚠️ ESM (dynamic import only)
"@login/valyuta" node16 (from ESM): 🟢 (ESM)
"@login/valyuta" bundler: 🟢(Asl chiqish — chiziqli jadval; telefon uchun qatorlarga ajratdik.) Ikki ogohlantirishni o'qiymiz:
- node10 — TypeScript'ning eski
moduleResolution: "node"rejimi. Uexportsni bilmaydi va top-levelmain/typesqidiradi. Bizda ular yo'q. Bunday eski sozlamali loyihalarvalyutatiplarini topmaydi. - node16 from CJS — attw "CJS loyiha bu paketni faqat
import()bilan ola oladi" deydi. Lekin biz yuqorida Node 24 darequireishlaganini ko'rdik. Farq shunda: attw tiplar dunyosidagi eski qoidani tekshiradi, Node 24 esarequire(esm)ni allaqachon biladi.
Biz bu ikkisini qabul qildik: paket engines.node >=24 va zamonaviy TypeScript loyihalar uchun. Eski loyihalarni qo'llash kerak bo'lsa — main va types maydonlari yoki dual build (tsup/tsdown) kerak bo'lardi. Muhimi — qaror ongli, tasodifiy emas.
9. CLI qadami: holat 12 ni qadoqlab sinash
Bu darsda kod o'zgarmaydi — holat 12 (CJS va ESM birga darsida commit qilingan) ustida ishlaymiz. Bitta narsa esa doimiy o'zgaradi: paket nomi. Shu darsdan boshlab loyihangiz @login/valyuta deb ataladi.
| Nima | Oldin | Shu darsdan keyin |
|---|---|---|
package.json → "name" |
valyuta |
@login/valyuta |
terminal buyrug'i (bin kaliti) |
valyuta |
valyuta — o'zgarmaydi |
| self-reference importi | import("valyuta") |
import("@login/valyuta") |
| arxiv nomi | valyuta-0.2.0.tgz |
login-valyuta-0.2.0.tgz |
Kurs matnidagi kanon chiqishlarida keyin ham valyuta nomi ko'rinadi — kanon loyiha shu nom bilan o'lchangan. Sizda @login/valyuta chiqsa, bu to'g'ri. Nom o'zgarishini hozir alohida commit qilmang — u holat 18 commiti bilan birga ketadi (path va os darsida).
valyutapapkasida:npm pkg set name=@login/valyuta(logino'rniga — o'z npm nomingiz), so'ngnpm pack. 17 fayl, taxminan 10.1 kB chiqishi kerak..gitignoreda*.tgzborligini tekshiring (kanonda bor) — arxiv repoga tushmasin.- Boshqa papkada:
npm init -y,npm i ../valyuta/login-valyuta-0.2.0.tgz. VALYUTA_OFFLINE=1 npx valyuta 100 USD→100.00 USD = 1 190 315.00 UZS.node -e 'import("@login/valyuta").then((m) => console.log(Object.keys(m)))'→ 9 ta nom.npm publish --dry-run --access public— "public access" qatorini ko'ring.
Haqiqiy nashrni hozir qilmang. Paket hali 0.2.0 — kesh, bayroqlar va README keyingi darslarda qo'shiladi. Yakuniy 1.0.0 va tarqatish — CLI'ni tarqatish darsida.
10. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING |
Paket .ts bilan nashr qilingan |
Build qiling, bin/exports → dist/*.js |
| O'rnatilgan paketda eski kod | dist/ qayta yig'ilmagan |
prepack: npm run build |
ENOENT faqat foydalanuvchida |
Fayl files ro'yxatida yo'q |
npm pack --dry-run ni o'qing |
E402 Payment Required |
Scope'li paket yopiq nashr qilinmoqda | --access public yoki publishConfig |
E403 … cannot publish over |
Bu versiya allaqachon nashr qilingan | npm version patch |
E404 scope'li nomda |
login sizning npm nomingiz emas |
Scope = hisob yoki tashkilot nomi |
| Tiplar topilmaydi | exports da types yo'q yoki oxirida |
types — har shartning birinchisi |
bin Linux'da shell xatosi beradi |
Shebang yo'q | #!/usr/bin/env node |
E402, E403 xabarlari — npm hujjatidan; biz ularni haqiqiy registrda ko'rmadik (nashr qilmadik).
11. Mashqlar
1-mashq (oson): arxivda nima bor?
npm pack chiqishiga qarab javob bering.
- Holat 12 arxivida nechta fayl bor?
dist/dagi qaysi fayl turi faqat tiplarni saqlaydi?.npm packdan oldin avtomatik build qiladigan skript nomi:- Scope'li paketni bepul hisobda nashr qilish uchun bayroq:
--access
Yechim
- 17 — 15 ta
dist/fayli, fixture vapackage.json. - d.ts — tip e'loni fayli; kod yo'q.
- prepack —
npm packvanpm publishdan oldin ishlaydi. - public — scope'li paket sukut bo'yicha yopiq.
2-mashq (o'rta): nashrga tayyormi?
package.json obyektini tekshiradigan tekshirPaket(pkg) funksiyasini yozing. U muammolar ro'yxatini qaytarsin:
private: true→"private: nashr qilinmaydi";versionsemver emas (X.Y.Z, raqamlar) →"version: semver emas";- nom
@bilan boshlanadi, lekinpublishConfig.access"public"emas →"scope: --access public kerak"; filesyo'q →"files: hamma fayl arxivga tushadi";exports["."]obyekt bo'lsa va uning birinchi kalititypesbo'lmasa →"exports: types birinchi bo'lsin".
Muammo yo'q bo'lsa — bo'sh massiv. Satr tekshiruvi uchun muntazam ifodalar kerak bo'ladi, obyekt kalitlari tartibi uchun Object.keys (Object.* metodlari).
Yechim
function tekshirPaket(pkg) {
const muammolar = [];
if (pkg.private === true) {
muammolar.push("private: nashr qilinmaydi");
}
if (!/^\d+\.\d+\.\d+$/.test(pkg.version ?? "")) {
muammolar.push("version: semver emas");
}
const ochiq = pkg.publishConfig?.access === "public";
if (pkg.name?.startsWith("@") && !ochiq) {
muammolar.push("scope: --access public kerak");
}
if (!Array.isArray(pkg.files)) {
muammolar.push("files: hamma fayl arxivga tushadi");
}
const nuqta = pkg.exports?.["."];
if (nuqta && typeof nuqta === "object") {
if (Object.keys(nuqta)[0] !== "types") {
muammolar.push("exports: types birinchi bo'lsin");
}
}
return muammolar;
}
const yaxshi = {
name: "@login/valyuta",
version: "0.2.0",
files: ["dist", "fixtures"],
publishConfig: { access: "public" },
exports: {
".": { types: "./dist/index.d.ts", default: "./dist/index.js" },
},
};
const yomon = {
name: "@login/valyuta",
version: "1.0",
private: true,
exports: {
".": { default: "./dist/index.js", types: "./dist/index.d.ts" },
},
};
console.log(tekshirPaket(yaxshi));
for (const m of tekshirPaket(yomon)) console.log(m);Konsolda:
[]
private: nashr qilinmaydi
version: semver emas
scope: --access public kerak
files: hamma fayl arxivga tushadi
exports: types birinchi bo'lsinRegex 1.0.0-beta.1 kabi prerelease versiyalarni rad etadi — haqiqiy loyihada semver paketining valid() funksiyasi ishlatiladi. exports kalitlari tartibi muhim: Node va TypeScript shartlarni yuqoridan pastga o'qiydi, birinchi mosi yutadi (kirish nuqtalari).
3-mashq (qiyin): o'z paketingizni qadoqlang
Kichik kutubxona yarating: @login/somchi — bitta funksiya somgaYoz(n) (1190315 → "1 190 315 so'm"). TypeScript'da yozing, tsconfig.build.json bilan dist/ ga build qiling (declaration: true), exports da types birinchi, files: ["dist"], prepack skripti. npm pack qiling, boshqa papkaga o'rnating va node -e bilan import qilib sinang. Oxirida npx publint va npx @arethetypeswrong/cli --pack . natijasini o'qing.
Yechim
src/index.ts:
export function somgaYoz(n: number): string {
const butun = Math.round(n).toString();
return `${butun.replace(/\B(?=(\d{3})+(?!\d))/g, " ")} so'm`;
}
console.log(somgaYoz(1190315)); // 1 190 315 so'mconsole.log faqat shu darsda tekshirish uchun — haqiqiy kutubxona faylida bo'lmaydi (yon ta'sirsiz import, CJS va ESM birga).
package.json ning muhim qismi:
{
"name": "@login/somchi",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": ["dist"],
"publishConfig": { "access": "public" },
"scripts": {
"build": "tsc -p tsconfig.build.json",
"prepack": "npm run build"
}
}npm pack → login-somchi-0.1.0.tgz, ichida dist/index.js, dist/index.d.ts va package.json. Boshqa papkada npm i ../somchi/login-somchi-0.1.0.tgz va:
node -e 'import("@login/somchi").then((m) => console.log(
m.somgaYoz(5000)))'Kutilgan natija: 5 000 so'm. publint — All good!; attw esa valyuta dagidek node10 va node16 (from CJS) ustunlarida ogohlantiradi (sababi — «Are The Types Wrong?» bo'limida).
4-mashq: CLI qadami
«CLI qadami» bo'limidagi oltita qadamni bajaring va natijani solishtiring: 17 fayl, 100.00 USD = 1 190 315.00 UZS, 9 ta eksport, public access.
Yechim
Natija mos kelmasa, eng ko'p sabab — sinovni valyuta papkasining o'zida qilish yoki npm pack dan keyin nomni o'zgartirish (arxiv eski nom bilan qoladi). Har o'zgarishdan keyin arxivni qayta yig'ing va boshqa papkada qayta o'rnating. .tgz faylni commit qilmang.
12. Real ishda
- Ichki paketlar. Kompaniyalar umumiy kodni (UI komponentlar, API klient, ESLint sozlamasi) ichki registrga yoki GitHub Packages'ga scope bilan nashr qiladi:
@kompaniya/ui. Jarayon aynan shu: build → pack → publish. - CI orqali nashr. Professional loyihalarda hech kim o'z kompyuteridan
npm publishqilmaydi — teg qo'yiladi, GitHub Actions trusted publishing bilan nashr qiladi. CI/CD'ni keyingi qismlarda chuqur o'rganamiz. - Intervyu savollari: "
.d.tsnima va kim yaratadi?", "npm packnega kerak?", "Xato versiyani nashr qilsangiz nima qilasiz?" (javob —deprecateva yangi patch,unpublishemas). - Ochiq kod hissasi. O'zbek tilidagi kichik foydali paket (sana formatlash, telefon raqami tekshiruvi, lotin-kirill o'girish) — portfolio uchun kuchli dalil: kodingizni boshqalar ishlatadi.
Xulosa
- npm'ga JS chiqariladi:
node_modulesichidagi.tsni Node bajarmaydi (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). tsc -p tsconfig.build.json→dist/:.js,.d.ts(tiplar),.map;prepackhar arxivdan oldin build qiladi.npm pack+ boshqa papkaganpm i ../x.tgz— nashrdan oldingi eng halol sinov (17 fayl, 10.1 kB, 1 paket).- Scope (
@login/valyuta) nom to'qnashuvini yo'qotadi; birinchi nashr--access publicyokipublishConfig. - Haqiqiy nashr — 2FA yoki trusted publishing (OIDC, tokensiz, provenance bilan); xato versiya —
npm deprecate. publintva attw nashrdan oldinexports/typesxatolarini ushlaydi; ogohlantirishni o'qib, ongli qaror qiling.
Keyingi dars: fs: uch API shakli — valyuta diskka yozishni o'rganadi: sync, callback va promise shakllari, ENOENT va kesh fayli.
Manbalar
- npm Docs (v11): npm publish, npm pack, npm deprecate, Unpublish policy
- npm Docs — Trusted publishing for npm packages va Generating provenance statements
- GitHub blogi — "Our plan for a more secure npm supply chain" (2025-09-22)
- Node.js 24 hujjati — Modules: TypeScript (type stripping va
node_modulescheklovi) - TypeScript — rewriteRelativeImportExtensions
- publint — https://publint.dev; Are The Types Wrong? — https://arethetypeswrong.github.io
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!