| author | |
| committer | |
| log | 58b932ffb8f20566c2c5ac58c252a911c7e80693 |
| tree | 69efaaead2c64e3fe4d68edaefda3d61d64484ce |
| parent | d58af33fba73936659158ba2167a00475889d1e5 |
- Lowercase sanitized thread segments when creating attachment IDs
- Add coverage for mixed-case thread IDs in attachment store and projection pipeline tests3 files changed, 12 insertions(+), 2 deletions(-)
apps/server/src/attachmentStore.test.ts+9| ... | ... | @@ -34,6 +34,15 @@ describe("attachmentStore", () => { |
| 34 | 34 | expect(parseThreadSegmentFromAttachmentId(fooBarId)).toBe("foo-bar"); |
| 35 | 35 | }); |
| 36 | 36 | |
| 37 | it("normalizes created thread segments to lowercase", () => { | |
| 38 | const attachmentId = createAttachmentId("Thread.Foo"); | |
| 39 | expect(attachmentId).toBeTruthy(); | |
| 40 | if (!attachmentId) { | |
| 41 | return; | |
| 42 | } | |
| 43 | expect(parseThreadSegmentFromAttachmentId(attachmentId)).toBe("thread-foo"); | |
| 44 | }); | |
| 45 | ||
| 37 | 46 | it("resolves attachment path by id using the extension that exists on disk", () => { |
| 38 | 47 | const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3code-attachment-store-")); |
| 39 | 48 | try { |
apps/server/src/attachmentStore.ts+1| ... | ... | @@ -23,6 +23,7 @@ const ATTACHMENT_ID_PATTERN = new RegExp( |
| 23 | 23 | export function toSafeThreadAttachmentSegment(threadId: string): string | null { |
| 24 | 24 | const segment = threadId |
| 25 | 25 | .trim() |
| 26 | .toLowerCase() | |
| 26 | 27 | .replace(/[^a-z0-9_-]+/gi, "-") |
| 27 | 28 | .replace(/-+/g, "-") |
| 28 | 29 | .replace(/^[-_]+|[-_]+$/g, "") |
apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts+2-2| ... | ... | @@ -733,7 +733,7 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { |
| 733 | 733 | const projectionPipeline = yield* OrchestrationProjectionPipeline; |
| 734 | 734 | const eventStore = yield* OrchestrationEventStore; |
| 735 | 735 | const now = new Date().toISOString(); |
| 736 | const threadId = ThreadId.makeUnsafe("thread revert.files"); | |
| 736 | const threadId = ThreadId.makeUnsafe("Thread Revert.Files"); | |
| 737 | 737 | const keepAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000001"; |
| 738 | 738 | const removeAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000002"; |
| 739 | 739 | const otherThreadAttachmentId = |
| ... | ... | @@ -948,7 +948,7 @@ projectionLayer("OrchestrationProjectionPipeline", (it) => { |
| 948 | 948 | const projectionPipeline = yield* OrchestrationProjectionPipeline; |
| 949 | 949 | const eventStore = yield* OrchestrationEventStore; |
| 950 | 950 | const now = new Date().toISOString(); |
| 951 | const threadId = ThreadId.makeUnsafe("thread delete.files"); | |
| 951 | const threadId = ThreadId.makeUnsafe("Thread Delete.Files"); | |
| 952 | 952 | const attachmentId = "thread-delete-files-00000000-0000-4000-8000-000000000001"; |
| 953 | 953 | const otherThreadAttachmentId = |
| 954 | 954 | "thread-delete-files-extra-00000000-0000-4000-8000-000000000002"; |