forked from mirror/crumbs-original
fix: address PR review comments
- Wrap readFile in try/catch, return 404 for missing attachment files - Remove unused CollaboratorPopover import from NoteCard - Make darkMode a proper $state rune for reactivity (add svelte-runes polyfill for Vitest so $state works in unit tests) - Add error toasts for failed share link toggle (non-2xx responses) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
Fred Cabassut
co-authored by
Claude Opus 4.6
parent
552c2b6265
commit
4eb97b86f9
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Polyfill Svelte 5 runes for Vitest.
|
||||
* The Svelte compiler transforms these in .svelte and .svelte.ts files,
|
||||
* but Vitest doesn't run the Svelte compiler, so we provide plain-JS stubs.
|
||||
*/
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
(globalThis as any).$state = <T>(initial: T): T => initial;
|
||||
(globalThis as any).$derived = <T>(value: T): T => value;
|
||||
(globalThis as any).$effect = (_fn: () => void): void => {};
|
||||
(globalThis as any).$props = (): any => ({});
|
||||
@@ -4,7 +4,6 @@
|
||||
import { renderMarkdown } from '$lib/utils/markdown.js';
|
||||
import { togglePin, trashNote, archiveNote, unarchiveNote, restoreNote, deleteNote, leaveNote, currentFilter } from '$lib/stores/notes.js';
|
||||
import ImageLightbox from './ImageLightbox.svelte';
|
||||
import CollaboratorPopover from './CollaboratorPopover.svelte';
|
||||
import SharingIndicator from './SharingIndicator.svelte';
|
||||
import type { Note } from '$lib/types/index.js';
|
||||
import Undo2 from 'lucide-svelte/icons/undo-2';
|
||||
|
||||
@@ -43,20 +43,24 @@
|
||||
try {
|
||||
if (publicShareToken) {
|
||||
const res = await fetch(`/api/notes/${noteId}/share`, { method: 'DELETE' });
|
||||
if (res.ok) {
|
||||
if (!res.ok) {
|
||||
showToast('Failed to remove share link', 'error');
|
||||
return;
|
||||
}
|
||||
publicShareToken = null;
|
||||
onShareUpdate(null);
|
||||
showToast('Public link removed', 'success');
|
||||
}
|
||||
} else {
|
||||
const res = await fetch(`/api/notes/${noteId}/share`, { method: 'POST' });
|
||||
if (res.ok) {
|
||||
if (!res.ok) {
|
||||
showToast('Failed to create share link', 'error');
|
||||
return;
|
||||
}
|
||||
const data = await res.json();
|
||||
publicShareToken = data.token;
|
||||
onShareUpdate(data.token);
|
||||
showToast('Public link created', 'success');
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
showToast('Failed to update share link', 'error');
|
||||
} finally {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { browser } from '$app/environment';
|
||||
const LIGHT_THEME_COLOR = '#f0e6d3';
|
||||
const DARK_THEME_COLOR = '#1a1715';
|
||||
|
||||
let darkMode = false;
|
||||
let darkMode = $state(false);
|
||||
|
||||
export function getIsDarkMode(): boolean {
|
||||
return darkMode;
|
||||
|
||||
@@ -26,6 +26,7 @@ export const GET: RequestHandler = async ({ params, url, getClientAddress }) =>
|
||||
const filePath = wantThumb && attachment.thumbnailPath ? attachment.thumbnailPath : attachment.path;
|
||||
const mimeType = wantThumb && attachment.thumbnailPath ? 'image/webp' : attachment.mimeType;
|
||||
|
||||
try {
|
||||
const buffer = await readFile(filePath);
|
||||
return new Response(buffer, {
|
||||
headers: {
|
||||
@@ -34,4 +35,7 @@ export const GET: RequestHandler = async ({ params, url, getClientAddress }) =>
|
||||
'Cache-Control': 'public, max-age=3600'
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
throw error(404, 'Attachment not found');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ export default defineConfig({
|
||||
test: {
|
||||
include: ['src/**/*.test.ts'],
|
||||
environment: 'node',
|
||||
setupFiles: ['src/lib/__mocks__/svelte-runes.ts'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'html', 'lcov', 'json-summary'],
|
||||
|
||||
Reference in New Issue
Block a user