upd wiki on chachy

This commit is contained in:
d-chrka 2026-03-15 11:25:35 +01:00
parent 64b5a82498
commit f28dc954e8
11 changed files with 133 additions and 97 deletions

View File

@ -40,7 +40,8 @@
"Bash(paru -S --noconfirm visual-studio-code-bin)", "Bash(paru -S --noconfirm visual-studio-code-bin)",
"Bash(code --version)", "Bash(code --version)",
"Bash(code --install-extension svelte.svelte-vscode --install-extension bradlc.vscode-tailwindcss --install-extension esbenp.prettier-vscode --install-extension dbaeumer.vscode-eslint)", "Bash(code --install-extension svelte.svelte-vscode --install-extension bradlc.vscode-tailwindcss --install-extension esbenp.prettier-vscode --install-extension dbaeumer.vscode-eslint)",
"Bash(git config:*)" "Bash(git config:*)",
"Bash(FILE=\"/home/d-chrka@internal.lan/Projekte/chrka/Ka-Note/ka-note/client/src/routes/wiki/[id]/+page.svelte\"\npython3 - \"$FILE\" <<'EOF'\nimport sys\npath = sys.argv[1]\nwith open\\(path, 'r'\\) as f:\n content = f.read\\(\\)\n\nold = '\\\\t\\\\t\\\\t\\\\t<input\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tclass=\"flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted\"'\nnew = '\\\\t\\\\t\\\\t\\\\t<input\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tbind:this={titleInputEl}\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tclass=\"flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted\"'\n\nif old in content:\n content = content.replace\\(old, new, 1\\)\n with open\\(path, 'w'\\) as f:\n f.write\\(content\\)\n print\\(\"replaced\"\\)\nelse:\n print\\(\"NOT FOUND\"\\)\n # debug: show actual bytes around the area\n idx = content.find\\('<input'\\)\n print\\(repr\\(content[idx:idx+100]\\)\\)\nEOF)"
] ]
} }
} }

View File

@ -1 +1 @@
1.2.37 1.2.47

View File

