File Manager
커넥터 가이드
읽기 전용에서 시작해 mutation을 capability와 쌍으로 늘려가는 커스텀 커넥터 구현 가이드
reopt design업데이트
1. 단계별 구현
커넥터는 한 번에 완성할 필요가 없습니다. list 하나로 시작해서 백엔드가 지원하는 만큼 capability를 켜 나가면 UI가 단계마다 완결된 상태를 유지합니다.
tsx
import type { FileManagerConnector } from "@reopt-ai/opt-filemanager";
// 1단계: 읽기 전용 — capabilities 전부 false + list만 구현해도
// 탐색·정렬·필터·상세 패널이 전부 동작합니다.
export function createReadOnlyConnector(): FileManagerConnector {
return {
capabilities: {
createFolder: false, createFile: false, upload: false,
rename: false, remove: false, move: false,
readText: false, usage: false, download: true,
},
async list({ folderId, signal }) {
const res = await fetch(`/api/files?folder=${folderId ?? ""}`, { signal });
return { entries: await res.json() };
},
};
}tsx
// 2단계: mutation은 "capability + 메서드"를 항상 쌍으로 추가합니다.
// 하나만 추가하면 UI가 액션을 숨기거나(메서드만) 호출이 실패합니다(플래그만).
{
capabilities: { ...readOnly, upload: true, remove: true },
async upload({ parentId, file, onProgress, signal }) {
// XHR/presigned 등 진행률을 알 수 있으면 onProgress(0~1)를 호출하세요.
// 없으면 완료 시 onProgress?.(1) 한 번이면 큐가 정상 종료됩니다.
return uploadToBackend(parentId, file, { onProgress, signal });
},
async remove({ id }) {
await deleteFromBackend(id); // 거부 사유는 throw로 — 아래 에러 계약 참조
},
}2. 에러 계약
사용자에게 설명해야 하는 실패는 FileManagerConnectorError로 던지세요. message가 오류 배너와 업로드 큐 행에 그대로 표시됩니다.
tsx
import { FileManagerConnectorError } from "@reopt-ai/opt-filemanager";
// message는 오류 배너에 그대로 표시됩니다 — 사람이 읽을 문장으로.
throw new FileManagerConnectorError(
"FILE_IN_USE",
"브랜드프론트 히어로 섹션에서 사용 중인 파일입니다",
);| code | 발생 지점 | 의미 |
|---|---|---|
| FILE_TOO_LARGE | 업로드 | 크기 상한 초과 — 커넥터가 전송 전에 즉시 던지는 것을 권장 |
| STORAGE_LIMIT | 업로드 | 저장공간 쿼터 초과 (brandapp 402) |
| FILE_IN_USE | 삭제 | 다른 곳에서 참조 중 (brandapp 409) — 사용처를 message에 |
| FOLDER_NOT_EMPTY | 폴더 삭제 | 비어있지 않은 폴더 (brandapp 409) |
| CONFLICT | 폴더 생성·이동 | 같은 위치에 동명 폴더 (brandapp 409) |
| MOVE_INTO_SELF | 이동 | 폴더를 자기 자신/자손으로 이동 시도 |
| FOLDER_NOT_SUPPORTED | 탐색 | 평평한 백엔드에서 폴더 진입 시도 |
3. brandapp capability 유도 규칙
createBrandappFilesConnector는 주입된 클라이언트가 실제로 제공하는 메서드에서 capability를 유도합니다. v1 4개 메서드(list/get/delete/upload)만 있으면 평평한 표면으로 자동 강등되고, 아래 메서드가 보이는 만큼 해제됩니다. 목록에서 본 적 없는 id로 rename/이동/삭제를 호출하면 파일 조회를 한 번 시도해 종류를 판별한 뒤(404면 폴더) 올바른 엔드포인트로 라우팅합니다.
| 클라이언트 메서드 | 해제되는 기능 |
|---|---|
| listFolders + createFolder | createFolder, 폴더 탐색 |
| update | rename, move(파일) |
| updateFolder | move(폴더 포함 완전한 이동) |
| deleteFolder | 폴더 삭제 라우팅 |
| readContent | readText (텍스트 미리보기) |
| usage | usage (저장공간 미터) |
4. 로컬 검증
bash
# 크레덴셜 없이 로컬에서 실서버 계약을 검증하려면:
reopt brandapp dev -p 4300 # 오프라인 인메모리 Files 서버
# createReoptFileClient({ baseUrl: "http://localhost:4300",
# clientId: "dev", clientSecret: "dev", brandappId: "dev-brandapp" })
# 를 createBrandappFilesConnector({ client })에 주입하면 끝.