From aec2c16d8cd3748d2ce694b76f868243f7ff88af Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Thu, 10 Jul 2025 13:29:31 +0200 Subject: Add durable object --- src/pages/api/counter.ts | 59 ++++++++++++++++++++++++++++++++++++++++++ src/worker.ts | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/pages/api/counter.ts create mode 100644 src/worker.ts (limited to 'src') diff --git a/src/pages/api/counter.ts b/src/pages/api/counter.ts new file mode 100644 index 0000000..152dc54 --- /dev/null +++ b/src/pages/api/counter.ts @@ -0,0 +1,59 @@ +import type { APIRoute } from 'astro'; + +interface Env { + COUNTER_DO: DurableObjectNamespace; +} + +export const GET: APIRoute = async ({ request }) => { + const env = request.cf?.env as Env; + if (!env?.COUNTER_DO) { + return new Response(JSON.stringify({ error: 'Durable Object not available' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } + + const id = env.COUNTER_DO.idFromName('global-counter'); + const stub = env.COUNTER_DO.get(id); + + const response = await stub.fetch(new Request('https://counter.do/get')); + const data = await response.json(); + + return new Response(JSON.stringify(data), { + headers: { 'Content-Type': 'application/json' } + }); +}; + +export const POST: APIRoute = async ({ request }) => { + const env = request.cf?.env as Env; + if (!env?.COUNTER_DO) { + return new Response(JSON.stringify({ error: 'Durable Object not available' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } + + const url = new URL(request.url); + const action = url.searchParams.get('action') || 'increment'; + + const id = env.COUNTER_DO.idFromName('global-counter'); + const stub = env.COUNTER_DO.get(id); + + let doRequest: Request; + switch (action) { + case 'reset': + doRequest = new Request('https://counter.do/reset'); + break; + case 'increment': + default: + doRequest = new Request('https://counter.do/increment'); + break; + } + + const response = await stub.fetch(doRequest); + const data = await response.json(); + + return new Response(JSON.stringify(data), { + headers: { 'Content-Type': 'application/json' } + }); +}; \ No newline at end of file diff --git a/src/worker.ts b/src/worker.ts new file mode 100644 index 0000000..0ad83a6 --- /dev/null +++ b/src/worker.ts @@ -0,0 +1,67 @@ +import type { SSRManifest } from 'astro'; +import { App } from 'astro/app'; +import { handle } from '@astrojs/cloudflare/handler'; +import { DurableObject } from 'cloudflare:workers'; + +interface Env { + COUNTER_DO: DurableObjectNamespace; +} + +class CounterDurableObject extends DurableObject { + constructor(ctx: DurableObjectState, env: Env) { + super(ctx, env); + } + + async fetch(request: Request): Promise { + const url = new URL(request.url); + const pathname = url.pathname; + + if (pathname === '/increment') { + const currentValue = (await this.ctx.storage.get('counter')) || 0; + const newValue = currentValue + 1; + await this.ctx.storage.put('counter', newValue); + + return new Response(JSON.stringify({ + counter: newValue, + timestamp: new Date().toISOString() + }), { + headers: { 'Content-Type': 'application/json' } + }); + } + + if (pathname === '/get') { + const currentValue = (await this.ctx.storage.get('counter')) || 0; + return new Response(JSON.stringify({ + counter: currentValue, + timestamp: new Date().toISOString() + }), { + headers: { 'Content-Type': 'application/json' } + }); + } + + if (pathname === '/reset') { + await this.ctx.storage.put('counter', 0); + return new Response(JSON.stringify({ + counter: 0, + message: 'Counter reset', + timestamp: new Date().toISOString() + }), { + headers: { 'Content-Type': 'application/json' } + }); + } + + return new Response('Not found', { status: 404 }); + } +} + +export function createExports(manifest: SSRManifest) { + const app = new App(manifest); + return { + default: { + async fetch(request, env, ctx) { + return handle(manifest, app, request, env, ctx); + } + } satisfies ExportedHandler, + CounterDurableObject: CounterDurableObject, + }; +} \ No newline at end of file -- cgit v1.3.1