@yakcloud/auth-adapter: core 인터페이스(프레임워크 무관, ds-sdk type-only) + dev-bypass + next-auth 격리 계층(peer). exports 서브패스(./core·./dev-bypass). @yakcloud/bff-kit: respond(web 표준)·serialize(Prisma-free)·ratelimit·session(AuthAdapter DI). auth-adapter=devDependency(type-only), 죽은 next peer 제거. @yakcloud/client-shell: ServiceClientShell 셸 크롬(헤더/탭/pane/가드)+패널 슬롯+BackupPanel 스텁. (FileBrowser 는 Phase 1) FIX-FIRST 반영: client-shell tsconfig jsx:react-jsx + @types/react(-dom), bff-kit/auth-adapter += @types/node. 7개 패키지 전부 tsc --noEmit 통과. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
// @yakcloud/bff-kit — serialize
|
|
// DTO 마스킹·필터. Prisma-free: 전체 모델 대신 필요한 필드만 가진 구조적 입력 타입을 받는다.
|
|
// connSecretRef(내부 Secret 이름) 및 시크릿 env 값은 절대 출력에 노출하지 않는다(마스킹 계약).
|
|
// yakconsole api/serialize.ts 하강.
|
|
|
|
import type { EnvVarDTO } from "@yakcloud/ds-sdk";
|
|
|
|
// ── 구조적 입력 타입(Repo 결과에서 핸들러가 구성; Prisma 모델도 구조적으로 호환) ──
|
|
|
|
// 날짜는 Repo 가 Date 로 주든 ISO string 으로 주든 그대로 통과시킨다(직렬화는 Response.json 소관).
|
|
type DateLike = Date | string;
|
|
|
|
export interface DeploymentInput {
|
|
env: unknown; // Deployment.env(Json) — 배열이 아니면 []
|
|
[k: string]: unknown; // 나머지 필드는 그대로 스프레드(구조적)
|
|
}
|
|
|
|
export interface ServiceInput {
|
|
id: string;
|
|
ownerId: string;
|
|
clusterId: string;
|
|
name: string;
|
|
type: string;
|
|
mode: string;
|
|
status: string;
|
|
statusMessage: string | null;
|
|
size: string;
|
|
storageGb: number;
|
|
persist: boolean;
|
|
connSecretRef?: string | null; // ⛔ 출력에서 제외(마스킹)
|
|
connInfo: unknown; // 비밀 제외 접속 메타 JSON
|
|
createdAt: DateLike;
|
|
updatedAt: DateLike;
|
|
}
|
|
|
|
export interface PublicServiceExtra {
|
|
clusterName?: string;
|
|
bindings?: { app: string; alias: string }[];
|
|
}
|
|
|
|
// Deployment.env(Json) → EnvVar[]. 배열이 아니면 빈 배열.
|
|
export function envOf(dep: DeploymentInput): EnvVarDTO[] {
|
|
const raw = dep.env;
|
|
if (!Array.isArray(raw)) return [];
|
|
return raw as EnvVarDTO[];
|
|
}
|
|
|
|
// API 응답용: 시크릿 환경변수의 값을 마스킹(빈 문자열)해 클라이언트로 노출하지 않는다.
|
|
export function publicDeployment<D extends DeploymentInput>(dep: D): Omit<D, "env"> & { env: EnvVarDTO[] } {
|
|
const env = envOf(dep).map((e) => (e.secret ? { key: e.key, value: "", secret: true } : e));
|
|
return { ...dep, env };
|
|
}
|
|
|
|
// 외부 서비스 응답 DTO — connSecretRef 미노출, connInfo(host/port/db/bucket)만.
|
|
// 크리덴셜은 애초에 포털에 저장되지 않으므로 여기서 마스킹할 비밀이 없다(설계 C).
|
|
export function publicService(svc: ServiceInput, extra?: PublicServiceExtra) {
|
|
return {
|
|
id: svc.id,
|
|
ownerId: svc.ownerId,
|
|
clusterId: svc.clusterId,
|
|
name: svc.name,
|
|
type: svc.type,
|
|
mode: svc.mode,
|
|
status: svc.status,
|
|
statusMessage: svc.statusMessage,
|
|
size: svc.size,
|
|
storageGb: svc.storageGb,
|
|
persist: svc.persist,
|
|
connInfo: (svc.connInfo as Record<string, unknown> | null) ?? null,
|
|
createdAt: svc.createdAt,
|
|
updatedAt: svc.updatedAt,
|
|
...(extra?.clusterName !== undefined ? { clusterName: extra.clusterName } : {}),
|
|
...(extra?.bindings !== undefined ? { bindings: extra.bindings } : {}),
|
|
};
|
|
}
|