Files
photo-live/services/api/src/uploads/storage.provider.ts
T
浅念 a2a3ccd340 feat(api): idempotent upload session init with presigned credential
POST /v1/uploads (Task 18, A03): @@unique(userId, clientTaskId) idempotency
anchor — same params return the original session (201, no duplicate photo);
param drift (album/bytes/contentType/extension) -> 409 UPLOAD_SESSION_CONFLICT.
photos.objectKey is set to the FINAL originals key at init while the session
holds the staging key; IDs come from an app-side cuid-like generator so both
self-referencing keys are written in one transaction. Credential is a real
MinIO presigned PUT (SIGNED_URL_TTL_SECONDS, lazily read). Permission order:
album invisible 404 -> member 403 -> uploadEnabled 409 -> size/ext 400 ->
category ownership 400. No audit on init (audit anchors on complete).

Pre-step for Task 19: QUEUE_PHOTO_PROCESS contract constant + lazy-safe
BullMQ queue producer (Redis down at boot must not crash the app; enqueue
failure only logs — sweep compensates). e2e reset now also wipes the MinIO
photo-live/dev prefix; jest maps @photo/storage to TS source.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 22:42:13 +08:00

14 lines
727 B
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// services/api/src/uploads/storage.provider.ts —— StoragePort 的 DI 装配(Task 18)。
// api 只依赖存储端口抽象(packages/storage),测试/本地指向 MinIO、生产指向 OSS,
// 由 createStorageFromEnv() 依 S3_* 环境变量构造。构造期无网络请求(S3Client
// 懒连接),缺 env 时快速失败(storage 包哲学:禁止静默回退默认值)。
import { createStorageFromEnv, type StoragePort } from '@photo/storage';
/** DI token:photos/public 等后续模块经模块导出复用同一实例。 */
export const STORAGE_PORT = Symbol('STORAGE_PORT');
export const storageProvider = {
provide: STORAGE_PORT,
useFactory: (): StoragePort => createStorageFromEnv(),
};