diff --git a/client/features/tasks/TaskList.tsx b/client/features/tasks/TaskList.tsx index 7f83a36..16a5ee4 100644 --- a/client/features/tasks/TaskList.tsx +++ b/client/features/tasks/TaskList.tsx @@ -12,7 +12,9 @@ import styles from './taskList.module.css'; export const TaskList = () => { const { setAlert } = useAlert(); - const { data: tasks, mutate: mutateTasks } = useAspidaSWR(apiClient.private.tasks); + const { data: tasks, mutate: mutateTasks } = useAspidaSWR(apiClient.private.tasks, { + refreshInterval: 5000, + }); const { lastMsg } = usePickedLastMsg(['taskCreated', 'taskUpdated', 'taskDeleted']); const fileRef = useRef(null); const [label, setLabel] = useState(''); diff --git a/server/api/private/tasks/controller.ts b/server/api/private/tasks/controller.ts index 89e8520..9f05bee 100644 --- a/server/api/private/tasks/controller.ts +++ b/server/api/private/tasks/controller.ts @@ -12,7 +12,7 @@ export default defineController(() => ({ status: 200, body: await taskQuery .listByAuthorId(prismaClient, user.id, query?.limit) - .then((tasks) => Promise.all(tasks.map(toTaskDto))), + .then((tasks) => tasks.map(toTaskDto)), }), post: { validators: { body: taskValidator.taskCreate }, diff --git a/server/api/private/tasks/di/controller.ts b/server/api/private/tasks/di/controller.ts index 086febc..48f4257 100644 --- a/server/api/private/tasks/di/controller.ts +++ b/server/api/private/tasks/di/controller.ts @@ -8,6 +8,6 @@ export default defineController({ listByAuthorId: taskQuery.listByAuthorId }, (d status: 200, body: await taskQuery.findManyWithDI .inject(deps)(prismaClient, user.id) - .then((tasks) => Promise.all(tasks.map(toTaskDto))), + .then((tasks) => tasks.map(toTaskDto)), }), })); diff --git a/server/domain/task/service/toTaskDto.ts b/server/domain/task/service/toTaskDto.ts index 12f3059..fe9f758 100644 --- a/server/domain/task/service/toTaskDto.ts +++ b/server/domain/task/service/toTaskDto.ts @@ -3,11 +3,9 @@ import { brandedId } from 'service/brandedId'; import { s3 } from 'service/s3Client'; import type { TaskEntity } from '../model/taskType'; -export const toTaskDto = async (task: TaskEntity): Promise => ({ +export const toTaskDto = (task: TaskEntity): TaskDto => ({ ...task, id: brandedId.task.dto.parse(task.id), - image: task.imageKey - ? { s3Key: task.imageKey, url: await s3.getSignedUrl(task.imageKey) } - : undefined, + image: task.imageKey ? { s3Key: task.imageKey, url: s3.keyToUrl(task.imageKey) } : undefined, author: { ...task.author, id: brandedId.user.dto.parse(task.author.id) }, }); diff --git a/server/domain/task/useCase/taskUseCase.ts b/server/domain/task/useCase/taskUseCase.ts index e9ed211..80d5292 100644 --- a/server/domain/task/useCase/taskUseCase.ts +++ b/server/domain/task/useCase/taskUseCase.ts @@ -16,7 +16,7 @@ export const taskUseCase = { await taskCommand.save(tx, created); - const dto = await toTaskDto(created.task); + const dto = toTaskDto(created.task); taskEvent.created(user, dto); return dto; @@ -28,7 +28,7 @@ export const taskUseCase = { await taskCommand.save(tx, updated); - const dto = await toTaskDto(updated.task); + const dto = toTaskDto(updated.task); taskEvent.updated(user, dto); return dto; @@ -40,7 +40,7 @@ export const taskUseCase = { await taskCommand.delete(tx, deleted); - const dto = await toTaskDto(deleted.task); + const dto = toTaskDto(deleted.task); taskEvent.deleted(user, dto); return dto; diff --git a/server/service/envValues.ts b/server/service/envValues.ts index 8fe3dbc..784e9a7 100644 --- a/server/service/envValues.ts +++ b/server/service/envValues.ts @@ -13,6 +13,9 @@ const COGNITO_USER_POOL_CLIENT_ID = z .parse(process.env.NEXT_PUBLIC_COGNITO_USER_POOL_CLIENT_ID); const S3_ENDPOINT = z.string().parse(process.env.S3_ENDPOINT ?? ''); const S3_BUCKET = z.string().parse(process.env.S3_BUCKET ?? ''); +const S3_PUBLIC_ENDPOINT = + z.string().url().optional().parse(process.env.S3_PUBLIC_ENDPOINT) ?? + `${S3_ENDPOINT}/${S3_BUCKET}`; const S3_ACCESS_KEY = z.string().parse(process.env.S3_ACCESS_KEY ?? ''); const S3_SECRET_KEY = z.string().parse(process.env.S3_SECRET_KEY ?? ''); const S3_REGION = z.string().parse(process.env.S3_REGION ?? ''); @@ -25,6 +28,7 @@ export { S3_ACCESS_KEY, S3_BUCKET, S3_ENDPOINT, + S3_PUBLIC_ENDPOINT, S3_REGION, S3_SECRET_KEY, SERVER_PORT, diff --git a/server/service/s3Client.ts b/server/service/s3Client.ts index feb94b2..6c73605 100644 --- a/server/service/s3Client.ts +++ b/server/service/s3Client.ts @@ -7,7 +7,14 @@ import { } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import type { MultipartFile } from '@fastify/multipart'; -import { S3_ACCESS_KEY, S3_BUCKET, S3_ENDPOINT, S3_REGION, S3_SECRET_KEY } from './envValues'; +import { + S3_ACCESS_KEY, + S3_BUCKET, + S3_ENDPOINT, + S3_PUBLIC_ENDPOINT, + S3_REGION, + S3_SECRET_KEY, +} from './envValues'; export type S3PutParams = { key: string; data: MultipartFile }; @@ -23,6 +30,7 @@ export const s3Client = new S3Client({ }); export const s3 = { + keyToUrl: (key: string): string => `${S3_PUBLIC_ENDPOINT}/${key}`, getSignedUrl: async (key: string): Promise => { const command = new GetObjectCommand({ Bucket: S3_BUCKET, Key: key });