Дундын код¶
Экосистемийн платформууд гаднаа өөр, дотроо нэг. Хэрэглэгчид тус бүр нь өөрийн брэнд, домэйн, үйлчилгээтэй харагдана — гэвч кодын 90 гаруй хувь нь бодитоор нэг эх сурвалжаас ирдэг.
Энэ хуудас тэр дундын кодыг хэрхэн хуваалцдагийг тайлбарлана.
Яагаад хэрэгтэй болсон бэ¶
Эхэндээ платформ бүр template-ээс хуулбарлагдаж гардаг байв. Улмаар нэг алдааны засварыг 8 репод гараар давтах шаардлагатай болсон: аль нэгийг нь мартвал тэр платформ чимээгүй хоцорно.
Хэмжилтээр frontend-ийн ~95% нь бодитоор дундын байсан; жинхэнэ зөрүү нь брэндийн нэр орсон ~40 мөр л байлаа. Өөрөөр хэлбэл давхардал нь техникийн шаардлага биш, зүгээр л хуулбарлалтын өв байв.
Гурван механизм¶
Дундын код нь давхаргаасаа хамаараад өөр өөр аргаар тардаг. Аль нь ч «хуулах» биш — бүгд хувилбартай, буцаах боломжтой.
| Давхарга | Хэлбэр | Механизм |
|---|---|---|
| Backend цөм | Go модуль | go.mod хамаарал |
| Frontend давхарга | npm багц | package.json хамаарал |
| Платформын араг яс | git түүх | git merge + өдөр тутмын autosync |
1. Backend цөм — Go модуль¶
Танилт, эрхийн хяналт (RBAC), API gateway, audit, AI pipeline, eID/SSO
интеграц — эдгээр нь нэг Go модульд байна. Платформын main.go нь
ихэвчлэн 30 орчим мөр: цөмийг эхлүүлээд, өөрийн онцлог маршрутаа нэмнэ.
Цөм нь нэг шууд давхаргатай:
open-gerege-core— төрийн болон Gerege урсгалын бүх backend шууд хэрэглэдэг нээлттэй суурь.
2026-08-02 хүртэл дунд нь private-gerege-core байсан ч нэмэлт логик,
migration агуулаагүй тул гинжнээс хасаж архивласан. Аппын арилжааны логик
тухайн бүтээгдэхүүний repository-д үлдэнэ.
2. Frontend давхарга — @gerege/ui-core¶
Backend-д цөм шийдсэн асуудлыг frontend дээр давтан шийдсэн багц. Дотор нь:
lib/**— API клиент, BFF туслах, i18n толь, theme, session,components/**— бүрхүүл (shell), админ, хэрэглэгчийн хэсэг, eID, gateway,api/**— 158 BFF route-ийн логик.
Багц нь TypeScript эх кодоор тардаг (build хийгдээгүй) тул хэрэглэгч апп
Next.js-ийн transpilePackages-аар өөрөө хөрвүүлнэ. Түгээлт нь нээлттэй
HTTPS tarball — нэвтрэлт шаардахгүй, Docker build дотор ч ажиллана.
BFF route яагаад бүрхүүлтэй үлдсэн бэ
Next.js нь route-ыг файлын системээр бүртгэдэг тул апп бүр зам тутамд нэг мөрийн дахин экспорт үлдээнэ:
// src/app/api/org/[id]/route.ts
export { GET, PUT, DELETE } from '@gerege/ui-core/api/org/[id]';
export const dynamic = 'force-dynamic';
158 файлыг ганц [...path] catch-all болгож болох ч тэр нь аюулгүй
байдлын зөвшөөрлийн жагсаалтыг устгана: route-ын жагсаалт нь хөтчөөс
backend-ийн аль зам хүрч болохыг тодорхойлдог. Бүрхүүл нь зориудын үнэ.
3. Платформын араг яс — git удамшил¶
Багцад орохгүй зүйлс (хуудасны бүтэц, globals.css, deploy тохиргоо) нь
template-ээс git merge-ээр удамшина. Өдөрт нэг удаа ажилладаг autosync нь
дээд template-ээс өөрчлөлтийг татаж, апп репод PR үүсгэнэ — production-д
хүрэх өөрчлөлт бүр хүний хяналтаар дамжина.
Платформ бүрийн өөрийнх байх ёстой файлууд (брэнд, deploy, CI, баримт)
.gitattributes-ийн merge=ours-оор хамгаалагдана.
merge=ours нь нэг талын өөрчлөлтөөс хамгаалдаггүй
Тэр драйвер зөвхөн conflict-ыг шийднэ. Дээд template файлаа устгавал merge түүнийг дагана — драйвер огт дуудагдахгүй. Иймд брэнд/тохиргооны файл бүр хоёр талдаа өөр агуулгатай байх нь жинхэнэ хамгаалалт.
Юу платформынх хэвээр үлддэг вэ¶
| Багцад / цөмд | Платформынх |
|---|---|
lib/**, components/**, BFF логик |
brand.config.ts — нэр, домэйн, өнгө, баримтын хаяг |
| Танилт, RBAC, gateway, audit | components/landing/** — маркетингийн текст |
| eID / SSO интеграц | app/**/page.tsx — route бүртгэл (нимгэн бүрхүүл) |
| Дундын i18n толь (846 түлхүүр × 7 хэл) | lib/<platform>I18n.ts — платформын нэр томьёо |
Цэсний бүтэц (AppShell) |
nav.config.ts — платформ аль хэсгийг нь үйлчилдэг |
app/globals.css — брэндийн өнгөний токен |
|
deploy/**, .github/** — байршуулалт, CI |
Платформын нэр томьёо яагаад аппад үлддэг вэ¶
Дүрэм: дундын толь нь дундын гадаргууг л мэднэ. Тухайн платформд л хамаатай үг — хэтэвчийн IBAN/хуулга, хөгжүүлэгчийн порталын API каталог, Ring-ийн бизнес-процессийн нэр томьёо — аппын өөрийн толинд байрлана.
Шалтгаан нь өртөг: Ring-ийн 1,104 нэр томьёог дундын толинд хийвэл kiosk, POS, хэтэвч бүгд түүнийг үүрэх бөгөөд хэл нэмэх бүрд тэр өртөг долоо дахин нэмэгдэнэ.
Хэрэгжүүлэлт нь репо бүрт ижил хэв маягтай:
// lib/walletI18n.ts — хэтэвчийн 15 нэр томьёо × 4 хэл
export function useWalletT() { … } // орчуулаагүй хэлэнд англи руу уналт
Компонент T-г дэд компонент руу проп болгож дамжуулдаг бол хоёр функц
(T + wt) болгох нь проп бүрийг хуваахад хүргэнэ. Тийм тохиолдолд нэг
шийдэгч бичнэ: түлхүүр платформынх бол өөрийн толиос, эс бөгөөс багцаас
(ring-dgov-ийн lib/lang.ts).
Цэс — бүтэц дундын, үйлчилгээ платформынх¶
AppShell нь бүх платформд ижил зохион байгуулалттай (Супер админ · Админ ·
Менежер · Иргэн) ч платформ бүр түүний дэд олонлогийг л хэрэгжүүлдэг:
хэтэвч нь gateway, relay, бүртгэлийн модульгүй.
| Тохиргоо | Зориулалт |
|---|---|
navRoutes |
Апп үнэхээр үйлчилдэг замууд; цэс үүгээр шүүгдэнэ |
navSystemLabels |
Rail дээрх системийн нэр (me → «Түрийвч») |
navExtra |
Зөвхөн тэр платформд байдаг цэс (Ring-ийн BPM 21 цэс) |
navExtra нь CLIENT компонентоос ирнэ
UiCoreProvider нь server root layout-аас дуудагддаг client компонент.
Цэсний дүрс (React component) болон нэрийн функц нь server→client хилээр
гарахгүй. Иймд апп нимгэн client бүрхүүл үүсгэж, түүн дотроос дамжуулна:
// src/nav.config.tsx
'use client';
export default function AppNav({ children }) {
return <UiCoreProvider navExtra={NAV_EXTRA}>{children}</UiCoreProvider>;
}
Цөөн платформ л үйлчилдэг цэсийг багцад optIn: true гэж тэмдэглэвэл
navRoutes-д ил бичсэн платформ дээр л гарна.
Гурван автомат хаалга¶
Дундын код нь гурван өөр төрлийн хамаарал үүсгэдэг. Тус бүр нь эвдрэхэд өөрөөр илэрдэг тул хаалт нь ч гурав:
| Хамаарал | Хаалт | Эвдрэхэд юу болох вэ |
|---|---|---|
| Багцын код ← аппын код | tsc |
Хөрвүүлэлт унана — шууд харагдана |
| Багцын route ← аппын BFF бүрхүүл | check-routes |
Endpoint чимээгүй алга болно |
| Багцын class ← аппын CSS | check-styles |
Дэлгэц чимээгүй загваргүй болно |
-
check-brand— платформын нэрbrand.config.ts-ээс гадуур кодод бичигдвэл build унана. Тухайн платформын нэрийгbrand.config.ts-ээс уншдаг тул жагсаалт гараар хоцрохгүй.Хаалт юу барьсан бэ
Нэвтрэх хуудас «Gerege SSO (sso.gerege.mn)»-оор нэвтрэхийг санал болгодог байсан ч төрийн урсгалын платформууд бодитоор
sso.dgov.mnруу чиглүүлдэг байв. Одоо хостыг backend-ийнSSO_ISSUER-ээс уншина. -
check-routes— багцын route бүрд апп бүрхүүл шаардана. Үгүй бол багц шинэ endpoint нэмэхэд тэр нь тухайн платформ дээр чимээгүй алга болно (логик нь апп дотор харагддаггүй тул нүдээр анзаарагдахгүй).EXCLUDE нь зөв эсэхийг хаалт батлахгүй
Route-ыг зориудаар нээхгүй бол
EXCLUDE-д бичнэ — зөрүү нь ил болно. Гэвч буруу бичсэнийг хаалт барихгүй. Ингэж нэг платформ дээрpublic/languagesхаагдсанаас хэлний сонгогч хоосон болсон байв: бүх хаалт ногоон, дэлгэц эвдэрсэн. -
check-styles— багц CSS агуулдаггүй: загвар нь репо бүрийнglobals.css-д байрладаг. Багц шинэ class нэрлэхэд, эсвэл репогийн CSS хуучирахад компонент чимээгүй загваргүй болно — товч хөтчийн анхдагч саарал чимэгтэй, хүснэгт хүрээгүй болно. Энэ хаалт багцынclassName-ыг репогийн CSS-тэй тулгана.
Хувилбарлалт¶
Гурван механизм гурвуулаа semver дагана. Шинэ хувилбар гармагц Dependabot
хэрэглэгч репод PR үүсгэнэ; шинэчлэлт нь go.mod эсвэл package.json дахь
нэг мөрийн өөрчлөлт.
Template-ийг өргөхөд хангалтгүй¶
Платформ бүр template-ээс удамшдаг тул «template-ийг өргөвөл бүгдэд тарна» гэж бодогдоно. Бодитоор хамаарлын хоёр төрөл ялгаатай ажилладаг:
| Файл | merge=ours? |
Template-ээс тарах уу |
|---|---|---|
backend/go.mod |
тийм | ❌ хэзээ ч |
frontend/package.json |
үгүй | ✅ тарна |
go.mod-ийн хамгаалалт нь бүтцийн шаардлага: module мөр репо бүрт өөр
(…/gerege-app-mn/backend vs …/wallet-gerege-mn/backend) тул merge бүр эхний
мөрөн дээр зөрчилдөнө. Иймд backend цөмийн хувилбарыг template дээр өргөх нь
юу ч тараахгүй — репо тус бүрд PR хэрэгтэй.
Удамшлын мод нь мөн гурван шаттай (public template → private template →
апп), тул тарах чадвартай файл ч навч хүртэл хэдэн autosync мөчлөг явна.
Хугацах өөрчлөлт нь хамаарлын PR-ыг гацаана
Толь бичгийг дөрвөн хэлнээс долоо болгоход Record<Lang, …> гэж бичсэн
газар бүр тасарсан. Үр дүнд нь Dependabot-ийн PR бүр tsc-ээр унаж, хэн ч
merge хийхгүй, дараагийнх нь түүн дээр овоорсон — флот v0.4.0-оос
v0.10.2 хүртэл сарнижээ.
Иймд багцад хугацах өөрчлөлт хийхдээ (а) шилжүүлэх зааврыг release тэмдэглэлд бичих, (б) хэрэглэгч репод засварыг нь ЗЭРЭГ гаргах. Автомат шинэчлэл нь хугацах өөрчлөлтөд гарын авлагын алхам шаарддаг.
Хоцрогдол нь чимээгүй
Хамаарлын PR хуримтлагдвал платформууд өөр өөр хувилбар дээр сарних тул «нэг засвар бүгдэд хүрнэ» гэсэн амлалт эвдэрнэ. Хамаарлын PR-ыг тогтмол хааж байх нь энэ бүтцийн ажиллах нөхцөл — сонголт биш.
Холбогдох¶
- Технологийн стек
- Нийтлэг зарчим
- Танилт ба эрх — нэвтрэх гадаргууны
AUTH_MODEтохиргоо