sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.09k stars 1.83k forks source link

adapter-cloudflare emulated bindings not always available #11996

Open lknlknim opened 3 months ago

lknlknim commented 3 months ago

Describe the bug

My work flow was using miniflare to polyfill the cloudflare platform environment in handle server hooks for local development.

For some of the people may concern it's easy to use wrangler-proxy or cfw-bindings-wrangler-bridge for remote data. Combining with import.meta.env.MODE it's very convenient to switch between dev, preview, live mode for local and remote data.

In the recent adapter update it's doing mostly what miniflare did. I got 2 projects 1 using authjs and another using lucia auth. In the lucia auth project I can remove the manually implemented miniflare part and rely on the adapter for local development. For remote data the bridge is still needed. In the auth js project it's broken as soon as I try to login. It's complaining about platform is undefined and it's trying to access platform.env. Those are implemted in handle server hooks, not sevltekit endpoints.

The lucia auth project is facing the same if I try to move the /google and /google/callback sveltekit endpoints into handle server hooks. It'll complain about platform is undefined.

I'm not familiar to how and when adapter inject the platform into the event object. From my simple testing it seems to inject the platform only when there is +server.ts as a sveltekit endpoint with known route. And no platform is injected when the endpoints logic is implemented in the handle server hooks directly.

Reproduction

Not available in near future

Logs

No response

System Info

-

Severity

annoyance

Additional Information

No response

valterkraemer commented 3 months ago

Ran into the same issue. Did some digging, platform is set here,

https://github.com/sveltejs/kit/blob/6a5d40ef098f63e7e9209bca2058ccf1820bc060/packages/kit/src/runtime/server/respond.js#L295

but it is only called if route is set

https://github.com/sveltejs/kit/blob/6a5d40ef098f63e7e9209bca2058ccf1820bc060/packages/kit/src/runtime/server/respond.js#L216

so

I'm not familiar to how and when adapter inject the platform into the event object. From my simple testing it seems to inject the platform only when there is +server.ts as a sveltekit endpoint with known route. And no platform is injected when the endpoints logic is implemented in the handle server hooks directly.

seems to be the correct assumption

sdarnell commented 3 months ago

Similar issue for me, and I created a simple repro that may help. See branch https://github.com/sdarnell/cf-svelte/tree/bugs/missing-platform

This works fine when directed to the regular page, but it you try to access a a non existent page, e.g. '/wibble' or in another case accessing the favicon seemed to cause the problem.

In the error case, the console will output:

building false url https://localhost:5173/wibble event.platform.env.DB undefined
Missing platform DB
mariusei commented 3 weeks ago

I have the same issue. Thanks for the workaround, @sdarnell!

stephen-trippett commented 2 weeks ago

Same problem. No platform object when running with npm run dev on 404 pages. Everywhere else it works great.

ChristianJacobsen commented 2 weeks ago

This bit my ass as well today, but I solved it with a catch-all route at src/routes/[...catchAll]/+server.ts returning 404.

import { error, type RequestHandler } from '@sveltejs/kit'

export const GET: RequestHandler = async () => {
    error(404, 'Not found')
}

Also fixes silly things like favicon.ico... 🙈

stephen-trippett commented 2 weeks ago

@ChristianJacobsen Good idea! I slightly improved on it by doing a src/routes/[...catchAll]/+page.server.ts instead. This way it uses the normal +error.svelte file as a template.

// NOTE: This file only exists to catch 404 routes so the platform binding works properly in dev mode. It can be deleted when this bug is fixed: https://github.com/sveltejs/kit/issues/11996
import { error } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async () => {
    error(404, { message: "Not found" });
};