Skip to content

Commit 3df3923

Browse files
committed
add example project
1 parent d85a62a commit 3df3923

File tree

4 files changed

+374
-0
lines changed

4 files changed

+374
-0
lines changed

example/bun.lock

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"lockfileVersion": 1,
3+
"workspaces": {
4+
"": {
5+
"name": "elysia-http-exception-example",
6+
"dependencies": {
7+
"elysia": "^1.3.8",
8+
"elysia-http-exception": "file:..",
9+
},
10+
"devDependencies": {
11+
"@types/bun": "latest",
12+
},
13+
},
14+
},
15+
"packages": {
16+
"@sinclair/typebox": ["@sinclair/[email protected]", "", {}, "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA=="],
17+
18+
"@tokenizer/inflate": ["@tokenizer/[email protected]", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
19+
20+
"@tokenizer/token": ["@tokenizer/[email protected]", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
21+
22+
"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.2.20" } }, "sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA=="],
23+
24+
"@types/node": ["@types/[email protected]", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
25+
26+
"@types/react": ["@types/[email protected]", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],
27+
28+
"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA=="],
29+
30+
"cookie": ["[email protected]", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
31+
32+
"csstype": ["[email protected]", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
33+
34+
"debug": ["[email protected]", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
35+
36+
"elysia": ["[email protected]", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.3", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": "^0.34.33", "openapi-types": "^12.1.3" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-kxYFhegJbUEf5otzmisEvGt3R7d/dPBNVERO2nHo0kFqKBHyj5slArc90mSRKLfi1vamMtPcz67rL6Zeg5F2yg=="],
37+
38+
"elysia-http-exception": ["elysia-http-exception@file:..", { "devDependencies": { "@types/bun": "latest", "elysia": "^1.3.8", "prettier": "^3.6.2" }, "peerDependencies": { "typescript": "^5" } }],
39+
40+
"exact-mirror": ["[email protected]", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-yI62LpSby0ItzPJF05C4DRycVAoknRiCIDOLOCCs9zaEKylOXQtOFM3flX54S44swpRz584vk3P70yWQodsLlg=="],
41+
42+
"fast-decode-uri-component": ["[email protected]", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
43+
44+
"fflate": ["[email protected]", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
45+
46+
"file-type": ["[email protected]", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
47+
48+
"ieee754": ["[email protected]", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
49+
50+
"ms": ["[email protected]", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
51+
52+
"openapi-types": ["[email protected]", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
53+
54+
"prettier": ["[email protected]", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
55+
56+
"strtok3": ["[email protected]", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
57+
58+
"token-types": ["[email protected]", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-MD9MjpVNhVyH4fyd5rKphjvt/1qj+PtQUz65aFqAZA6XniWAuSFRjLk3e2VALEFlh9OwBpXUN7rfeqSnT/Fmkw=="],
59+
60+
"typescript": ["[email protected]", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
61+
62+
"uint8array-extras": ["[email protected]", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
63+
64+
"undici-types": ["[email protected]", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
65+
}
66+
}

example/index.ts

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
import { Elysia } from 'elysia';
2+
import {
3+
httpExceptionPlugin,
4+
// 4xx Client Error Exceptions
5+
BadRequestException,
6+
UnauthorizedException,
7+
PaymentRequiredException,
8+
ForbiddenException,
9+
NotFoundException,
10+
MethodNotAllowedException,
11+
NotAcceptableException,
12+
RequestTimeoutException,
13+
ConflictException,
14+
GoneException,
15+
LengthRequiredException,
16+
PreconditionFailedException,
17+
PayloadTooLargeException,
18+
UriTooLongException,
19+
UnsupportedMediaTypeException,
20+
RangeNotSatisfiableException,
21+
ExpectationFailedException,
22+
ImATeapotException,
23+
MisdirectedRequestException,
24+
UnprocessableEntityException,
25+
LockedException,
26+
FailedDependencyException,
27+
TooEarlyException,
28+
UpgradeRequiredException,
29+
PreconditionRequiredException,
30+
TooManyRequestsException,
31+
RequestHeaderFieldsTooLargeException,
32+
UnavailableForLegalReasonsException,
33+
// 5xx Server Error Exceptions
34+
InternalServerErrorException,
35+
NotImplementedException,
36+
BadGatewayException,
37+
ServiceUnavailableException,
38+
GatewayTimeoutException,
39+
HttpVersionNotSupportedException,
40+
VariantAlsoNegotiatesException,
41+
InsufficientStorageException,
42+
LoopDetectedException,
43+
NotExtendedException,
44+
NetworkAuthenticationRequiredException,
45+
} from 'elysia-http-exception';
46+
47+
const app = new Elysia()
48+
.use(httpExceptionPlugin())
49+
.get('/', () => 'Elysia HTTP Exception Examples - Try different endpoints to see various errors!')
50+
51+
// 4xx Client Errors
52+
.get('/400', () => {
53+
throw new BadRequestException('Invalid request format');
54+
})
55+
.get('/401', () => {
56+
throw new UnauthorizedException('Authentication required');
57+
})
58+
.get('/402', () => {
59+
throw new PaymentRequiredException('Payment is required to access this resource');
60+
})
61+
.get('/403', () => {
62+
throw new ForbiddenException('You do not have permission to access this resource');
63+
})
64+
.get('/404', () => {
65+
throw new NotFoundException('The requested resource was not found');
66+
})
67+
.get('/405', () => {
68+
throw new MethodNotAllowedException('This HTTP method is not allowed for this endpoint');
69+
})
70+
.get('/406', () => {
71+
throw new NotAcceptableException('The requested format is not acceptable');
72+
})
73+
.get('/408', () => {
74+
throw new RequestTimeoutException('Request timeout occurred');
75+
})
76+
.get('/409', () => {
77+
throw new ConflictException('Resource conflict detected');
78+
})
79+
.get('/410', () => {
80+
throw new GoneException('This resource is no longer available');
81+
})
82+
.get('/411', () => {
83+
throw new LengthRequiredException('Content-Length header is required');
84+
})
85+
.get('/412', () => {
86+
throw new PreconditionFailedException('Precondition in request headers failed');
87+
})
88+
.get('/413', () => {
89+
throw new PayloadTooLargeException('Request payload is too large');
90+
})
91+
.get('/414', () => {
92+
throw new UriTooLongException('The URI provided was too long');
93+
})
94+
.get('/415', () => {
95+
throw new UnsupportedMediaTypeException('Unsupported media type');
96+
})
97+
.get('/416', () => {
98+
throw new RangeNotSatisfiableException('Requested range not satisfiable');
99+
})
100+
.get('/417', () => {
101+
throw new ExpectationFailedException('Expectation failed');
102+
})
103+
.get('/418', () => {
104+
throw new ImATeapotException("I'm a teapot - cannot brew coffee!");
105+
})
106+
.get('/421', () => {
107+
throw new MisdirectedRequestException('Request was misdirected');
108+
})
109+
.get('/422', () => {
110+
throw new UnprocessableEntityException('The request was well-formed but contains semantic errors');
111+
})
112+
.get('/423', () => {
113+
throw new LockedException('The resource is locked');
114+
})
115+
.get('/424', () => {
116+
throw new FailedDependencyException('Request failed due to dependency failure');
117+
})
118+
.get('/425', () => {
119+
throw new TooEarlyException('Too early to process this request');
120+
})
121+
.get('/426', () => {
122+
throw new UpgradeRequiredException('Client should upgrade to different protocol');
123+
})
124+
.get('/428', () => {
125+
throw new PreconditionRequiredException('Precondition is required');
126+
})
127+
.get('/429', () => {
128+
throw new TooManyRequestsException('Too many requests - rate limit exceeded');
129+
})
130+
.get('/431', () => {
131+
throw new RequestHeaderFieldsTooLargeException('Request header fields too large');
132+
})
133+
.get('/451', () => {
134+
throw new UnavailableForLegalReasonsException('Unavailable for legal reasons');
135+
})
136+
137+
// 5xx Server Errors
138+
.get('/500', () => {
139+
throw new InternalServerErrorException('An internal server error occurred');
140+
})
141+
.get('/501', () => {
142+
throw new NotImplementedException('This functionality is not implemented');
143+
})
144+
.get('/502', () => {
145+
throw new BadGatewayException('Bad gateway response from upstream server');
146+
})
147+
.get('/503', () => {
148+
throw new ServiceUnavailableException('Service temporarily unavailable');
149+
})
150+
.get('/504', () => {
151+
throw new GatewayTimeoutException('Gateway timeout from upstream server');
152+
})
153+
.get('/505', () => {
154+
throw new HttpVersionNotSupportedException('HTTP version not supported');
155+
})
156+
.get('/506', () => {
157+
throw new VariantAlsoNegotiatesException('Variant also negotiates');
158+
})
159+
.get('/507', () => {
160+
throw new InsufficientStorageException('Insufficient storage space');
161+
})
162+
.get('/508', () => {
163+
throw new LoopDetectedException('Infinite loop detected');
164+
})
165+
.get('/510', () => {
166+
throw new NotExtendedException('Further extensions are required');
167+
})
168+
.get('/511', () => {
169+
throw new NetworkAuthenticationRequiredException('Network authentication required');
170+
})
171+
172+
// Examples with custom data/objects
173+
.get('/custom-error', () => {
174+
throw new BadRequestException({
175+
error: 'VALIDATION_FAILED',
176+
details: {
177+
field: 'email',
178+
message: 'Invalid email format'
179+
},
180+
timestamp: new Date().toISOString()
181+
});
182+
})
183+
184+
.get('/custom-string', () => {
185+
throw new NotFoundException('User with ID "12345" not found in the system');
186+
})
187+
188+
.get('/custom-error-object', () => {
189+
const validationError = new Error('Validation failed for input data');
190+
throw new UnprocessableEntityException(validationError);
191+
})
192+
193+
// Practical example - User management
194+
.get('/users/:id', ({ params }) => {
195+
const userId = parseInt(params.id);
196+
197+
if (isNaN(userId)) {
198+
throw new BadRequestException('User ID must be a valid number');
199+
}
200+
201+
if (userId < 1) {
202+
throw new BadRequestException('User ID must be positive');
203+
}
204+
205+
if (userId === 404) {
206+
throw new NotFoundException(`User with ID ${userId} not found`);
207+
}
208+
209+
if (userId === 403) {
210+
throw new ForbiddenException('You do not have permission to view this user');
211+
}
212+
213+
return { id: userId, name: `User ${userId}`, email: `user${userId}@example.com` };
214+
})
215+
216+
// API rate limiting example
217+
.get('/api/data', ({ request }) => {
218+
const rateLimitExceeded = Math.random() > 0.7; // Simulate rate limiting
219+
220+
if (rateLimitExceeded) {
221+
throw new TooManyRequestsException({
222+
message: 'Rate limit exceeded',
223+
retryAfter: 60,
224+
limit: 100,
225+
remaining: 0
226+
});
227+
}
228+
229+
return { data: 'Some API data', timestamp: Date.now() };
230+
})
231+
232+
// Database connection example
233+
.get('/database/status', () => {
234+
const dbConnected = Math.random() > 0.3; // Simulate database connection
235+
236+
if (!dbConnected) {
237+
throw new ServiceUnavailableException('Database connection failed - please try again later');
238+
}
239+
240+
return { status: 'Database is healthy', connections: 25 };
241+
})
242+
243+
.listen(3000);
244+
245+
console.log(`🚀 Server is running at http://localhost:3000`);
246+
247+
console.log('\n📚 Available endpoints:');
248+
console.log('GET / - Welcome message');
249+
console.log('\n🔴 4xx Client Errors:');
250+
console.log('GET /400, /401, /402, /403, /404, /405, /406, /408, /409, /410');
251+
console.log('GET /411, /412, /413, /414, /415, /416, /417, /418, /421, /422');
252+
console.log('GET /423, /424, /425, /426, /428, /429, /431, /451');
253+
console.log('\n🔥 5xx Server Errors:');
254+
console.log('GET /500, /501, /502, /503, /504, /505, /506, /507, /508, /510, /511');
255+
console.log('\n🎯 Custom Examples:');
256+
console.log('GET /custom-error - Custom error with object data');
257+
console.log('GET /custom-string - Custom error with string message');
258+
console.log('GET /custom-error-object - Custom error with Error object');
259+
console.log('\n💡 Practical Examples:');
260+
console.log('GET /users/:id - User management with validation');
261+
console.log('GET /api/data - API rate limiting example');
262+
console.log('GET /database/status - Database connection example');

example/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "elysia-http-exception-example",
3+
"version": "1.0.0",
4+
"description": "Example project demonstrating all HTTP exception classes",
5+
"type": "module",
6+
"main": "index.ts",
7+
"scripts": {
8+
"dev": "bun run index.ts",
9+
"start": "bun run index.ts"
10+
},
11+
"dependencies": {
12+
"elysia": "^1.3.8",
13+
"elysia-http-exception": "file:.."
14+
},
15+
"devDependencies": {
16+
"@types/bun": "latest"
17+
}
18+
}

example/tsconfig.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["ESNext"],
4+
"target": "ESNext",
5+
"module": "esnext",
6+
"moduleDetection": "force",
7+
"jsx": "preserve",
8+
"moduleResolution": "bundler",
9+
"allowImportingTsExtensions": true,
10+
"verbatimModuleSyntax": true,
11+
"noEmit": true,
12+
"strict": true,
13+
"skipLibCheck": true,
14+
"noFallthroughCasesInSwitch": true,
15+
"noUncheckedIndexedAccess": true,
16+
"noImplicitOverride": true,
17+
"allowSyntheticDefaultImports": true,
18+
"forceConsistentCasingInFileNames": true,
19+
"noUnusedLocals": false,
20+
"noUnusedParameters": false,
21+
"noPropertyAccessFromIndexSignature": false,
22+
"allowJs": true,
23+
"declaration": true,
24+
"emitDeclarationOnly": true,
25+
"outDir": "dist",
26+
"types": ["bun-types"]
27+
}
28+
}

0 commit comments

Comments
 (0)