cloudflare-docs icon indicating copy to clipboard operation
cloudflare-docs copied to clipboard

Deploy a Svelte site example required for Durable Objects

Open gerhardcit opened this issue 4 months ago • 27 comments

Which Cloudflare product(s) does this pertain to?

Durable Objects

Subject Matter

The way a durableobject class is exported in context of a sveltekit project.

Content Location

https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-site/#sveltekit-cloudflare-configuration

Additional information

The latest create-cloudflare project generates this code in hooks.ts when you select a sveltekit project.

import { dev } from '$app/environment';

/*
  When developing, this hook will add proxy objects to the `platform` object which
  will emulate any bindings defined in `wrangler.toml`.
*/

let platform: App.Platform;

if (dev) {
	const { getPlatformProxy } = await import('wrangler');
	platform = await getPlatformProxy();
}

export const handle = async ({ event, resolve }) => {
	if (platform) {
		event.platform = {
			...event.platform,
			...platform
		};
	}

	return resolve(event);
};

This is great. So now in npm dev node (using sveltekit dev mode) you can easily use KV and R2 (tested) and probably D1 bindings.

However, there is not proper example of how (or where) to export a Durable Object class.. eg: Given this class:

export class DOCounter {
    constructor(state: DurableObjectState, env: Env) { }
    async fetch(request: Request) {
        return new Response("Hello World");
    }
}

WHERE do we put this class so that it forms part of the build process. (It cannot be in a +server.ts or a +page.server.ts file. sveltekit does not like that.

Having this a wrangler.toml config of like this:

[[durable_objects.bindings]]
name = "DO_COUNTER"
class_name = "DOCounter"

migrations
[[migrations]]
tag = "v1"
new_classes = ["DOCounter"]

And a /api/+server.ts file like this:


export const GET: RequestHandler = async ({ request, platform }) => {
    if (!platform) {
        return new Response();
    }
    const env = platform.env;
    if (!env.DO_COUNTER) {
        return new Response('env.DO_COUNTER not found', { status: 404 });
    }
    const id = env.DO_COUNTER.idFromName(new URL(request.url).pathname);
    const stub = env.DO_COUNTER.get(id);
    const response = await stub.fetch(request);
    return response;
};

PLEASE, PLEASE PLEASE create a sveltekit project that works when you do this

  1. npm run build
  2. npx wrangler pages dev .svelte-kit/cloudflare

To prevent this error:

Your worker has access to the following bindings:
- Durable Objects:
  - DO_COUNTER: DOCounter
- KV Namespaces:
  - KVCOUNTER: someKvId
- R2 Buckets:
  - R2_BUCKET: r2-bucket
⎔ Starting local server...
Parsed 2 valid header rules.
✘ [ERROR] service core:user:sveltekit-cloudflare-bindings: Uncaught TypeError: Class extends value undefined is not a constructor or null

    at null.<anonymous> (rrkgcneij6.js:18422:44) in maskDurableObjectDefinition
    at null.<anonymous> (rrkgcneij6.js:18431:18)


✘ [ERROR] MiniflareCoreError [ERR_RUNTIME_FAILURE]: The Workers runtime failed to start. There is likely additional logging output above.

we are soooooo close to getting this in line. But the documentation lacks the full example that provide context of the class.

DurableObjects are easy in a simple cloudflare worker... but NOT in a sveltekit project. Does other frameworks solve this?

gerhardcit avatar Feb 19 '24 17:02 gerhardcit