@ -2,7 +2,7 @@
import { page } from '$app/state'; import { page } from '$app/state';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { db } from '$lib/db/schema'; import { db } from '$lib/db/schema';
import { upsertPage, softDeletePage, togglePageFavorite, getNotebooksForPage, getBacklinksForPage, assignPageToNotebook, removePageFromNotebook, getAllNotebooks } from '$lib/db/repositories'; import { upsertPage, softDeletePage, togglePageFavorite, getNotebooksForPage, getBacklinksForPage, assignPageToNotebook, removePageFromNotebook, getAllNotebooks, createPage } from '$lib/db/repositories';
import MarkdownEditor from '$lib/components/MarkdownEditor.svelte'; import MarkdownEditor from '$lib/components/MarkdownEditor.svelte';
import RenderedMarkdown from '$lib/components/RenderedMarkdown.svelte'; import RenderedMarkdown from '$lib/components/RenderedMarkdown.svelte';
import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
@ -23,6 +23,7 @@
let autosaveTimer: ReturnType<typeof setTimeout> | undefined; let autosaveTimer: ReturnType<typeof setTimeout> | undefined;
let titleInput = $state(''); let titleInput = $state('');
let titleInputEl = $state<HTMLInputElement | undefined>();
let editorRef: MarkdownEditor | undefined = $state(); let editorRef: MarkdownEditor | undefined = $state();
let notebooks = $state<Notebook[]>([]); let notebooks = $state<Notebook[]>([]);
let backlinks = $state<Page[]>([]); let backlinks = $state<Page[]>([]);
@ -37,9 +38,10 @@
// Re-initialize whenever pageId changes (SvelteKit reuses component on param navigation) // Re-initialize whenever pageId changes (SvelteKit reuses component on param navigation)
$effect(() => { $effect(() => {
const id = pageId; // track reactively const id = pageId; // track reactively
const openInEdit = page.url.searchParams.get('edit') === '1';
currentPage = undefined; currentPage = undefined;
titleInitialized = false; titleInitialized = false;
editing = false; editing = openInEdit;
notebooks = []; notebooks = [];
backlinks = []; backlinks = [];
db.pages.get(id).then(p => { db.pages.get(id).then(p => {
@ -58,6 +60,10 @@
if (currentPage && !titleInitialized) { if (currentPage && !titleInitialized) {
titleInput = currentPage.title; titleInput = currentPage.title;
titleInitialized = true; titleInitialized = true;
if (editing) {
// focus title on next tick so the input is rendered
setTimeout(() => titleInputEl?.focus(), 0);
}
} }
}); });
@ -88,6 +94,14 @@
currentPage = { ...currentPage!, title }; currentPage = { ...currentPage!, title };
} }
async function addPage() {
const newPage = await createPage('Neue Seite', scope === 'private');
for (const nb of notebooks) {
await assignPageToNotebook(newPage.id, nb.id);
}
goto(`/wiki/${newPage.id}?edit=1`);
}
async function handleDelete() { async function handleDelete() {
await softDeletePage(pageId); await softDeletePage(pageId);
goto('/wiki'); goto('/wiki');
@ -118,6 +132,7 @@
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
{#if editing} {#if editing}
<input <input
bind:this={titleInputEl}
class="flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted" class="flex-1 bg-transparent text-2xl font-bold text-white outline-none placeholder:text-muted"
bind:value={titleInput} bind:value={titleInput}
onblur={saveTitle} onblur={saveTitle}
@ -153,6 +168,13 @@
> >
{editing ? '✓ Fertig' : '✎ Bearbeiten'} {editing ? '✓ Fertig' : '✎ Bearbeiten'}
</button> </button>
{#if !editing}
<button
class="rounded px-3 py-1.5 text-sm font-medium bg-white/10 text-[#ccc] hover:bg-white/20 hover:text-white transition-colors"
onclick={addPage}
title="Neue Seite mit gleichem Scope und Notizbüchern anlegen"
>+ Neue Seite</button>
{/if}
{#if editing} {#if editing}
<span class="text-xs {savedState === 'saved' ? 'text-muted' : savedState === 'saving' ? 'text-muted animate-pulse' : 'text-warning'}"> <span class="text-xs {savedState === 'saved' ? 'text-muted' : savedState === 'saving' ? 'text-muted animate-pulse' : 'text-warning'}">
{savedState === 'saved' ? '✓ gespeichert' : savedState === 'saving' ? '…' : '● ungespeichert'} {savedState === 'saved' ? '✓ gespeichert' : savedState === 'saving' ? '…' : '● ungespeichert'}
@ -204,7 +226,8 @@
<!-- Content: read or edit --> <!-- Content: read or edit -->
{#if editing} {#if editing}
<div class="rounded border border-accent/40 bg-sidebar/50 p-3 min-h-[300px]"> <!-- svelte-ignore a11y_no_static_element_interactions -->
<div class="rounded border border-accent/40 bg-sidebar/50 p-3 min-h-[300px]" ondblclick={(e) => { if (!(e.target as Element).closest('.cm-editor')) switchToRead(); }}>
<MarkdownEditor <MarkdownEditor
bind:this={editorRef} bind:this={editorRef}
content={currentPage.body} content={currentPage.body}

View File

@ -29,9 +29,9 @@ export default defineConfig({
}) })
], ],
server: { server: {
host: '127.0.0.1', host: 'localhost',
proxy: { proxy: {
'/api': 'http://127.0.0.1:9000' '/api': 'http://localhost:9000'
}, },
headers: { headers: {
'Cache-Control': 'no-store' 'Cache-Control': 'no-store'

View File

@ -1,8 +1,10 @@
<# <#
.PARAMETER CheckOnly .PARAMETER CheckOnly
Download and verify the prod DB without building or deploying. Download and verify the prod DB without building or deploying.
.PARAMETER SkipDbBackup
Skip the DB download/verification step (use when DB hasn't changed since last run).
#> #>
param([switch]$CheckOnly) param([switch]$CheckOnly, [switch]$SkipDbBackup)
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
@ -34,60 +36,66 @@ if ($CheckOnly) {
$checkLabel = if ($CheckOnly) { " [check-only]" } else { "" } $checkLabel = if ($CheckOnly) { " [check-only]" } else { "" }
Write-Host "=== Version: $VERSION$checkLabel ===" -ForegroundColor Yellow Write-Host "=== Version: $VERSION$checkLabel ===" -ForegroundColor Yellow
Write-Host "=== Backup DB from Prod ===" -ForegroundColor Cyan
$KuduToken = az account get-access-token --resource "https://management.azure.com" --query accessToken -o tsv
if ($LASTEXITCODE -ne 0) { throw "Failed to get Azure access token" }
$KuduDbUrl = "https://${APP}.scm.azurewebsites.net/api/vfs/data/ka-note.db" $KuduDbUrl = "https://${APP}.scm.azurewebsites.net/api/vfs/data/ka-note.db"
$AppUrl = "https://$APP.azurewebsites.net"
$BackupDir = Join-Path $PSScriptRoot "backups" $BackupDir = Join-Path $PSScriptRoot "backups"
$null = New-Item -ItemType Directory -Path $BackupDir -Force $null = New-Item -ItemType Directory -Path $BackupDir -Force
$BackupFile = Join-Path $BackupDir ("ka-note-pre-deploy-$VERSION.db") $BackupFile = Join-Path $BackupDir ("ka-note-pre-deploy-$VERSION.db")
# Flush WAL before download so the snapshot is consistent (WAL file not included in Kudu download). if ($SkipDbBackup) {
$AppUrl = "https://$APP.azurewebsites.net" Write-Host "=== Skipping DB Backup (-SkipDbBackup) ===" -ForegroundColor Yellow
if ($env:KA_NOTE_DEPLOY_API_KEY) { $KuduToken = $null
Write-Host " Flushing WAL checkpoint before download..." -ForegroundColor DarkGray
try {
$cpResult = Invoke-RestMethod -Uri "$AppUrl/api/admin/checkpoint" -Method POST `
-Headers @{ Authorization = "Bearer $env:KA_NOTE_DEPLOY_API_KEY" } `
-UseBasicParsing -TimeoutSec 30
Write-Host " Checkpoint: $($cpResult.checkpointed)/$($cpResult.log) pages" -ForegroundColor DarkGray
} catch {
Write-Host " Checkpoint call failed (continuing anyway): $_" -ForegroundColor Yellow
}
} else { } else {
Write-Host " KA_NOTE_DEPLOY_API_KEY not set, skipping WAL checkpoint" -ForegroundColor Yellow Write-Host "=== Backup DB from Prod ===" -ForegroundColor Cyan
} $KuduToken = az account get-access-token --resource "https://management.azure.com" --query accessToken -o tsv
if ($LASTEXITCODE -ne 0) { throw "Failed to get Azure access token" }
Write-Host " Downloading ka-note.db from prod..." -ForegroundColor DarkGray # Flush WAL before download so the snapshot is consistent (WAL file not included in Kudu download).
try { if ($env:KA_NOTE_DEPLOY_API_KEY) {
Invoke-WebRequest -Uri $KuduDbUrl ` Write-Host " Flushing WAL checkpoint before download..." -ForegroundColor DarkGray
-Headers @{ Authorization = "Bearer $KuduToken" } ` try {
-OutFile $BackupFile -UseBasicParsing $cpResult = Invoke-RestMethod -Uri "$AppUrl/api/admin/checkpoint" -Method POST `
} catch { -Headers @{ Authorization = "Bearer $env:KA_NOTE_DEPLOY_API_KEY" } `
throw "Kudu DB download failed: $_" -UseBasicParsing -TimeoutSec 30
} Write-Host " Checkpoint: $($cpResult.checkpointed)/$($cpResult.log) pages" -ForegroundColor DarkGray
} catch {
Write-Host " Checkpoint call failed (continuing anyway): $_" -ForegroundColor Yellow
}
} else {
Write-Host " KA_NOTE_DEPLOY_API_KEY not set, skipping WAL checkpoint" -ForegroundColor Yellow
}
$DbSize = (Get-Item $BackupFile).Length Write-Host " Downloading ka-note.db from prod..." -ForegroundColor DarkGray
Write-Host " Downloaded: $([math]::Round($DbSize/1KB,1)) KB" -ForegroundColor DarkGray try {
Invoke-WebRequest -Uri $KuduDbUrl `
-Headers @{ Authorization = "Bearer $KuduToken" } `
-OutFile $BackupFile -UseBasicParsing
} catch {
throw "Kudu DB download failed: $_"
}
if ($DbSize -lt 4096) { $DbSize = (Get-Item $BackupFile).Length
throw "DB backup is suspiciously small ($DbSize bytes) - aborting deploy" Write-Host " Downloaded: $([math]::Round($DbSize/1KB,1)) KB" -ForegroundColor DarkGray
}
# Verify with sqlite3 (must be in PATH) if ($DbSize -lt 4096) {
$IntegrityResult = & sqlite3 $BackupFile "PRAGMA integrity_check;" 2>&1 throw "DB backup is suspiciously small ($DbSize bytes) - aborting deploy"
if ($LASTEXITCODE -ne 0 -or $IntegrityResult -ne 'ok') { }
throw "DB integrity_check FAILED: $IntegrityResult - aborting deploy. Backup saved at $BackupFile"
}
Write-Host " integrity_check: ok ($([math]::Round($DbSize/1KB,1)) KB)" -ForegroundColor Green # Verify with sqlite3 (must be in PATH)
$IntegrityResult = & sqlite3 $BackupFile "PRAGMA integrity_check;" 2>&1
if ($LASTEXITCODE -ne 0 -or $IntegrityResult -ne 'ok') {
throw "DB integrity_check FAILED: $IntegrityResult - aborting deploy. Backup saved at $BackupFile"
}
if ($CheckOnly) { Write-Host " integrity_check: ok ($([math]::Round($DbSize/1KB,1)) KB)" -ForegroundColor Green
Write-Host ""
Write-Host "=== Check passed -- no deploy performed ===" -ForegroundColor Green if ($CheckOnly) {
Write-Host " Backup: $BackupFile" -ForegroundColor DarkGray Write-Host ""
Write-Host "" Write-Host "=== Check passed -- no deploy performed ===" -ForegroundColor Green
exit 0 Write-Host " Backup: $BackupFile" -ForegroundColor DarkGray
Write-Host ""
exit 0
}
} }
# Bump version now that DB check passed # Bump version now that DB check passed
@ -209,6 +217,10 @@ while ($keepValidating) {
$keepValidating = $true $keepValidating = $true
} elseif ($answer -eq 'yes') { } elseif ($answer -eq 'yes') {
Write-Host " Uploading backup to prod..." -ForegroundColor Cyan Write-Host " Uploading backup to prod..." -ForegroundColor Cyan
if (-not $KuduToken) {
$KuduToken = az account get-access-token --resource "https://management.azure.com" --query accessToken -o tsv
if ($LASTEXITCODE -ne 0) { throw "Failed to get Azure access token for restore" }
}
Invoke-WebRequest -Uri $KuduDbUrl ` Invoke-WebRequest -Uri $KuduDbUrl `
-Method PUT ` -Method PUT `
-Headers @{ Authorization = "Bearer $KuduToken" } ` -Headers @{ Authorization = "Bearer $KuduToken" } `

View File

@ -1,4 +1,46 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_contexts` (
`id` text NOT NULL,
`user_id` text NOT NULL,
`name` text NOT NULL,
`type` text NOT NULL,
`sort_order` integer DEFAULT 0 NOT NULL,
`meta` text,
`archived_at` text,
`is_favorite` integer DEFAULT false NOT NULL,
`updated_at` text NOT NULL,
`deleted_at` text,
`version` integer DEFAULT 1 NOT NULL,
PRIMARY KEY(`id`, `user_id`)
);
--> statement-breakpoint
INSERT INTO `__new_contexts`("id", "user_id", "name", "type", "sort_order", "meta", "archived_at", "is_favorite", "updated_at", "deleted_at", "version") SELECT "id", '', "name", "type", "sort_order", "meta", "archived_at", "is_favorite", "updated_at", "deleted_at", "version" FROM `contexts`;--> statement-breakpoint
DROP TABLE `contexts`;--> statement-breakpoint
ALTER TABLE `__new_contexts` RENAME TO `contexts`;--> statement-breakpoint
CREATE INDEX `contexts_updated_at_idx` ON `contexts` (`updated_at`);--> statement-breakpoint
CREATE INDEX `contexts_user_id_idx` ON `contexts` (`user_id`);--> statement-breakpoint
CREATE TABLE `__new_topics` (
`id` text NOT NULL,
`user_id` text NOT NULL,
`context_id` text NOT NULL,
`title` text NOT NULL,
`status` text DEFAULT 'active' NOT NULL,
`snooze_until` text,
`sort_order` integer DEFAULT 0 NOT NULL,
`is_new` integer DEFAULT true NOT NULL,
`updated_at` text NOT NULL,
`deleted_at` text,
`version` integer DEFAULT 1 NOT NULL,
PRIMARY KEY(`id`, `user_id`),
FOREIGN KEY (`context_id`,`user_id`) REFERENCES `contexts`(`id`,`user_id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_topics`("id", "user_id", "context_id", "title", "status", "snooze_until", "sort_order", "is_new", "updated_at", "deleted_at", "version") SELECT "id", '', "context_id", "title", "status", "snooze_until", "sort_order", "is_new", "updated_at", "deleted_at", "version" FROM `topics`;--> statement-breakpoint
DROP TABLE `topics`;--> statement-breakpoint
ALTER TABLE `__new_topics` RENAME TO `topics`;--> statement-breakpoint
CREATE INDEX `topics_updated_at_idx` ON `topics` (`updated_at`);--> statement-breakpoint
CREATE INDEX `topics_context_id_idx` ON `topics` (`context_id`);--> statement-breakpoint
CREATE INDEX `topics_user_id_idx` ON `topics` (`user_id`);--> statement-breakpoint
CREATE TABLE `__new_history_entries` ( CREATE TABLE `__new_history_entries` (
`id` text NOT NULL, `id` text NOT NULL,
`user_id` text NOT NULL, `user_id` text NOT NULL,
@ -18,7 +60,6 @@ CREATE TABLE `__new_history_entries` (
INSERT INTO `__new_history_entries`("id", "user_id", "topic_id", "date", "text", "sort_order", "linked_context_id", "done_at", "updated_at", "deleted_at", "version") SELECT "id", '', "topic_id", "date", "text", "sort_order", "linked_context_id", "done_at", "updated_at", "deleted_at", "version" FROM `history_entries`;--> statement-breakpoint INSERT INTO `__new_history_entries`("id", "user_id", "topic_id", "date", "text", "sort_order", "linked_context_id", "done_at", "updated_at", "deleted_at", "version") SELECT "id", '', "topic_id", "date", "text", "sort_order", "linked_context_id", "done_at", "updated_at", "deleted_at", "version" FROM `history_entries`;--> statement-breakpoint
DROP TABLE `history_entries`;--> statement-breakpoint DROP TABLE `history_entries`;--> statement-breakpoint
ALTER TABLE `__new_history_entries` RENAME TO `history_entries`;--> statement-breakpoint ALTER TABLE `__new_history_entries` RENAME TO `history_entries`;--> statement-breakpoint
PRAGMA foreign_keys=ON;--> statement-breakpoint
CREATE INDEX `history_entries_updated_at_idx` ON `history_entries` (`updated_at`);--> statement-breakpoint CREATE INDEX `history_entries_updated_at_idx` ON `history_entries` (`updated_at`);--> statement-breakpoint
CREATE INDEX `history_entries_topic_id_idx` ON `history_entries` (`topic_id`);--> statement-breakpoint CREATE INDEX `history_entries_topic_id_idx` ON `history_entries` (`topic_id`);--> statement-breakpoint
CREATE INDEX `history_entries_user_id_idx` ON `history_entries` (`user_id`);--> statement-breakpoint CREATE INDEX `history_entries_user_id_idx` ON `history_entries` (`user_id`);--> statement-breakpoint
@ -44,45 +85,4 @@ ALTER TABLE `__new_ratings` RENAME TO `ratings`;--> statement-breakpoint
CREATE INDEX `ratings_updated_at_idx` ON `ratings` (`updated_at`);--> statement-breakpoint CREATE INDEX `ratings_updated_at_idx` ON `ratings` (`updated_at`);--> statement-breakpoint
CREATE INDEX `ratings_topic_id_idx` ON `ratings` (`topic_id`);--> statement-breakpoint CREATE INDEX `ratings_topic_id_idx` ON `ratings` (`topic_id`);--> statement-breakpoint
CREATE INDEX `ratings_user_id_idx` ON `ratings` (`user_id`);--> statement-breakpoint CREATE INDEX `ratings_user_id_idx` ON `ratings` (`user_id`);--> statement-breakpoint
CREATE TABLE `__new_topics` ( PRAGMA foreign_keys=ON;
`id` text NOT NULL,
`user_id` text NOT NULL,
`context_id` text NOT NULL,
`title` text NOT NULL,
`status` text DEFAULT 'active' NOT NULL,
`snooze_until` text,
`sort_order` integer DEFAULT 0 NOT NULL,
`is_new` integer DEFAULT true NOT NULL,
`updated_at` text NOT NULL,
`deleted_at` text,
`version` integer DEFAULT 1 NOT NULL,
PRIMARY KEY(`id`, `user_id`),
FOREIGN KEY (`context_id`,`user_id`) REFERENCES `contexts`(`id`,`user_id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_topics`("id", "user_id", "context_id", "title", "status", "snooze_until", "sort_order", "is_new", "updated_at", "deleted_at", "version") SELECT "id", '', "context_id", "title", "status", "snooze_until", "sort_order", "is_new", "updated_at", "deleted_at", "version" FROM `topics`;--> statement-breakpoint
DROP TABLE `topics`;--> statement-breakpoint
ALTER TABLE `__new_topics` RENAME TO `topics`;--> statement-breakpoint
CREATE INDEX `topics_updated_at_idx` ON `topics` (`updated_at`);--> statement-breakpoint
CREATE INDEX `topics_context_id_idx` ON `topics` (`context_id`);--> statement-breakpoint
CREATE INDEX `topics_user_id_idx` ON `topics` (`user_id`);--> statement-breakpoint
CREATE TABLE `__new_contexts` (
`id` text NOT NULL,
`user_id` text NOT NULL,
`name` text NOT NULL,
`type` text NOT NULL,
`sort_order` integer DEFAULT 0 NOT NULL,
`meta` text,
`archived_at` text,
`is_favorite` integer DEFAULT false NOT NULL,
`updated_at` text NOT NULL,
`deleted_at` text,
`version` integer DEFAULT 1 NOT NULL,
PRIMARY KEY(`id`, `user_id`)
);
--> statement-breakpoint
INSERT INTO `__new_contexts`("id", "user_id", "name", "type", "sort_order", "meta", "archived_at", "is_favorite", "updated_at", "deleted_at", "version") SELECT "id", '', "name", "type", "sort_order", "meta", "archived_at", "is_favorite", "updated_at", "deleted_at", "version" FROM `contexts`;--> statement-breakpoint
DROP TABLE `contexts`;--> statement-breakpoint
ALTER TABLE `__new_contexts` RENAME TO `contexts`;--> statement-breakpoint
CREATE INDEX `contexts_updated_at_idx` ON `contexts` (`updated_at`);--> statement-breakpoint
CREATE INDEX `contexts_user_id_idx` ON `contexts` (`user_id`);

Binary file not shown.

Binary file not shown.

View File

@ -48,7 +48,7 @@ router.post('/', handle('api-keys/create', async (c) => {
router.delete('/:id', handle('api-keys/delete', async (c) => { router.delete('/:id', handle('api-keys/delete', async (c) => {
const { userId } = c.get('auth'); const { userId } = c.get('auth');
const id = c.req.param('id'); const id = c.req.param('id')!;
const result = await db const result = await db
.update(apiKeys) .update(apiKeys)

View File

@ -67,7 +67,7 @@ backup.get('/list', handle('backup/list', async (c) => {
// Download a stored backup file // Download a stored backup file
backup.get('/download/:filename', handle('backup/download', async (c) => { backup.get('/download/:filename', handle('backup/download', async (c) => {
const filename = c.req.param('filename'); const filename = c.req.param('filename')!;
let filePath: string; let filePath: string;
try { try {
filePath = backupFilePath(filename); filePath = backupFilePath(filename);
@ -85,7 +85,7 @@ backup.get('/download/:filename', handle('backup/download', async (c) => {
// Delete a stored backup // Delete a stored backup
backup.delete('/:filename', handle('backup/delete', async (c) => { backup.delete('/:filename', handle('backup/delete', async (c) => {
const filename = c.req.param('filename'); const filename = c.req.param('filename')!;
try { try {
await deleteBackup(filename); await deleteBackup(filename);
} catch (e: unknown) { } catch (e: unknown) {

View File

@ -56,7 +56,7 @@ sync.get('/pull', handle('sync/pull', async (c) => {
sync.get('/blob/:id', handle('sync/blob', async (c) => { sync.get('/blob/:id', handle('sync/blob', async (c) => {
const { userId } = c.get('auth'); const { userId } = c.get('auth');
const id = c.req.param('id'); const id = c.req.param('id')!;
const blob = await fetchBlob(id, userId); const blob = await fetchBlob(id, userId);
if (!blob) return c.json({ error: 'Not found' }, 404); if (!blob) return c.json({ error: 'Not found' }, 404);
return c.json(blob); return c.json(blob);