Mundarija (24)
- Bu darsda
- 1. Nega bu kerak?
- 2. PrismaService naqshi
- 2.1 Xizmat — klientning o'zi
- 2.2 Filtr: Prisma xatosi → HTTP
- 2.3 Controller va ulash
- 2.4 Natija
- 3. Lifecycle — qachon nima
- 4. Kanon qarori: PrismaService yo'q
- 4.1 Loyihada nima bor
- 4.2 Nega shunday
- 4.3 Farq xizmat ichida qanday ko'rinadi
- 4.4 O'z loyihangiz uchun: qaysi birini tanlash
- 5. Express'da qanday edi, Nest'da qanday
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): hook va kod
- 2-mashq (o'rta): xato kodini Problem Details'ga aylantirish
- 3-mashq (qiyin): lifecycle tartibi
- 9. Loyiha qadami: o'zgarish yo'q — va nega
- 10. Real ishda
- Xulosa
- Manbalar
Prisma bilan NestJS: PrismaService, lifecycle va Prisma xatolari filtri
Qisqacha: Nest hujjatidagi naqsh:
PrismaService extends PrismaClient— Prisma klienti@Injectablexizmatga aylanadi.onModuleInitda$connect,onModuleDestroyda$disconnect;@GlobalPrismaModuleuni hamma joyga beradi. Prisma 7 da klientga adapter (PrismaPg) beriladi. Prisma xatolarini HTTP'ga@Catch(Prisma.PrismaClientKnownRequestError)filtri aylantiradi:P2002(takror) → 409,P2025(topilmadi) → 404.vazifalar-apibu naqshni olmadi — ombor ish vaqtida tanlanadi va Prisma o'z pool'i bilanOmborModuleichida yashaydi.
Bu darsda
PrismaServicevaPrismaModuleni Prisma 7 adapteri bilan yozasiz.onModuleInit/onModuleDestroyqachon ishlashini haqiqiy chiqishda ko'rasiz.- Prisma xato kodlarini HTTP status'ga aylantiruvchi exception filter yozasiz va adapter bilan
meta.targetneganullekanini bilasiz. - Kanon nega
PrismaServiceklassini kiritmaganini va o'rniga nima borligini tushuntirasiz.
Oldin bilishingiz kerak: Prisma 7: o'rnatish va arxitektura, Prisma prodakshnda, Lifecycle hook'lar, Exception filter'lar, So'rov konteksti: nestjs-cls.
O'tgan darsda config, log va so'rov konteksti qadami commit bo'ldi. Endi ma'lumot qatlami: 27-qismda o'rgangan ORM'lar Nest ichida qanday ulanadi. Bu va keyingi uch dars — tajriba darslari: har birida Nest naqshi, kanon tajribasining haqiqiy natijasi va nega loyiha boshqa yo'lni tanlagani.
1. Nega bu kerak?
27-qismda Prisma 7 bilan PrismaOmbori ni yozgandik (Prisma 7). U yerda klient bitta joyda yaratilardi va ilova yopilganda $disconnect qilinardi — buni server.ts qo'lda boshqarardi.
Nest'da ikki savol paydo bo'ladi. Birinchisi: klient bitta bo'lishi va kerakli xizmatlarga DI orqali yetishi kerak. Ikkinchisi: ulanish ilova ko'tarilganda ochilib, yopilganda yopilishi kerak — main.ts ga qo'l bilan yozmasdan.
O'xshatish: ofisdagi bitta printer. Har xodimga alohida printer olmaysiz — bitta, umumiy, hamma ulanadi. Ertalab birinchi kelgan uni yoqadi, kechqurun oxirgi ketgan o'chiradi. Nest'da "yoqish" va "o'chirish" ni lifecycle hook'lar qiladi (Lifecycle hook'lar).
2. PrismaService naqshi
2.1 Xizmat — klientning o'zi
Nest hujjatidagi yo'l — Prisma klientidan meros olish:
const URL = "postgres://postgres@127.0.0.1:5495/tajriba30";
@Injectable()
class PrismaService extends PrismaClient
implements OnModuleInit, OnModuleDestroy {
constructor() {
super({ adapter: new PrismaPg({ connectionString: URL }) });
}
async onModuleInit() {
const t = performance.now();
await this.$connect();
const ms = (performance.now() - t).toFixed(0);
console.log(` onModuleInit: $connect ${ms} ms`);
}
async onModuleDestroy() {
await this.$disconnect();
console.log(" onModuleDestroy: $disconnect");
}
}
@Global()
@Module({ providers: [PrismaService], exports: [PrismaService] })
class PrismaModule {}Bu kanon tajribasining kodi (telefon uchun bo'lindi, ma'no o'zgarmagan). Qatorma-qator:
extends PrismaClient—PrismaServicenusxasi to'liq Prisma klienti:this.foydalanuvchi.create(...),this.$transaction(...)— hammasi bor. Ustiga@Injectable()qo'shildi — Nest uni yaratadi va kerakli joyga beradi.super({ adapter: ... })— Prisma 7 da klient bazaga o'zi ulanmaydi: unga driver adapter beriladi.PrismaPg—pgdrayveri ustidagi adapter (Prisma 7). Prisma 6 dagi Nest hujjati misollarida adapter yo'q — eski kodda shunday uchratasiz.onModuleInit— modul tayyor bo'lgach, ilova so'rov qabul qilishidan oldin.$connectshu yerda — birinchi so'rov ulanish ochilishini kutmasin.onModuleDestroy—app.close()da.$disconnect— ulanishlar yopiladi, jarayon toza chiqadi.@Global()modul —PrismaServiceni har modul import qilmasdan oladi (Modullar).
Diqqat:
PrismaServiceni ikki modulningprovidersiga yozmang. Modullar darsidagi tuzoq: ikki nusxa — ikki ulanishlar hovuzi (pool). Bazaningmax_connectionschegarasi ikki barobar tez to'ladi.
2.2 Filtr: Prisma xatosi → HTTP
Prisma xatolari kod bilan keladi: P2002 — noyoblik cheklovi buzildi, P2025 — kerakli yozuv topilmadi (Prisma: CRUD). Ularni har controller'da try/catch qilish o'rniga — bitta exception filter:
@Catch(Prisma.PrismaClientKnownRequestError)
class PrismaXatoFiltri implements ExceptionFilter {
catch(
x: Prisma.PrismaClientKnownRequestError,
host: ArgumentsHost,
) {
const holat =
x.code === "P2002" ? 409 : x.code === "P2025" ? 404 : 500;
host.switchToHttp().getResponse<Response>().status(holat).json({
status: holat, kod: x.code, maydon: x.meta?.["target"] ?? null,
});
}
}@Catch(Klass) — filtr faqat shu turdagi xatoni ushlaydi; qolganlari keyingi filtrga (yoki Nest'ning sukutiga) o'tadi. x.meta?.["target"] — hujjatga ko'ra P2002 da buzilgan maydon nomi.
2.3 Controller va ulash
@Controller("f")
class C {
constructor(private readonly db: PrismaService) {}
@Post("takror") takror() {
return this.db.foydalanuvchi.create({
data: { email: "aziz@example.com", toliqIsm: "Takror" },
});
}
@Get(":id") ol(@Param("id") id: string) {
return this.db.foydalanuvchi.findUniqueOrThrow({
where: { id: BigInt(id) }, select: { email: true },
});
}
}
@Module({
imports: [PrismaModule],
controllers: [C],
providers: [{ provide: APP_FILTER, useClass: PrismaXatoFiltri }],
})
class M {}foydalanuvchi — 27-qism sxemasidagi Foydalanuvchi modeli; namuna bazasida aziz@example.com allaqachon bor. BigInt(id) — sxemada id BigInt (Prisma: modellar). Filtr global — APP_FILTER bilan, DI orqali (Global enhancer'lar).
2.4 Natija
Tajriba uch so'rov yubordi: takror email bilan yaratish, mavjud foydalanuvchi va yo'q foydalanuvchi. Kanon chiqishi (kanon o'lchovi, IlmHamroh, 2026-10, NestJS 12.2.0, Prisma 7.10.1):
onModuleInit: $connect 53 ms
POST /f/takror → 409 {"status":409,"kod":"P2002","maydon":null}
GET /f/1 → 200 {"email":"aziz@example.com"}
GET /f/999999 → 404 {"status":404,"kod":"P2025","maydon":null}
onModuleDestroy: $disconnect- Birinchi qator —
onModuleInitso'rovlardan oldin: ulanish 53 ms. Bu vaqtni birinchi foydalanuvchi to'lamaydi. P2002 → 409,P2025 → 404— filtr ishladi."maydon": null— topilma. Hujjatdameta.targetmaydon nomini beradi (["email"]). Driver adapter bilan esa unull: ma'lumot boshqa joyda —meta.driverAdapterError.causeichida. 27-qismdaPrismaOmboriaynan shu sababli xato sababinidriverAdapterErrordan o'qiydi (Prisma: nested write va tranzaksiyalar).- Oxirgi qator —
app.close()da$disconnect.
Tekshirib ko'ring: Filtr
@Catch(Prisma.PrismaClientKnownRequestError)bilan yozilgan. Baza butunlay o'chiq bo'lsa, so'rov qanday javob oladi?
Javob
Bu filtr ushlamaydi: ulanish xatosi PrismaClientKnownRequestError emas (boshqa klass — masalan, PrismaClientInitializationError). Xato keyingi filtrga — vazifalar-api da Problem Details filtriga — o'tadi va 500 bo'ladi. To'g'ri: baza yo'qligi — mijozning aybi emas. Ehtiyot: onModuleInit dagi $connect bo'lsa, ilova umuman ishga tushmagan bo'lardi — fail-fast.
3. Lifecycle — qachon nima
sequenceDiagram
participant M as main.ts
participant N as Nest
participant P as PrismaService
participant DB as Postgres
M->>N: NestFactory.create
N->>P: constructor (adapter)
N->>P: onModuleInit
P->>DB: $connect (53 ms)
M->>N: listen
Note over N,DB: so'rovlar
M->>N: app.close()
N->>P: onModuleDestroy
P->>DB: $disconnectDiagrammadagi tartib Lifecycle hook'lar darsidagi bilan bir xil: onModuleInit — listen dan oldin, onModuleDestroy — close da. Signal kelganda (SIGTERM) app.close() ni kim chaqiradi? Nest hujjati app.enableShutdownHooks() ni taklif qiladi. Kanon uni ishlatmaydi: signalni jarayon.ts o'zi ushlaydi — avval HTTP ulanishlarni to'g'ri yopadi, keyin app.close(). Ikki joyda ushlansa, yopish ikki marta boshlanardi (main.ts dagi izoh).
4. Kanon qarori: PrismaService yo'q
4.1 Loyihada nima bor
vazifalar-api da Prisma — to'rt saqlash usulidan biri: SAQLASH=xotira | fayl | postgres | prisma (postgres va prisma ustiga — ixtiyoriy Redis kesh, REDIS_URL). Qaysi biri — config hal qiladi, ish vaqtida. Bu Dynamic modullar darsida qurilgan OmborModule.forRootAsync():
static forRootAsync(): DynamicModule {
return {
module: OmborModule,
providers: [
{
provide: SAQLASH,
useFactory: (config: Config, log: Log): Promise<Saqlash> =>
omborYarat(config, log),
inject: [CONFIG, LOG],
},
{
provide: VAZIFA_OMBORI,
useFactory: (s: Saqlash) => s.ombor,
inject: [SAQLASH],
},
SaqlashYopuvchi,
],
exports: [VAZIFA_OMBORI],
};
}omborYarat — 27-qismdan qolgan funksiya. SAQLASH=prisma bo'lsa, u pool'ni o'zi yaratadi va adapter'ga beradi:
const pool = new pg.Pool({
connectionString: config.DATABASE_URL,
application_name: "vazifalar-api",
max: config.PG_POOL_MAX,
idleTimeoutMillis: 30_000,
connectionTimeoutMillis: 5_000,
statement_timeout: config.PG_STATEMENT_TIMEOUT,
});
const db = new PrismaClient({ adapter: new PrismaPg(pool) });Yopish — SaqlashYopuvchi ning onApplicationShutdown hook'ida: HTTP server yopilgandan keyin, boshlangan so'rovlar bazani ishlatib bo'lgach.
4.2 Nega shunday
| Hujjat naqshi | Kanon | |
|---|---|---|
| Ombor tanlash | doim Prisma | config bo'yicha 4 variant (+ kesh) |
| Pool | adapter o'zi | o'zimiz: timeout'lar, application_name |
| Xato kodlari | global filtr | PrismaOmbori ichida → KonfliktXatosi |
| Xizmat nima ko'radi | butun PrismaClient |
VazifaOmbori interfeysi |
- Ombor tanlanadi.
PrismaServicedoim Prisma. Kanonda esa xuddi shu xizmat va controller'lar xotira, fayl,pgva Prisma bilan ishlaydi — bitta shartnoma testlari to'plami bilan (27-qism). - Pool nazoratda. Prisma o'z pool'ini yaratsa,
statement_timeout,application_namevaerrortinglovchisini qo'yish qiyinroq. 26-qismda o'rgangan sozlamalar (Connection pooling) yo'qolmasin. - Xatolar domenda.
P2002ni global filtr 409 qilsa, xato javobi Prisma tilida gapiradi (kod: "P2002"). KanondaPrismaOmboriuniKonfliktXatosiga aylantiradi — xuddipgomboridagi23505kabi — va javob Problem Details:"type": ".../takror-matn". Mijoz qaysi ORM ishlatilganini bilmaydi. - Turlar chiqmaydi.
extends PrismaClient— xizmatga butun klient beriladi: istalgan jadvalga, istalgan$queryRaw. Bu Repository naqshi darsining mavzusi.
Nima yo'qotdik: Nest hujjatini o'qib kelgan dasturchi PrismaService ni qidiradi va topmaydi. O'rniga — OmborModule va uning boshidagi izoh.
4.3 Farq xizmat ichida qanday ko'rinadi
Ikki yondashuvning farqi eng aniq xizmat constructor'ida ko'rinadi. Hujjat naqshida xizmat Prisma'ni to'g'ridan oladi:
// Hujjat naqshi: xizmat Prisma klientini biladi
@Injectable()
export class VazifalarService {
constructor(private readonly db: PrismaService) {}
ol(id: number) {
return this.db.vazifa.findUniqueOrThrow({
where: { id: BigInt(id) },
});
}
}Kanonda xizmat faqat interfeysni oladi — uning ortida qaysi ombor turgani unga noma'lum:
// Kanon: xizmat VazifaOmbori interfeysini biladi, xolos
@Injectable()
export class VazifalarService {
constructor(
@Inject(VAZIFA_OMBORI) private readonly ombor: VazifaOmbori,
) {}
async ol(id: number): Promise<Vazifa> {
const v = await this.ombor.ol(id);
if (!v) throw topilmadi(id);
return v;
}
}(Ikkinchisi — kanon vazifalar.service.ts dan ol metodi; constructor'dagi LOG va XABARCHI tushirib qoldirildi. Birinchisi — taqqoslash uchun sxema.) Birinchisida BigInt, findUniqueOrThrow va P2025 — xizmatning muammosi. Ikkinchisida ular PrismaOmbori ichida qoladi, xizmat esa xotira omborida ham, pg omborida ham aynan bir xil ishlaydi. Interfeys ortidagi @Inject(TOKEN) — Custom provider'lar darsidagi naqsh.
4.4 O'z loyihangiz uchun: qaysi birini tanlash
| Loyihangizda | Tanlov | Sabab |
|---|---|---|
| Prisma yagona baza vositasi, almashtirish rejasi yo'q | hujjat naqshi (PrismaService) |
sodda, hamma Nest dasturchisiga tanish |
| Bir nechta saqlash usuli yoki testda xotira ombori kerak | ombor interfeysi + fabrika | xizmat ORM'ga bog'lanmaydi |
| Prisma bor, lekin pool sozlamalari muhim | PrismaService + o'z pg.Pool adapterga |
timeout va application_name qo'lingizda |
Uchinchi qator — oraliq yo'l: PrismaService ning constructor'ida new PrismaPg({ connectionString }) o'rniga o'zingiz yaratgan pg.Pool ni bering. Naqsh hujjatdagidek qoladi, pool esa nazoratingizda.
5. Express'da qanday edi, Nest'da qanday
| 27-qism (Express) | Nest | |
|---|---|---|
| Klient kim yaratadi | omborYarat (server.ts dan) |
DI: provider yoki fabrika |
| Kimga yetadi | parametr bilan | constructor orqali |
| Ochish / yopish | server.ts qo'lda |
lifecycle hook'lar |
| Xato → HTTP | xato ishlovchi middleware | exception filter |
Kanonda chap ustundagi omborYarat o'zgarmadi — u Nest fabrikasi ichiga ko'chdi. O'zgargani — "kim chaqiradi" va "kim yopadi": endi Nest. 27-qismdagi server.ts qilgan ish (yaratish, EGASI_ID tekshiruvi, yopish) bir qatorga ham kamaymadi, faqat OmborModule ga joylashdi. Nest'ga ko'chishning umumiy narxi ham shu yerda ko'rinadi. Kanon o'lchovida sovuq start Express'dagi 2.5 s dan 4.8–5.3 s ga oshdi (bitta mashina, bir vaqtda o'lchangan, nisbat muhim). Bazali PATCH so'rovlari tezligi esa farqsiz qoldi — vaqtning asosiy qismi bazada.
6. Hujumchi nigohi
PrismaService extends PrismaClient xizmatga butun klientni beradi — shu jumladan xom SQL metodlarini. 27-qismda ularni ko'rgandik (Prisma: raw SQL va TypedSQL):
// ✅ teg-shablon: qiymat parametr bo'lib ketadi ($1)
await this.db.$queryRaw`SELECT * FROM vazifalar WHERE matn = ${matn}`;
// ❌ satr birlashtirish: SQL injection
await this.db.$queryRawUnsafe(
"SELECT * FROM vazifalar WHERE matn = '" + matn + "'",
);Hujumchi matn ga x' OR '1'='1 yuborsa, ikkinchi so'rov hamma vazifalarni qaytaradi — boshqa foydalanuvchilarnikini ham. PrismaService hamma xizmatga ochiq bo'lgani uchun xavfli metod ham hamma joyda bor. Himoya: $queryRawUnsafe ni lint qoidasi bilan taqiqlash va xom SQL'ni faqat ombor qatlamida yozish. Kanonda xizmatlar PrismaClient ni umuman ko'rmaydi — xom SQL faqat PrismaOmbori va PgOmbori ichida, parametrli.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Prisma 7 da klient yaratishda xato | adapter berilmagan | new PrismaClient({ adapter: new PrismaPg(...) }) |
| Ulanishlar soni ikki barobar | PrismaService ikki modul providers ida |
bitta @Global modul |
| Jarayon yopilmaydi | $disconnect yo'q |
onModuleDestroy yoki onApplicationShutdown |
meta.target — null |
driver adapter | meta.driverAdapterError.cause dan o'qing |
P2025 — 500 |
filtr yo'q yoki @Catch boshqa klass |
@Catch(Prisma.PrismaClientKnownRequestError) |
| Birinchi so'rov sekin | $connect yo'q — dangasa ulanish |
onModuleInit da $connect |
8. Mashqlar
Mashqlar kurs/mashqlar/30/31-prisma-nestjs/ da.
1-mashq (oson): hook va kod
To'ldiring:
- Ulanishni ochadigan hook —
- Takror qiymat (noyoblik) Prisma kodi —
findUniqueOrThrowtopa olmasa —- Prisma 7 da
pguchun adapter klassi —
Yechim
- onModuleInit —
listendan oldin ishlaydi. - P2002 → 409, P2025 → 404.
- PrismaPg —
@prisma/adapter-pgpaketidan.
2-mashq (o'rta): xato kodini Problem Details'ga aylantirish
prismaXatosi(x, yol) funksiyasini yozing. x — { code, meta } obyekt. Natija — Problem Details: P2002 → 409, title: "Takror qiymat"; P2025 → 404, title: "Topilmadi"; boshqasi → 500, title: "Ichki xato". Maydon nomi meta.target dan, u null bo'lsa — meta.driverAdapterError.cause.constraint.fields dan (bo'lmasa null). Ishora: undefined va null darsidagi ?. va ??.
Yechim
const JADVAL = {
P2002: { status: 409, title: "Takror qiymat" },
P2025: { status: 404, title: "Topilmadi" },
};
function prismaXatosi(x, yol) {
const { status, title } =
JADVAL[x.code] ?? { status: 500, title: "Ichki xato" };
const maydon = x.meta?.target
?? x.meta?.driverAdapterError?.cause?.constraint?.fields
?? null;
return { status, title, instance: yol, kod: x.code, maydon };
}
console.log(prismaXatosi(
{ code: "P2002", meta: { target: ["email"] } }, "/f/takror"));
console.log(prismaXatosi({
code: "P2002",
meta: {
target: null,
driverAdapterError: {
cause: { constraint: { fields: ["email"] } },
},
},
}, "/f/takror"));
console.log(prismaXatosi({ code: "P2025" }, "/f/999999"));
console.log(prismaXatosi({ code: "P1001" }, "/f/1").status);Konsolda:
{
status: 409,
title: 'Takror qiymat',
instance: '/f/takror',
kod: 'P2002',
maydon: [ 'email' ]
}
{
status: 409,
title: 'Takror qiymat',
instance: '/f/takror',
kod: 'P2002',
maydon: [ 'email' ]
}
{
status: 404,
title: 'Topilmadi',
instance: '/f/999999',
kod: 'P2025',
maydon: null
}
500Ikkinchi chaqiruv — adapter holati: target null, maydon ichkaridan topildi. Ichki tuzilma (cause.constraint.fields) — model uchun soddalashtirilgan; real Prisma xatosida aniq yo'lni console.dir(x.meta, { depth: 5 }) bilan tekshiring. To'rtinchisi — P1001 (bazaga ulanib bo'lmadi) jadvalda yo'q, 500 bo'ldi.
3-mashq (qiyin): lifecycle tartibi
Provider'lar ro'yxati berilgan: { nom, kerak: [...], init?, destroy? }. ishgaTushir(royxat) provider'larni bog'liqlik tartibida yaratsin (avval kerak dagilar) va har biri uchun init ni chaqirsin; yop(tartib) — destroy larni teskari tartibda. Har qadamni konsolga yozing. Sinov: PrismaService (init — $connect, destroy — $disconnect), VazifalarOmbori (kerak: Prisma), VazifalarXizmati (kerak: ombor). Ishora: rekursiv funksiya va Set (Rekursiya).
Yechim
function ishgaTushir(royxat) {
const nomli = new Map(royxat.map((p) => [p.nom, p]));
const tayyor = new Set();
const tartib = [];
function yarat(nom) {
if (tayyor.has(nom)) return;
const p = nomli.get(nom);
for (const k of p.kerak) yarat(k);
console.log(`yaratildi: ${nom}`);
tayyor.add(nom);
tartib.push(p);
}
royxat.forEach((p) => yarat(p.nom));
for (const p of tartib) p.init?.();
return tartib;
}
function yop(tartib) {
for (const p of [...tartib].reverse()) p.destroy?.();
}
const royxat = [
{ nom: "VazifalarXizmati", kerak: ["VazifalarOmbori"] },
{ nom: "VazifalarOmbori", kerak: ["PrismaService"] },
{
nom: "PrismaService",
kerak: [],
init: () => console.log("onModuleInit: $connect"),
destroy: () => console.log("onModuleDestroy: $disconnect"),
},
];
const tartib = ishgaTushir(royxat);
console.log("— so'rovlar —");
yop(tartib);Konsolda:
yaratildi: PrismaService
yaratildi: VazifalarOmbori
yaratildi: VazifalarXizmati
onModuleInit: $connect
— so'rovlar —
onModuleDestroy: $disconnectRo'yxatda VazifalarXizmati birinchi, lekin PrismaService birinchi yaratildi — DI bog'liqliklarni oldin quradi (DI va IoC konteyner). Hook'lar hammasi yaratilgandan keyin chaqiriladi. Yopish teskari: avval undan foydalanuvchilar, keyin bazaning o'zi. Haqiqiy Nest'da onModuleDestroy ham modullar tartibiga bog'liq — model buni soddalashtirgan.
9. Loyiha qadami: o'zgarish yo'q — va nega
Bu darsda vazifalar-api o'zgarmaydi. Kanon PrismaService naqshini alohida tajribada sinadi (yuqoridagi chiqish) va loyihaga kiritmadi — «Kanon qarori» bo'limidagi to'rt sabab bilan.
O'z loyihangizda tekshirib ko'ring: SAQLASH=prisma bilan ishga tushirsangiz, OmborModule.forRootAsync Prisma klientini yaratadi, EGASI_ID ni bazada tekshiradi (fail-fast) va migratsiya holatini solishtiradi. Yopilganda logda "ombor ulanishlari yopildi" qatori chiqadi. Bularning hammasi Dynamic modullar darsidan beri bor; bu dars ularni hujjatdagi naqsh bilan solishtirish imkonini berdi.
Agar boshqa loyihada Prisma yagona saqlash bo'lsa va boshqa omborga o'tish rejada bo'lmasa — hujjat naqshi to'liq o'rinli. Kanon tanlovi — "noto'g'ri naqsh" emas, ko'p omborli loyihaga mos javob.
10. Real ishda
PrismaService extends PrismaClient— Nest + Prisma loyihalarining 90 % ida shunday (prisma.service.ts). Uni birinchi kunning o'zida uchratasiz.- Prisma 6 → 7 ko'chishi — eski
PrismaServicelarda adapter yo'q va$on("beforeExit")kabi eskirgan kod bor. Yangilashda birinchi o'zgaradigan fayl. - Xato kodlari filtri —
P2002 → 409qoidasi ko'p loyihada global; javobda ichki kod (P2002) chiqib ketmasligi review'da tekshiriladi. - Intervyu: "Nest'da Prisma'ni qanday ulaysiz?", "ulanish qachon ochiladi va yopiladi?", "
P2002ni qanday ushlaysiz?".
Xulosa
- Hujjat naqshi:
PrismaService extends PrismaClient+@Injectable,@GlobalPrismaModule. - Prisma 7 — klientga adapter (
PrismaPg) beriladi; eski misollarda yo'q. onModuleInit—$connect(listendan oldin),onModuleDestroy—$disconnect(closeda).@Catch(Prisma.PrismaClientKnownRequestError)filtri:P2002→ 409,P2025→ 404; adapter bilanmeta.target—null.- Kanon: Prisma —
OmborModuleichida, o'z pool'i bilan, xatolarPrismaOmborida domen xatosiga aylanadi; xizmat faqatVazifaOmborini ko'radi.
Keyingi dars: TypeORM bilan NestJS — rasmiy @nestjs/typeorm moduli: forRootAsync, forFeature va @InjectRepository.
Manbalar
- NestJS hujjati — Prisma recipe: https://docs.nestjs.com/recipes/prisma
- Prisma — Driver adapters (
@prisma/adapter-pg): https://www.prisma.io/docs/orm/overview/databases/database-drivers - Prisma — Error reference (
P2002,P2025): https://www.prisma.io/docs/orm/reference/error-reference - Kanon (IlmHamroh, 2026-10-28):
PrismaServicetajribasi (NestJS 12.2.0, Prisma 7.10.1, adapter-pg) —$connect53 ms, P2002 → 409, P2025 → 404,meta.targetnull;OmborModule.forRootAsyncvaomborYarat. Tajriba kodi tip tekshiruvidan o'tkazildi (biz ishga tushirdik:tsc, holat nusxasida, 2026-11-02).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!