Files
AriWeb-Suite/portal/app.mjs
T

35 lines
2.2 KiB
JavaScript

/**
* portal/app.mjs — 고객 포털 앱 조립.
*
* 각 영역(portal/<영역>/api.mjs)은 `register(app, deps)` 를 내보내고 여기서 순서대로 등록된다. deps 는 모든 영역이 공유하는 의존성 묶음이다.
* deps = { store(lib/db), vault, jobs(작업 엔진), config(설정), hal(HAL 클라이언트), webmaker(어댑터), arimail(어댑터), notify, audit, quota, t, page, badge, statePanel, log }
* 인증 미들웨어(portal/auth/api.mjs 의 middleware)가 가장 먼저 실행되어 ctx.user·ctx.group·ctx.membership·ctx.session·ctx.sitePerms 를 채운다.
* 영역 등록 순서: auth → groups → dashboard → commerce → usage → sites → domains → source → mail → backup → relocation → transfer → lifecycle → notifications → audit → ops(내부 운영자 API) → webhooks(HAL 이벤트)
*/
import { createApp } from '../lib/http.mjs';
import { t } from '../lib/i18n.mjs';
import { page, badge, statePanel, dangerSpec } from './ui/layout.mjs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { existsSync } from 'node:fs';
const HERE = dirname(fileURLToPath(import.meta.url));
/** 영역 목록(파일이 있는 것만 등록 — 병렬 개발 중 아직 없는 영역은 건너뛴다) */
export const AREAS = ['core', 'auth', 'groups', 'dashboard', 'commerce', 'usage', 'sites', 'domains', 'source', 'mail', 'backup', 'relocation', 'transfer', 'lifecycle', 'notifications', 'auditui', 'ops', 'webhooks', 'help'];
/** @param {{areas?:string[]}} [opts] areas 를 주면 그 영역만 등록(테스트에서 다른 영역과 분리) */
export async function buildApp(deps, opts = {}) {
const app = createApp({ log: deps.log, onError: deps.onError });
app.static('/ui', join(HERE, 'ui', 'public'));
Object.assign(deps, { t, page, badge, statePanel, dangerSpec, app });
const loaded = [];
if (opts.before) app.use(opts.before);
for (const a of (opts.areas || AREAS)) {
const file = join(HERE, a, 'api.mjs'); if (!existsSync(file)) continue;
const mod = await import(file); if (typeof mod.register !== 'function') continue;
await mod.register(app, deps); loaded.push(a);
}
deps.log(`[portal] 영역 등록: ${loaded.join(', ')}`);
return app;
}