Skip to content

Commit 3efc16b

Browse files
authored
Merge pull request #17 from cloudflare/workers/express-example
Adds missing endpoint to the express app
2 parents 4aa8ec6 + 1b8664f commit 3efc16b

File tree

1 file changed

+164
-86
lines changed

1 file changed

+164
-86
lines changed

workers/express-on-workers/src/index.ts

Lines changed: 164 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,187 @@
1-
import { env } from 'cloudflare:workers';
2-
import { httpServerHandler } from 'cloudflare:node';
3-
import express from 'express';
1+
import { env } from "cloudflare:workers";
2+
import { httpServerHandler } from "cloudflare:node";
3+
import express from "express";
44

55
const app = express();
66

77
// Middleware to parse JSON bodies
88
app.use(express.json());
99

1010
// Health check endpoint
11-
app.get('/', (req, res) => {
12-
res.json({ message: 'Express.js running on Cloudflare Workers!' });
11+
app.get("/", (req, res) => {
12+
res.json({ message: "Express.js running on Cloudflare Workers!" });
1313
});
1414

1515
// GET all members
16-
app.get('/api/members', async (req, res) => {
17-
try {
18-
const { results } = await env.DB.prepare('SELECT * FROM members ORDER BY joined_date DESC').all();
19-
20-
res.json({ success: true, members: results });
21-
} catch (error) {
22-
res.status(500).json({ success: false, error: 'Failed to fetch members' });
23-
}
16+
app.get("/api/members", async (req, res) => {
17+
try {
18+
const { results } = await env.DB.prepare(
19+
"SELECT * FROM members ORDER BY joined_date DESC"
20+
).all();
21+
22+
res.json({ success: true, members: results });
23+
} catch (error) {
24+
res.status(500).json({ success: false, error: "Failed to fetch members" });
25+
}
2426
});
2527

2628
// GET a single member by ID
27-
app.get('/api/members/:id', async (req, res) => {
28-
try {
29-
const { id } = req.params;
30-
31-
const { results } = await env.DB.prepare('SELECT * FROM members WHERE id = ?').bind(id).all();
32-
33-
if (results.length === 0) {
34-
return res.status(404).json({ success: false, error: 'Member not found' });
35-
}
29+
app.get("/api/members/:id", async (req, res) => {
30+
try {
31+
const { id } = req.params;
32+
33+
const { results } = await env.DB.prepare(
34+
"SELECT * FROM members WHERE id = ?"
35+
)
36+
.bind(id)
37+
.all();
38+
39+
if (results.length === 0) {
40+
return res
41+
.status(404)
42+
.json({ success: false, error: "Member not found" });
43+
}
44+
45+
res.json({ success: true, member: results[0] });
46+
} catch (error) {
47+
res.status(500).json({ success: false, error: "Failed to fetch member" });
48+
}
49+
});
3650

37-
res.json({ success: true, member: results[0] });
38-
} catch (error) {
39-
res.status(500).json({ success: false, error: 'Failed to fetch member' });
40-
}
51+
// PUT - Update a member
52+
app.put("/api/members/:id", async (req, res) => {
53+
try {
54+
const { id } = req.params;
55+
const { name, email } = req.body;
56+
57+
// Validate input
58+
if (!name && !email) {
59+
return res.status(400).json({
60+
success: false,
61+
error: "At least one field (name or email) is required",
62+
});
63+
}
64+
65+
// Basic email validation if provided (simplified for tutorial purposes)
66+
// For production, consider using a validation library or more comprehensive checks
67+
if (email && (!email.includes("@") || !email.includes("."))) {
68+
return res.status(400).json({
69+
success: false,
70+
error: "Invalid email format",
71+
});
72+
}
73+
74+
// Build dynamic update query
75+
const updates: string[] = [];
76+
const values: any[] = [];
77+
78+
if (name) {
79+
updates.push("name = ?");
80+
values.push(name);
81+
}
82+
if (email) {
83+
updates.push("email = ?");
84+
values.push(email);
85+
}
86+
87+
values.push(id);
88+
89+
const result = await env.DB.prepare(
90+
`UPDATE members SET ${updates.join(", ")} WHERE id = ?`
91+
)
92+
.bind(...values)
93+
.run();
94+
95+
if (result.meta.changes === 0) {
96+
return res
97+
.status(404)
98+
.json({ success: false, error: "Member not found" });
99+
}
100+
101+
res.json({ success: true, message: "Member updated successfully" });
102+
} catch (error: any) {
103+
if (error.message?.includes("UNIQUE constraint failed")) {
104+
return res.status(409).json({
105+
success: false,
106+
error: "Email already exists",
107+
});
108+
}
109+
res.status(500).json({ success: false, error: "Failed to update member" });
110+
}
41111
});
42112

43113
// POST - Create a new member
44-
app.post('/api/members', async (req, res) => {
45-
try {
46-
const { name, email } = req.body;
47-
48-
// Validate input
49-
if (!name || !email) {
50-
return res.status(400).json({
51-
success: false,
52-
error: 'Name and email are required',
53-
});
54-
}
55-
56-
// Basic email validation (simplified for tutorial purposes)
57-
// For production, consider using a validation library or more comprehensive checks
58-
if (!email.includes('@') || !email.includes('.')) {
59-
return res.status(400).json({
60-
success: false,
61-
error: 'Invalid email format',
62-
});
63-
}
64-
65-
const joined_date = new Date().toISOString().split('T')[0];
66-
67-
const result = await env.DB.prepare('INSERT INTO members (name, email, joined_date) VALUES (?, ?, ?)')
68-
.bind(name, email, joined_date)
69-
.run();
70-
71-
if (result.success) {
72-
res.status(201).json({
73-
success: true,
74-
message: 'Member created successfully',
75-
id: result.meta.last_row_id,
76-
});
77-
} else {
78-
res.status(500).json({ success: false, error: 'Failed to create member' });
79-
}
80-
} catch (error: any) {
81-
// Handle unique constraint violation
82-
if (error.message?.includes('UNIQUE constraint failed')) {
83-
return res.status(409).json({
84-
success: false,
85-
error: 'Email already exists',
86-
});
87-
}
88-
res.status(500).json({ success: false, error: 'Failed to create member' });
89-
}
114+
app.post("/api/members", async (req, res) => {
115+
try {
116+
const { name, email } = req.body;
117+
118+
// Validate input
119+
if (!name || !email) {
120+
return res.status(400).json({
121+
success: false,
122+
error: "Name and email are required",
123+
});
124+
}
125+
126+
// Basic email validation (simplified for tutorial purposes)
127+
// For production, consider using a validation library or more comprehensive checks
128+
if (!email.includes("@") || !email.includes(".")) {
129+
return res.status(400).json({
130+
success: false,
131+
error: "Invalid email format",
132+
});
133+
}
134+
135+
const joined_date = new Date().toISOString().split("T")[0];
136+
137+
const result = await env.DB.prepare(
138+
"INSERT INTO members (name, email, joined_date) VALUES (?, ?, ?)"
139+
)
140+
.bind(name, email, joined_date)
141+
.run();
142+
143+
if (result.success) {
144+
res.status(201).json({
145+
success: true,
146+
message: "Member created successfully",
147+
id: result.meta.last_row_id,
148+
});
149+
} else {
150+
res
151+
.status(500)
152+
.json({ success: false, error: "Failed to create member" });
153+
}
154+
} catch (error: any) {
155+
// Handle unique constraint violation
156+
if (error.message?.includes("UNIQUE constraint failed")) {
157+
return res.status(409).json({
158+
success: false,
159+
error: "Email already exists",
160+
});
161+
}
162+
res.status(500).json({ success: false, error: "Failed to create member" });
163+
}
90164
});
91165

92166
// DELETE - Delete a member
93-
app.delete('/api/members/:id', async (req, res) => {
94-
try {
95-
const { id } = req.params;
96-
97-
const result = await env.DB.prepare('DELETE FROM members WHERE id = ?').bind(id).run();
98-
99-
if (result.meta.changes === 0) {
100-
return res.status(404).json({ success: false, error: 'Member not found' });
101-
}
102-
103-
res.json({ success: true, message: 'Member deleted successfully' });
104-
} catch (error) {
105-
res.status(500).json({ success: false, error: 'Failed to delete member' });
106-
}
167+
app.delete("/api/members/:id", async (req, res) => {
168+
try {
169+
const { id } = req.params;
170+
171+
const result = await env.DB.prepare("DELETE FROM members WHERE id = ?")
172+
.bind(id)
173+
.run();
174+
175+
if (result.meta.changes === 0) {
176+
return res
177+
.status(404)
178+
.json({ success: false, error: "Member not found" });
179+
}
180+
181+
res.json({ success: true, message: "Member deleted successfully" });
182+
} catch (error) {
183+
res.status(500).json({ success: false, error: "Failed to delete member" });
184+
}
107185
});
108186

109187
app.listen(3000);

0 commit comments

Comments
 (0)