| ... | ... | @@ -38,6 +38,11 @@ import { |
| 38 | 38 | OrchestrationProjectionPipeline, |
| 39 | 39 | type OrchestrationProjectionPipelineShape, |
| 40 | 40 | } from "../Services/ProjectionPipeline.ts"; |
| 41 | import { |
| 42 | ATTACHMENTS_ROUTE_PREFIX, |
| 43 | IMAGE_EXTENSION_BY_MIME_TYPE, |
| 44 | SAFE_IMAGE_FILE_EXTENSIONS, |
| 45 | } from "../../projectFaviconRoute.ts"; |
| 41 | 46 | |
| 42 | 47 | export const ORCHESTRATION_PROJECTOR_NAMES = { |
| 43 | 48 | projects: "projection.projects", |
| ... | ... | @@ -61,31 +66,6 @@ interface ProjectorDefinition { |
| 61 | 66 | ) => Effect.Effect<void, ProjectionRepositoryError>; |
| 62 | 67 | } |
| 63 | 68 | |
| 64 | | const ATTACHMENTS_ROUTE_PREFIX = "/attachments"; |
| 65 | | const ATTACHMENTS_STATE_SUBDIRECTORY = "attachments"; |
| 66 | | const IMAGE_EXTENSION_BY_MIME_TYPE: Record<string, string> = { |
| 67 | | "image/png": ".png", |
| 68 | | "image/jpeg": ".jpg", |
| 69 | | "image/jpg": ".jpg", |
| 70 | | "image/gif": ".gif", |
| 71 | | "image/webp": ".webp", |
| 72 | | "image/svg+xml": ".svg", |
| 73 | | "image/bmp": ".bmp", |
| 74 | | "image/tiff": ".tiff", |
| 75 | | "image/heic": ".heic", |
| 76 | | }; |
| 77 | | const SAFE_IMAGE_FILE_EXTENSIONS = new Set([ |
| 78 | | ".jpg", |
| 79 | | ".jpeg", |
| 80 | | ".png", |
| 81 | | ".gif", |
| 82 | | ".webp", |
| 83 | | ".bmp", |
| 84 | | ".tiff", |
| 85 | | ".svg", |
| 86 | | ".ico", |
| 87 | | ]); |
| 88 | | |
| 89 | 69 | interface PendingAttachmentWrite { |
| 90 | 70 | readonly absolutePath: string; |
| 91 | 71 | readonly bytes: Uint8Array; |
| ... | ... | @@ -133,7 +113,7 @@ const materializeAttachmentsForProjection = Effect.fn(function* (input: { |
| 133 | 113 | if (Option.isNone(serverConfig)) return input.attachments; |
| 134 | 114 | |
| 135 | 115 | const path = yield* Path.Path; |
| 136 | | const attachmentsRootDir = path.join(serverConfig.value.stateDir, ATTACHMENTS_STATE_SUBDIRECTORY); |
| 116 | const attachmentsRootDir = path.join(serverConfig.value.stateDir, "attachments"); |
| 137 | 117 | const threadSegment = encodeURIComponent(input.threadId); |
| 138 | 118 | const messageSegment = encodeURIComponent(input.messageId); |
| 139 | 119 | |
| ... | ... | @@ -332,10 +312,7 @@ const runAttachmentSideEffects = Effect.fn(function* (input: { |
| 332 | 312 | return; |
| 333 | 313 | } |
| 334 | 314 | |
| 335 | | const attachmentsRootDir = input.path.join( |
| 336 | | serverConfig.value.stateDir, |
| 337 | | ATTACHMENTS_STATE_SUBDIRECTORY, |
| 338 | | ); |
| 315 | const attachmentsRootDir = input.path.join(serverConfig.value.stateDir, "attachments"); |
| 339 | 316 | |
| 340 | 317 | yield* Effect.forEach( |
| 341 | 318 | input.sideEffects.deletedThreadIds, |