summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2025-07-10 13:55:01 +0200
committerYuval Adam <_@yuv.al>2025-07-10 13:55:23 +0200
commit3f0837d920ba67496c5fc7f50485aed84b37d05e (patch)
tree45548ab3defff3abfb34245e41db606caedf7e0b /src
parentc4284d7c2ab7b73af8424fcf379f44dee1682a1a (diff)
Simplify code'
Diffstat (limited to 'src')
-rw-r--r--src/pages/api/counter.ts52
-rw-r--r--src/pages/api/hello.ts54
-rw-r--r--src/pages/index.astro277
-rw-r--r--src/worker.ts43
4 files changed, 57 insertions, 369 deletions
diff --git a/src/pages/api/counter.ts b/src/pages/api/counter.ts
index 1d3d0b7..4f42236 100644
--- a/src/pages/api/counter.ts
+++ b/src/pages/api/counter.ts
@@ -6,54 +6,16 @@ interface Env {
export const GET: APIRoute = async ({ locals }) => {
const env = locals.runtime.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 id = env.COUNTER_DO.idFromName('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' }
- });
+ const response = await stub.fetch('https://counter.do/get');
+ return response;
};
-export const POST: APIRoute = async ({ request, locals }) => {
+export const POST: APIRoute = async ({ locals }) => {
const env = locals.runtime.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 id = env.COUNTER_DO.idFromName('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' }
- });
+ const response = await stub.fetch('https://counter.do/increment');
+ return response;
}; \ No newline at end of file
diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts
deleted file mode 100644
index eba198d..0000000
--- a/src/pages/api/hello.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import type { APIRoute } from 'astro';
-
-export const GET: APIRoute = async ({ request }) => {
- const url = new URL(request.url);
- const name = url.searchParams.get('name') || 'World';
-
- return new Response(
- JSON.stringify({
- message: `Hello, ${name}!`,
- timestamp: new Date().toISOString(),
- method: 'GET'
- }),
- {
- status: 200,
- headers: {
- 'Content-Type': 'application/json',
- },
- }
- );
-};
-
-export const POST: APIRoute = async ({ request }) => {
- try {
- const body = await request.json();
-
- return new Response(
- JSON.stringify({
- message: 'Data received successfully',
- received: body,
- timestamp: new Date().toISOString(),
- method: 'POST'
- }),
- {
- status: 200,
- headers: {
- 'Content-Type': 'application/json',
- },
- }
- );
- } catch (error) {
- return new Response(
- JSON.stringify({
- error: 'Invalid JSON',
- timestamp: new Date().toISOString()
- }),
- {
- status: 400,
- headers: {
- 'Content-Type': 'application/json',
- },
- }
- );
- }
-}; \ No newline at end of file
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 363e843..ae53624 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -7,267 +7,74 @@
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
- <meta name="generator" content={Astro.generator} />
- <title>Astro + Cloudflare Durable Objects Demo</title>
+ <title>Astro + Cloudflare Durable Objects</title>
<style>
body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
- max-width: 800px;
- margin: 0 auto;
- padding: 2rem;
- line-height: 1.6;
- background: #f8fafc;
- color: #334155;
- }
-
- .container {
- background: white;
- padding: 2rem;
- border-radius: 12px;
- box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
- }
-
- h1 {
- color: #1e293b;
- margin-bottom: 1rem;
- font-size: 2.5rem;
- }
-
- .subtitle {
- color: #64748b;
- margin-bottom: 2rem;
- font-size: 1.1rem;
+ font-family: system-ui, sans-serif;
+ max-width: 600px;
+ margin: 2rem auto;
+ padding: 1rem;
+ line-height: 1.5;
}
- .counter-section {
- background: #f1f5f9;
+ .counter {
+ text-align: center;
+ margin: 2rem 0;
padding: 2rem;
+ background: #f5f5f5;
border-radius: 8px;
- margin: 2rem 0;
- text-align: center;
}
- .counter-display {
+ .count {
font-size: 3rem;
font-weight: bold;
- color: #3b82f6;
- margin: 1rem 0;
- }
-
- .button-group {
- display: flex;
- gap: 1rem;
- justify-content: center;
- flex-wrap: wrap;
+ color: #0066cc;
}
button {
- background: #3b82f6;
+ background: #0066cc;
color: white;
border: none;
- padding: 0.75rem 1.5rem;
- border-radius: 6px;
- font-size: 1rem;
+ padding: 0.5rem 1rem;
+ margin: 0.5rem;
+ border-radius: 4px;
cursor: pointer;
- transition: background-color 0.2s;
}
button:hover {
- background: #2563eb;
- }
-
- button:disabled {
- background: #94a3b8;
- cursor: not-allowed;
- }
-
- .reset-btn {
- background: #ef4444;
- }
-
- .reset-btn:hover {
- background: #dc2626;
- }
-
- .status {
- margin-top: 1rem;
- padding: 0.75rem;
- border-radius: 6px;
- font-size: 0.9rem;
- }
-
- .status.loading {
- background: #fef3c7;
- color: #92400e;
- }
-
- .status.error {
- background: #fee2e2;
- color: #b91c1c;
- }
-
- .status.success {
- background: #dcfce7;
- color: #166534;
- }
-
- .explanation {
- background: #f8fafc;
- padding: 1.5rem;
- border-left: 4px solid #3b82f6;
- margin: 2rem 0;
- }
-
- .explanation h3 {
- margin-top: 0;
- color: #1e293b;
- }
-
- code {
- background: #e2e8f0;
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-family: 'Monaco', 'Consolas', monospace;
- font-size: 0.9rem;
+ background: #0052a3;
}
</style>
</head>
<body>
- <div class="container">
- <h1>Astro + Cloudflare Durable Objects</h1>
- <p class="subtitle">A persistent counter demonstrating Durable Objects with Astro and Cloudflare Workers</p>
-
- <div class="counter-section">
- <h2>Global Counter</h2>
- <div class="counter-display" id="counterValue">-</div>
- <div class="button-group">
- <button id="getBtn">Get Counter</button>
- <button id="incrementBtn">Increment</button>
- <button id="resetBtn" class="reset-btn">Reset</button>
- </div>
- <div id="status" class="status" style="display: none;"></div>
- </div>
-
- <div class="explanation">
- <h3>How it works</h3>
- <p>This demo showcases a <strong>Cloudflare Durable Object</strong> that maintains a persistent counter. The counter state survives across requests, deployments, and server restarts.</p>
-
- <h4>API Endpoints:</h4>
- <ul>
- <li><code>GET /api/counter</code> - Retrieve the current counter value</li>
- <li><code>POST /api/counter</code> - Increment the counter by 1</li>
- <li><code>POST /api/counter?action=reset</code> - Reset the counter to 0</li>
- </ul>
-
- <h4>Key Features:</h4>
- <ul>
- <li><strong>Persistent Storage:</strong> Counter value persists across deployments</li>
- <li><strong>Global State:</strong> Single counter instance shared across all requests</li>
- <li><strong>Edge Computing:</strong> Runs at Cloudflare's edge locations</li>
- <li><strong>Real-time Updates:</strong> Immediate consistency for all operations</li>
- </ul>
- </div>
+ <h1>Astro + Cloudflare Durable Objects</h1>
+ <p>A simple persistent counter using Durable Objects.</p>
+
+ <div class="counter">
+ <div class="count" id="count">-</div>
+ <button id="getBtn">Get Count</button>
+ <button id="incBtn">Increment</button>
</div>
-
+
+ <p><strong>How it works:</strong> The counter value is stored in a Durable Object and persists across deployments.</p>
+
<script>
- const counterValue = document.getElementById('counterValue');
- const getBtn = document.getElementById('getBtn');
- const incrementBtn = document.getElementById('incrementBtn');
- const resetBtn = document.getElementById('resetBtn');
- const status = document.getElementById('status');
-
- function showStatus(message, type = 'loading') {
- status.textContent = message;
- status.className = `status ${type}`;
- status.style.display = 'block';
-
- if (type !== 'loading') {
- setTimeout(() => {
- status.style.display = 'none';
- }, 3000);
- }
- }
-
- function setButtonsDisabled(disabled) {
- getBtn.disabled = disabled;
- incrementBtn.disabled = disabled;
- resetBtn.disabled = disabled;
- }
-
- async function getCounter() {
- try {
- setButtonsDisabled(true);
- showStatus('Getting counter value...', 'loading');
-
- const response = await fetch('/api/counter');
- const data = await response.json();
-
- if (response.ok) {
- counterValue.textContent = data.counter;
- showStatus(`Counter retrieved: ${data.counter}`, 'success');
- } else {
- throw new Error(data.error || 'Failed to get counter');
- }
- } catch (error) {
- showStatus(`Error: ${error.message}`, 'error');
- counterValue.textContent = 'Error';
- } finally {
- setButtonsDisabled(false);
- }
- }
-
- async function incrementCounter() {
- try {
- setButtonsDisabled(true);
- showStatus('Incrementing counter...', 'loading');
-
- const response = await fetch('/api/counter', {
- method: 'POST'
- });
- const data = await response.json();
-
- if (response.ok) {
- counterValue.textContent = data.counter;
- showStatus(`Counter incremented to: ${data.counter}`, 'success');
- } else {
- throw new Error(data.error || 'Failed to increment counter');
- }
- } catch (error) {
- showStatus(`Error: ${error.message}`, 'error');
- } finally {
- setButtonsDisabled(false);
- }
+ async function getCount() {
+ const response = await fetch('/api/counter');
+ const count = await response.text();
+ document.getElementById('count').textContent = count;
}
-
- async function resetCounter() {
- try {
- setButtonsDisabled(true);
- showStatus('Resetting counter...', 'loading');
-
- const response = await fetch('/api/counter?action=reset', {
- method: 'POST'
- });
- const data = await response.json();
-
- if (response.ok) {
- counterValue.textContent = data.counter;
- showStatus('Counter reset to 0', 'success');
- } else {
- throw new Error(data.error || 'Failed to reset counter');
- }
- } catch (error) {
- showStatus(`Error: ${error.message}`, 'error');
- } finally {
- setButtonsDisabled(false);
- }
+
+ async function increment() {
+ const response = await fetch('/api/counter', { method: 'POST' });
+ const count = await response.text();
+ document.getElementById('count').textContent = count;
}
-
- getBtn.addEventListener('click', getCounter);
- incrementBtn.addEventListener('click', incrementCounter);
- resetBtn.addEventListener('click', resetCounter);
-
- // Load initial counter value
- getCounter();
+
+ document.getElementById('getBtn').onclick = getCount;
+ document.getElementById('incBtn').onclick = increment;
+
+ getCount();
</script>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/src/worker.ts b/src/worker.ts
index 5eb9d5d..52e9f5e 100644
--- a/src/worker.ts
+++ b/src/worker.ts
@@ -8,46 +8,19 @@ interface Env {
}
class CounterDurableObject extends DurableObject<Env> {
- constructor(ctx: DurableObjectState, env: Env) {
- super(ctx, env);
- }
-
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
- const pathname = url.pathname;
-
- if (pathname === '/increment') {
- const currentValue = (await this.ctx.storage.get<number>('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<number>('counter')) || 0;
- return new Response(JSON.stringify({
- counter: currentValue,
- timestamp: new Date().toISOString()
- }), {
- headers: { 'Content-Type': 'application/json' }
- });
+ if (url.pathname === '/get') {
+ const count = (await this.ctx.storage.get<number>('count')) || 0;
+ return new Response(count.toString());
}
- 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' }
- });
+ if (url.pathname === '/increment') {
+ const count = (await this.ctx.storage.get<number>('count')) || 0;
+ const newCount = count + 1;
+ await this.ctx.storage.put('count', newCount);
+ return new Response(newCount.toString());
}
return new Response('Not found', { status: 404 });