feat: upgrade to SvelteKit 3 and adapter-bun
Some checks failed
Test and deploy staging / staging (push) Failing after 43s
Some checks failed
Test and deploy staging / staging (push) Failing after 43s
Run the sveltekit-3 migration and finish its manual tasks:
- Move kit config into the sveltekit() Vite plugin; drop svelte.config.js
- Replace $lib with #lib subpath imports
- Declare env vars in src/env.ts and import them from $app/env/{private,public}
- Consolidate param matchers into src/params.ts
- Use error(status, message), Response.json, refreshAll and goto reset/shallow
- Fall back to a full page load when goto rejects a login return path
Switch from adapter-node to adapter-bun: the build script runs Vite under
Bun (the adapter requires it) and the image starts with `bun ./build`.
Runtime env names (PORT, BODY_SIZE_LIMIT, ADDRESS_HEADER, ...) are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { db } from '$lib/server/db';
|
||||
import { listItemCompletions, lists } from '$lib/server/db/schema';
|
||||
import { requireAdmin } from '$lib/server/authorization';
|
||||
import { uniqueListSlug } from '$lib/server/slugify';
|
||||
import { listImageUrl } from '$lib/server/r2';
|
||||
import { db } from '#lib/server/db/index.js';
|
||||
import { listItemCompletions, lists } from '#lib/server/db/schema/index.js';
|
||||
import { requireAdmin } from '#lib/server/authorization.js';
|
||||
import { uniqueListSlug } from '#lib/server/slugify.js';
|
||||
import { listImageUrl } from '#lib/server/r2.js';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { fail, redirect } from '@sveltejs/kit';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
onMount(() => {
|
||||
hydrated = true;
|
||||
});
|
||||
import { NativeSelect } from '$lib/components/ui/native-select/index.js';
|
||||
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||
import { enhance } from '$app/forms';
|
||||
import { NativeSelect } from '#lib/components/ui/native-select/index.js';
|
||||
import * as Dialog from '#lib/components/ui/dialog/index.js';
|
||||
import { enhance, type SubmitFunction } from '$app/forms';
|
||||
import { resolve } from '$app/paths';
|
||||
import ProgressBar from '$lib/components/ProgressBar.svelte';
|
||||
import ListPictureDropzone from '$lib/components/ListPictureDropzone.svelte';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import type { SubmitFunction } from '@sveltejs/kit';
|
||||
import ProgressBar from '#lib/components/ProgressBar.svelte';
|
||||
import ListPictureDropzone from '#lib/components/ListPictureDropzone.svelte';
|
||||
import { Button } from '#lib/components/ui/button/index.js';
|
||||
import { Input } from '#lib/components/ui/input/index.js';
|
||||
import type { PageProps } from './$types';
|
||||
let { data, form }: PageProps = $props();
|
||||
let uploadError = $state('');
|
||||
@@ -36,7 +35,7 @@
|
||||
try {
|
||||
const body = new FormData();
|
||||
body.set('picture', picture);
|
||||
const response = await fetch(resolve('/lists/api/upload'), { method: 'POST', body });
|
||||
const response = await fetch(resolve('lists/api/upload'), { method: 'POST', body });
|
||||
if (!response.ok) throw new Error('Could not upload the image. Please try again.');
|
||||
const { key } = await response.json();
|
||||
formData.set('pictureKey', key);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '$lib/server/db';
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { lists, listItems, listItemCompletions } from '$lib/server/db/schema';
|
||||
import { requireAdmin, requireUser } from '$lib/server/authorization';
|
||||
import { deleteObject, listImageKey, listImageUrl } from '$lib/server/r2';
|
||||
import { validSlug } from '$lib/server/slugify';
|
||||
import { db } from '#lib/server/db/index.js';
|
||||
import { ORIGIN } from '$app/env/private';
|
||||
import { lists, listItems, listItemCompletions } from '#lib/server/db/schema/index.js';
|
||||
import { requireAdmin, requireUser } from '#lib/server/authorization.js';
|
||||
import { deleteObject, listImageKey, listImageUrl } from '#lib/server/r2.js';
|
||||
import { validSlug } from '#lib/server/slugify.js';
|
||||
import { and, eq, ne } from 'drizzle-orm';
|
||||
import { error, fail, redirect } from '@sveltejs/kit';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
@@ -15,7 +15,7 @@ async function currentList(slug: string) {
|
||||
}
|
||||
async function removeStoredPicture(url: string | null) {
|
||||
// Development and staging may reference pictures copied from production.
|
||||
if (env.ORIGIN !== 'https://stanrunge.dev') return;
|
||||
if (ORIGIN !== 'https://stanrunge.dev') return;
|
||||
const key = url ? listImageKey(url) : null;
|
||||
if (!key) return;
|
||||
try {
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { NativeSelect } from '$lib/components/ui/native-select/index.js';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import { Textarea } from '$lib/components/ui/textarea/index.js';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
|
||||
import * as Collapsible from '$lib/components/ui/collapsible/index.js';
|
||||
import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
|
||||
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import { NativeSelect } from '#lib/components/ui/native-select/index.js';
|
||||
import { Input } from '#lib/components/ui/input/index.js';
|
||||
import { Textarea } from '#lib/components/ui/textarea/index.js';
|
||||
import { Checkbox } from '#lib/components/ui/checkbox/index.js';
|
||||
import * as Collapsible from '#lib/components/ui/collapsible/index.js';
|
||||
import * as AlertDialog from '#lib/components/ui/alert-dialog/index.js';
|
||||
import * as Dialog from '#lib/components/ui/dialog/index.js';
|
||||
import { Button } from '#lib/components/ui/button/index.js';
|
||||
let addOpen = $state(false);
|
||||
import { resolve } from '$app/paths';
|
||||
import ArrowLeft from 'lucide-svelte/icons/arrow-left';
|
||||
import Check from 'lucide-svelte/icons/check';
|
||||
import { enhance } from '$app/forms';
|
||||
import ListPictureDropzone from '$lib/components/ListPictureDropzone.svelte';
|
||||
import ProgressBar from '$lib/components/ProgressBar.svelte';
|
||||
import type { SubmitFunction } from '@sveltejs/kit';
|
||||
import { enhance, type SubmitFunction } from '$app/forms';
|
||||
import ListPictureDropzone from '#lib/components/ListPictureDropzone.svelte';
|
||||
import ProgressBar from '#lib/components/ProgressBar.svelte';
|
||||
import type { PageProps } from './$types';
|
||||
let { data, form }: PageProps = $props();
|
||||
let completed = $derived(new Set(data.completedIds));
|
||||
@@ -60,7 +59,7 @@
|
||||
try {
|
||||
const uploadForm = new FormData();
|
||||
uploadForm.set('picture', picture);
|
||||
const uploaded = await fetch(resolve('/lists/api/upload'), {
|
||||
const uploaded = await fetch(resolve('lists/api/upload'), {
|
||||
method: 'POST',
|
||||
body: uploadForm
|
||||
});
|
||||
@@ -79,7 +78,7 @@
|
||||
|
||||
<section class="mx-auto max-w-4xl space-y-6 px-4 py-10 sm:px-6 sm:py-14">
|
||||
<a
|
||||
href={resolve('/lists')}
|
||||
href={resolve('lists')}
|
||||
class="inline-flex items-center gap-1 text-base text-[var(--site-muted)] hover:text-[var(--site-text)]"
|
||||
><ArrowLeft size={16} aria-hidden="true" /> lists</a
|
||||
>
|
||||
@@ -123,8 +122,8 @@
|
||||
</div>
|
||||
{:else}
|
||||
<p>
|
||||
<a class="underline" href={resolve(`/login?returnTo=/lists/${data.list.slug}`)}>Log in</a> to
|
||||
save your progress.
|
||||
<a class="underline" href={resolve(`login?returnTo=/lists/${data.list.slug}`)}>Log in</a> to save
|
||||
your progress.
|
||||
</p>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import { requireAdmin } from '$lib/server/authorization';
|
||||
import { uploadImage } from '$lib/server/r2';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { requireAdmin } from '#lib/server/authorization.js';
|
||||
import { uploadImage } from '#lib/server/r2.js';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
@@ -16,7 +16,7 @@ export const POST: RequestHandler = async (event) => {
|
||||
if (!picture.size || picture.size > 5 * 1024 * 1024)
|
||||
error(400, 'Images must be 5 MB or smaller.');
|
||||
try {
|
||||
return json(await uploadImage(picture, 'lists'));
|
||||
return Response.json(await uploadImage(picture, 'lists'));
|
||||
} catch (cause) {
|
||||
console.error('List image upload failed', cause);
|
||||
error(503, 'Image storage is unavailable.');
|
||||
|
||||
Reference in New Issue
Block a user