create-acrylblends 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +61 -2
  2. package/bin/create-acrylblends.js +4 -0
  3. package/dist/index.d.ts +56 -0
  4. package/dist/index.js +274 -0
  5. package/dist/index.js.map +1 -0
  6. package/docs/framework/LICENSE +23 -0
  7. package/docs/framework/README.md +63 -0
  8. package/docs/framework/UPSTREAM.md +3 -0
  9. package/docs/framework/agents/index.md +24 -0
  10. package/docs/framework/api/acryl.md +259 -0
  11. package/docs/framework/api/context.md +527 -0
  12. package/docs/framework/api/exception.md +80 -0
  13. package/docs/framework/api/index.md +12 -0
  14. package/docs/framework/api/presets.md +65 -0
  15. package/docs/framework/api/request.md +396 -0
  16. package/docs/framework/api/routing.md +303 -0
  17. package/docs/framework/api/summary.md +140 -0
  18. package/docs/framework/concepts/benchmarks.md +26 -0
  19. package/docs/framework/concepts/developer-experience.md +5 -0
  20. package/docs/framework/concepts/middleware.md +21 -0
  21. package/docs/framework/concepts/motivation.md +14 -0
  22. package/docs/framework/concepts/routers.md +63 -0
  23. package/docs/framework/concepts/stacks.md +235 -0
  24. package/docs/framework/concepts/web-standard.md +37 -0
  25. package/docs/framework/cordis/acryl-in-a-cordis-app.md +146 -0
  26. package/docs/framework/cordis/concepts.md +105 -0
  27. package/docs/framework/cordis/middleware.md +8 -0
  28. package/docs/framework/cordis/migration-from-0-3.md +111 -0
  29. package/docs/framework/cordis/migration-from-0-4.md +14 -0
  30. package/docs/framework/cordis/migration-from-dsh-webserver.md +109 -0
  31. package/docs/framework/cordis/mounting.md +85 -0
  32. package/docs/framework/cordis/node-server.md +75 -0
  33. package/docs/framework/cordis/plugin-lifecycle.md +111 -0
  34. package/docs/framework/cordis/surfaces.md +71 -0
  35. package/docs/framework/cordis/transport-and-cancellation.md +57 -0
  36. package/docs/framework/cordis/validation.md +135 -0
  37. package/docs/framework/getting-started/basic.md +196 -0
  38. package/docs/framework/getting-started/bun.md +221 -0
  39. package/docs/framework/getting-started/nodejs.md +344 -0
  40. package/docs/framework/getting-started/other-runtimes.md +23 -0
  41. package/docs/framework/guides/best-practices.md +231 -0
  42. package/docs/framework/guides/create-acrylblends.md +79 -0
  43. package/docs/framework/guides/examples.md +3 -0
  44. package/docs/framework/guides/faq.md +19 -0
  45. package/docs/framework/guides/helpers.md +33 -0
  46. package/docs/framework/guides/jsx-dom.md +299 -0
  47. package/docs/framework/guides/jsx.md +440 -0
  48. package/docs/framework/guides/middleware.md +253 -0
  49. package/docs/framework/guides/rpc.md +886 -0
  50. package/docs/framework/guides/testing.md +133 -0
  51. package/docs/framework/guides/validation.md +383 -0
  52. package/docs/framework/helpers/accepts.md +60 -0
  53. package/docs/framework/helpers/adapter.md +87 -0
  54. package/docs/framework/helpers/conninfo.md +112 -0
  55. package/docs/framework/helpers/cookie.md +232 -0
  56. package/docs/framework/helpers/css.md +285 -0
  57. package/docs/framework/helpers/dev.md +67 -0
  58. package/docs/framework/helpers/factory.md +180 -0
  59. package/docs/framework/helpers/html.md +123 -0
  60. package/docs/framework/helpers/jwt.md +184 -0
  61. package/docs/framework/helpers/proxy.md +118 -0
  62. package/docs/framework/helpers/route.md +143 -0
  63. package/docs/framework/helpers/ssg.md +393 -0
  64. package/docs/framework/helpers/streaming.md +119 -0
  65. package/docs/framework/helpers/testing.md +101 -0
  66. package/docs/framework/helpers/websocket.md +215 -0
  67. package/docs/framework/middleware/builtin/basic-auth.md +165 -0
  68. package/docs/framework/middleware/builtin/bearer-auth.md +138 -0
  69. package/docs/framework/middleware/builtin/body-limit.md +71 -0
  70. package/docs/framework/middleware/builtin/cache.md +122 -0
  71. package/docs/framework/middleware/builtin/combine.md +94 -0
  72. package/docs/framework/middleware/builtin/compress.md +59 -0
  73. package/docs/framework/middleware/builtin/context-storage.md +78 -0
  74. package/docs/framework/middleware/builtin/cors.md +135 -0
  75. package/docs/framework/middleware/builtin/csrf.md +105 -0
  76. package/docs/framework/middleware/builtin/etag.md +54 -0
  77. package/docs/framework/middleware/builtin/ip-restriction.md +69 -0
  78. package/docs/framework/middleware/builtin/jsx-renderer.md +286 -0
  79. package/docs/framework/middleware/builtin/jwk.md +192 -0
  80. package/docs/framework/middleware/builtin/jwt.md +145 -0
  81. package/docs/framework/middleware/builtin/language.md +232 -0
  82. package/docs/framework/middleware/builtin/logger.md +74 -0
  83. package/docs/framework/middleware/builtin/loopback-only.md +31 -0
  84. package/docs/framework/middleware/builtin/method-not-allowed.md +48 -0
  85. package/docs/framework/middleware/builtin/method-override.md +80 -0
  86. package/docs/framework/middleware/builtin/mount.md +106 -0
  87. package/docs/framework/middleware/builtin/pretty-json.md +53 -0
  88. package/docs/framework/middleware/builtin/request-id.md +94 -0
  89. package/docs/framework/middleware/builtin/secure-headers.md +247 -0
  90. package/docs/framework/middleware/builtin/timeout.md +98 -0
  91. package/docs/framework/middleware/builtin/timing.md +101 -0
  92. package/docs/framework/middleware/builtin/trailing-slash.md +74 -0
  93. package/docs/framework/middleware/third-party.md +4 -0
  94. package/docs/framework/upstream.json +9 -0
  95. package/package.json +47 -3
  96. package/templates/bun/gitignore +1 -0
  97. package/templates/bun/package.json +19 -0
  98. package/templates/bun/src/index.ts +7 -0
  99. package/templates/bun/test/app.test.ts +8 -0
  100. package/templates/bun/tsconfig.json +15 -0
  101. package/templates/nodejs/gitignore +1 -0
  102. package/templates/nodejs/package.json +22 -0
  103. package/templates/nodejs/src/app.ts +7 -0
  104. package/templates/nodejs/src/index.ts +9 -0
  105. package/templates/nodejs/test/app.test.ts +9 -0
  106. package/templates/nodejs/tsconfig.json +16 -0
@@ -0,0 +1,527 @@
1
+ # Context
2
+
3
+ The `Context` object is instantiated for each request and kept until the response is returned. You can put values in it, set headers and a status code you want to return, and access AcrylRequest and Response objects.
4
+
5
+ ## req
6
+
7
+ `req` is an instance of AcrylRequest. For more details, see [AcrylRequest](request.md).
8
+
9
+ ```ts twoslash
10
+ import { Acryl } from 'acrylblends'
11
+ const app = new Acryl()
12
+ // ---cut---
13
+ app.get('/hello', (c) => {
14
+ const userAgent = c.req.header('User-Agent')
15
+ // ...
16
+ // ---cut-start---
17
+ return c.text(`Hello, ${userAgent}`)
18
+ // ---cut-end---
19
+ })
20
+ ```
21
+
22
+ ## status()
23
+
24
+ You can set an HTTP status code with `c.status()`. The default is `200`. You don't have to use `c.status()` if the code is `200`.
25
+
26
+ ```ts twoslash
27
+ import { Acryl } from 'acrylblends'
28
+ const app = new Acryl()
29
+ // ---cut---
30
+ app.post('/posts', (c) => {
31
+ // Set HTTP status code
32
+ c.status(201)
33
+ return c.text('Your post is created!')
34
+ })
35
+ ```
36
+
37
+ ## header()
38
+
39
+ You can set HTTP Headers for the response.
40
+
41
+ ```ts twoslash
42
+ import { Acryl } from 'acrylblends'
43
+ const app = new Acryl()
44
+ // ---cut---
45
+ app.get('/', (c) => {
46
+ // Set headers
47
+ c.header('X-Message', 'My custom message')
48
+ return c.text('Hello!')
49
+ })
50
+ ```
51
+
52
+ ## body()
53
+
54
+ Return an HTTP response.
55
+
56
+ > **Note.** When returning text or HTML, it is recommended to use `c.text()` or `c.html()`.
57
+
58
+ ```ts twoslash
59
+ import { Acryl } from 'acrylblends'
60
+ const app = new Acryl()
61
+ // ---cut---
62
+ app.get('/welcome', (c) => {
63
+ c.header('Content-Type', 'text/plain')
64
+ // Return the response body
65
+ return c.body('Thank you for coming')
66
+ })
67
+ ```
68
+
69
+ You can also write the following.
70
+
71
+ ```ts twoslash
72
+ import { Acryl } from 'acrylblends'
73
+ const app = new Acryl()
74
+ // ---cut---
75
+ app.get('/welcome', (c) => {
76
+ return c.body('Thank you for coming', 201, {
77
+ 'X-Message': 'Hello!',
78
+ 'Content-Type': 'text/plain',
79
+ })
80
+ })
81
+ ```
82
+
83
+ The response is the same `Response` object as below.
84
+
85
+ ```ts twoslash
86
+ new Response('Thank you for coming', {
87
+ status: 201,
88
+ headers: {
89
+ 'X-Message': 'Hello!',
90
+ 'Content-Type': 'text/plain',
91
+ },
92
+ })
93
+ ```
94
+
95
+ ## text()
96
+
97
+ Render text as `Content-Type: text/plain`.
98
+
99
+ ```ts twoslash
100
+ import { Acryl } from 'acrylblends'
101
+ const app = new Acryl()
102
+ // ---cut---
103
+ app.get('/say', (c) => {
104
+ return c.text('Hello!')
105
+ })
106
+ ```
107
+
108
+ ## json()
109
+
110
+ Render JSON as `Content-Type: application/json`.
111
+
112
+ ```ts twoslash
113
+ import { Acryl } from 'acrylblends'
114
+ const app = new Acryl()
115
+ // ---cut---
116
+ app.get('/api', (c) => {
117
+ return c.json({ message: 'Hello!' })
118
+ })
119
+ ```
120
+
121
+ ## html()
122
+
123
+ Render HTML as `Content-Type: text/html`.
124
+
125
+ ```ts twoslash
126
+ import { Acryl } from 'acrylblends'
127
+ const app = new Acryl()
128
+ // ---cut---
129
+ app.get('/', (c) => {
130
+ return c.html('<h1>Hello! Acryl!</h1>')
131
+ })
132
+ ```
133
+
134
+ ## notFound()
135
+
136
+ Return a `Not Found` Response. You can customize it with [`app.notFound()`](acryl.md#not-found).
137
+
138
+ ```ts twoslash
139
+ import { Acryl } from 'acrylblends'
140
+ const app = new Acryl()
141
+ // ---cut---
142
+ app.get('/notfound', (c) => {
143
+ return c.notFound()
144
+ })
145
+ ```
146
+
147
+ ## redirect()
148
+
149
+ Redirect, default status code is `302`.
150
+
151
+ ```ts twoslash
152
+ import { Acryl } from 'acrylblends'
153
+ const app = new Acryl()
154
+ // ---cut---
155
+ app.get('/redirect', (c) => {
156
+ return c.redirect('/')
157
+ })
158
+ app.get('/redirect-permanently', (c) => {
159
+ return c.redirect('/', 301)
160
+ })
161
+ ```
162
+
163
+ ## res
164
+
165
+ You can access the [Response] object that will be returned.
166
+
167
+ ```ts twoslash
168
+ import { Acryl } from 'acrylblends'
169
+ const app = new Acryl()
170
+ // ---cut---
171
+ // Response object
172
+ app.use('/', async (c, next) => {
173
+ await next()
174
+ c.res.headers.append('X-Debug', 'Debug message')
175
+ })
176
+ ```
177
+
178
+ [Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response
179
+
180
+ ## set() / get()
181
+
182
+ Get and set arbitrary key-value pairs, with a lifetime of the current request. This allows passing specific values between middleware or from middleware to route handlers.
183
+
184
+ ```ts twoslash
185
+ import { Acryl } from 'acrylblends'
186
+ const app = new Acryl<{ Variables: { message: string } }>()
187
+ // ---cut---
188
+ app.use(async (c, next) => {
189
+ c.set('message', 'Acryl is cool!!')
190
+ await next()
191
+ })
192
+
193
+ app.get('/', (c) => {
194
+ const message = c.get('message')
195
+ return c.text(`The message is "${message}"`)
196
+ })
197
+ ```
198
+
199
+ Pass the `Variables` as Generics to the constructor of `Acryl` to make it type-safe.
200
+
201
+ ```ts twoslash
202
+ import { Acryl } from 'acrylblends'
203
+ // ---cut---
204
+ type Variables = {
205
+ message: string
206
+ }
207
+
208
+ const app = new Acryl<{ Variables: Variables }>()
209
+ ```
210
+
211
+ The value of `c.set` / `c.get` are retained only within the same request. They cannot be shared or persisted across different requests.
212
+
213
+ ## var
214
+
215
+ You can also access the value of a variable with `c.var`.
216
+
217
+ ```ts twoslash
218
+ import type { Context } from 'acrylblends'
219
+ declare const c: Context
220
+ // ---cut---
221
+ const result = c.var.client.oneMethod()
222
+ ```
223
+
224
+ If you want to create the middleware which provides a custom method,
225
+ write like the following:
226
+
227
+ ```ts twoslash
228
+ import { Acryl } from 'acrylblends'
229
+ import { createMiddleware } from 'acrylblends/factory'
230
+ // ---cut---
231
+ type Env = {
232
+ Variables: {
233
+ echo: (str: string) => string
234
+ }
235
+ }
236
+
237
+ const app = new Acryl()
238
+
239
+ const echoMiddleware = createMiddleware<Env>(async (c, next) => {
240
+ c.set('echo', (str) => str)
241
+ await next()
242
+ })
243
+
244
+ app.get('/echo', echoMiddleware, (c) => {
245
+ return c.text(c.var.echo('Hello!'))
246
+ })
247
+ ```
248
+
249
+ If you want to use the middleware in multiple handlers, you can use `app.use()`.
250
+ Then, you have to pass the `Env` as Generics to the constructor of `Acryl` to make it type-safe.
251
+
252
+ ```ts twoslash
253
+ import { Acryl } from 'acrylblends'
254
+ import type { MiddlewareHandler } from 'acrylblends/types'
255
+ declare const echoMiddleware: MiddlewareHandler
256
+ type Env = {
257
+ Variables: {
258
+ echo: (str: string) => string
259
+ }
260
+ }
261
+ // ---cut---
262
+ const app = new Acryl<Env>()
263
+
264
+ app.use(echoMiddleware)
265
+
266
+ app.get('/echo', (c) => {
267
+ return c.text(c.var.echo('Hello!'))
268
+ })
269
+ ```
270
+
271
+ ## render() / setRenderer()
272
+
273
+ You can set a layout using `c.setRenderer()` within a custom middleware.
274
+
275
+ ```tsx
276
+ /** @jsx jsx */
277
+ /** @jsxImportSource acrylblends/jsx */
278
+ import { Acryl } from 'acrylblends'
279
+ const app = new Acryl()
280
+ // ---cut---
281
+ app.use(async (c, next) => {
282
+ c.setRenderer((content) => {
283
+ return c.html(
284
+ <html>
285
+ <body>
286
+ <p>{content}</p>
287
+ </body>
288
+ </html>
289
+ )
290
+ })
291
+ await next()
292
+ })
293
+ ```
294
+
295
+ Then, you can utilize `c.render()` to create responses within this layout.
296
+
297
+ ```ts twoslash
298
+ import { Acryl } from 'acrylblends'
299
+ const app = new Acryl()
300
+ // ---cut---
301
+ app.get('/', (c) => {
302
+ return c.render('Hello!')
303
+ })
304
+ ```
305
+
306
+ The output of which will be:
307
+
308
+ ```html
309
+ <html>
310
+ <body>
311
+ <p>Hello!</p>
312
+ </body>
313
+ </html>
314
+ ```
315
+
316
+ Additionally, this feature offers the flexibility to customize arguments.
317
+ To ensure type safety, types can be defined as:
318
+
319
+ ```ts
320
+ declare module 'acrylblends' {
321
+ interface ContextRenderer {
322
+ (
323
+ content: string | Promise<string>,
324
+ head: { title: string }
325
+ ): Response | Promise<Response>
326
+ }
327
+ }
328
+ ```
329
+
330
+ Here's an example of how you can use this:
331
+
332
+ ```ts
333
+ app.use('/pages/*', async (c, next) => {
334
+ c.setRenderer((content, head) => {
335
+ return c.html(
336
+ <html>
337
+ <head>
338
+ <title>{head.title}</title>
339
+ </head>
340
+ <body>
341
+ <header>{head.title}</header>
342
+ <p>{content}</p>
343
+ </body>
344
+ </html>
345
+ )
346
+ })
347
+ await next()
348
+ })
349
+
350
+ app.get('/pages/my-favorite', (c) => {
351
+ return c.render(<p>Ramen and Sushi</p>, {
352
+ title: 'My favorite',
353
+ })
354
+ })
355
+
356
+ app.get('/pages/my-hobbies', (c) => {
357
+ return c.render(<p>Watching baseball</p>, {
358
+ title: 'My hobbies',
359
+ })
360
+ })
361
+ ```
362
+
363
+ ## executionCtx
364
+
365
+ You can access Cloudflare Workers' specific [ExecutionContext](https://developers.cloudflare.com/workers/runtime-apis/context/).
366
+
367
+ ```ts twoslash
368
+ import { Acryl } from 'acrylblends'
369
+ const app = new Acryl<{
370
+ Bindings: {
371
+ KV: any
372
+ }
373
+ }>()
374
+ declare const key: string
375
+ declare const data: string
376
+ // ---cut---
377
+ // ExecutionContext object
378
+ app.get('/foo', async (c) => {
379
+ c.executionCtx.waitUntil(c.env.KV.put(key, data))
380
+ // ...
381
+ })
382
+ ```
383
+
384
+ The `ExecutionContext` also has an [`exports`](https://developers.cloudflare.com/workers/runtime-apis/context/#exports) field. To get autocomplete with Wrangler's generated types, you can use module augmentation:
385
+
386
+ ```ts
387
+ import 'acrylblends'
388
+
389
+ declare module 'acrylblends' {
390
+ interface ExecutionContext {
391
+ readonly exports: Cloudflare.Exports
392
+ }
393
+ }
394
+ ```
395
+
396
+ ## event
397
+
398
+ You can access Cloudflare Workers' specific `FetchEvent`. This was used in "Service Worker" syntax. But, it is not recommended now.
399
+
400
+ ```ts twoslash
401
+ import { Acryl } from 'acrylblends'
402
+ declare const key: string
403
+ declare const data: string
404
+ type KVNamespace = any
405
+ // ---cut---
406
+ // Type definition to make type inference
407
+ type Bindings = {
408
+ MY_KV: KVNamespace
409
+ }
410
+
411
+ const app = new Acryl<{ Bindings: Bindings }>()
412
+
413
+ // FetchEvent object (only set when using Service Worker syntax)
414
+ app.get('/foo', async (c) => {
415
+ c.event.waitUntil(c.env.MY_KV.put(key, data))
416
+ // ...
417
+ })
418
+ ```
419
+
420
+ ## env
421
+
422
+ In Cloudflare Workers Environment variables, secrets, KV namespaces, D1 database, R2 bucket etc. that are bound to a worker are known as bindings.
423
+ Regardless of type, bindings are always available as global variables and can be accessed via the context `c.env.BINDING_KEY`.
424
+
425
+ ```ts twoslash
426
+ import { Acryl } from 'acrylblends'
427
+ type KVNamespace = any
428
+ // ---cut---
429
+ // Type definition to make type inference
430
+ type Bindings = {
431
+ MY_KV: KVNamespace
432
+ }
433
+
434
+ const app = new Acryl<{ Bindings: Bindings }>()
435
+
436
+ // Environment object for Cloudflare Workers
437
+ app.get('/', async (c) => {
438
+ c.env.MY_KV.get('my-key')
439
+ // ...
440
+ })
441
+ ```
442
+
443
+ ## error
444
+
445
+ If the Handler throws an error, the error object is placed in `c.error`.
446
+ You can access it in your middleware.
447
+
448
+ ```ts twoslash
449
+ import { Acryl } from 'acrylblends'
450
+ const app = new Acryl()
451
+ // ---cut---
452
+ app.use(async (c, next) => {
453
+ await next()
454
+ if (c.error) {
455
+ // do something...
456
+ }
457
+ })
458
+ ```
459
+
460
+ ## ContextVariableMap
461
+
462
+ **Warning.**
463
+
464
+ `ContextVariableMap` adds types **globally** to all contexts, regardless of whether the middleware that sets the variable has actually run. This means `c.get('result')` will appear type-safe even in handlers where your middleware was never registered, potentially hiding `undefined` bugs at runtime.
465
+
466
+ Take a look at the following example:
467
+
468
+ ```ts
469
+ declare module 'acrylblends' {
470
+ interface ContextVariableMap {
471
+ result: string
472
+ }
473
+ }
474
+
475
+ const mw = createMiddleware(async (c, next) => {
476
+ c.set('result', 'some values')
477
+ await next()
478
+ })
479
+
480
+ const app = new Acryl()
481
+
482
+ // handler uses the middleware
483
+ app.get('/foo', mw, (c) => {
484
+ const val = c.get('result') // ✅ val is a string and typed as such, as expected
485
+ })
486
+
487
+ // handler doesn't use the middleware
488
+ app.get('/bar', (c) => {
489
+ const val = c.get('result') // ❌ val is undefined but typed as a string, which can lead to runtime errors
490
+ })
491
+ ```
492
+
493
+ You can augment the `ContextVariableMap` interface to define types for context variables globally across your entire application. This is appropriate when a variable is set by middleware that is applied app-wide and is guaranteed to exist in the context.
494
+
495
+ For example:
496
+
497
+ ```ts
498
+ declare module 'acrylblends' {
499
+ interface ContextVariableMap {
500
+ result: string
501
+ }
502
+ }
503
+ ```
504
+
505
+ You can then utilize this in your middleware:
506
+
507
+ ```ts twoslash
508
+ import { createMiddleware } from 'acrylblends/factory'
509
+ // ---cut---
510
+ const mw = createMiddleware(async (c, next) => {
511
+ c.set('result', 'some values') // result is a string
512
+ await next()
513
+ })
514
+ ```
515
+
516
+ In a handler, the variable is inferred as the proper type:
517
+
518
+ ```ts twoslash
519
+ import { Acryl } from 'acrylblends'
520
+ const app = new Acryl<{ Variables: { result: string } }>()
521
+ // ---cut---
522
+ app.get('/', (c) => {
523
+ const val = c.get('result') // val is a string
524
+ // ...
525
+ return c.json({ result: val })
526
+ })
527
+ ```
@@ -0,0 +1,80 @@
1
+ # HTTPException
2
+
3
+ When a fatal error occurs, Acryl (and many ecosystem middleware) may throw an `HTTPException`. This is a custom Acryl `Error` that simplifies [returning error responses](#handling-httpexceptions).
4
+
5
+ ## Throwing HTTPExceptions
6
+
7
+ You can throw your own HTTPExceptions by specifying a status code, and either a message or a custom response.
8
+
9
+ ### Custom Message
10
+
11
+ For basic `text` responses, just set the error `message`.
12
+
13
+ ```ts twoslash
14
+ import { HTTPException } from 'acrylblends/http-exception'
15
+
16
+ throw new HTTPException(401, { message: 'Unauthorized' })
17
+ ```
18
+
19
+ ### Custom Response
20
+
21
+ For other response types, or to set response headers, use the `res` option. _Note that the status passed to the constructor is the one used to create responses._
22
+
23
+ ```ts twoslash
24
+ import { HTTPException } from 'acrylblends/http-exception'
25
+
26
+ const errorResponse = new Response('Unauthorized', {
27
+ status: 401, // this gets ignored
28
+ headers: {
29
+ Authenticate: 'error="invalid_token"',
30
+ },
31
+ })
32
+
33
+ throw new HTTPException(401, { res: errorResponse })
34
+ ```
35
+
36
+ ### Cause
37
+
38
+ In either case, you can use the [`cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) option to add arbitrary data to the HTTPException.
39
+
40
+ ```ts twoslash
41
+ import { Acryl, Context } from 'acrylblends'
42
+ import { HTTPException } from 'acrylblends/http-exception'
43
+ const app = new Acryl()
44
+ declare const message: string
45
+ declare const authorize: (c: Context) => Promise<void>
46
+ // ---cut---
47
+ app.post('/login', async (c) => {
48
+ try {
49
+ await authorize(c)
50
+ } catch (cause) {
51
+ throw new HTTPException(401, { message, cause })
52
+ }
53
+ return c.redirect('/')
54
+ })
55
+ ```
56
+
57
+ ## Handling HTTPExceptions
58
+
59
+ You can handle uncaught HTTPExceptions with [`app.onError`](acryl.md#error-handling). They include a `getResponse` method that returns a new `Response` created from the error `status`, and either the error `message`, or the [custom response](#custom-response) set when the error was thrown.
60
+
61
+ ```ts twoslash
62
+ import { Acryl } from 'acrylblends'
63
+ const app = new Acryl()
64
+ // ---cut---
65
+ import { HTTPException } from 'acrylblends/http-exception'
66
+
67
+ // ...
68
+
69
+ app.onError((err, c) => {
70
+ if (err instanceof HTTPException) {
71
+ // Return the error response generated by HTTPException
72
+ return err.getResponse()
73
+ }
74
+ // For any other unexpected errors, log and return a generic 500 response
75
+ console.error(err)
76
+ return c.text('Internal Server Error', 500)
77
+ })
78
+ ```
79
+
80
+ > **Warning.** **`HTTPException.getResponse` is not aware of `Context`**. To include headers already set in `Context`, you must apply them to a new `Response`.
@@ -0,0 +1,12 @@
1
+ # API
2
+
3
+ Acryl's API is simple.
4
+ Just composed by extended objects from Web Standards.
5
+ So, you can understand it well quickly.
6
+
7
+ In this section, we introduce API of Acryl like below.
8
+
9
+ - Acryl object
10
+ - About routing
11
+ - Context object
12
+ - About middleware
@@ -0,0 +1,65 @@
1
+ # Presets
2
+
3
+ > **Partly available.** The default router (`SmartRouter`), `RegExpRouter`, `TrieRouter`, `LinearRouter` and `PatternRouter` are available and are chosen with the `router` option of `new Acryl()` (see [Routers](../concepts/routers.md)). The presets `acrylblends/quick` and `acrylblends/tiny` are **not yet available**; their examples below are not checked by the docs tests.
4
+
5
+
6
+ Acryl has several routers, each designed for a specific purpose.
7
+ You can specify the router you want to use in the constructor of Acryl.
8
+
9
+ **Presets** are provided for common use cases, so you don't have to specify the router each time.
10
+ The `Acryl` class imported from all presets is the same, the only difference being the router.
11
+ Therefore, you can use them interchangeably.
12
+
13
+ ## `acrylblends`
14
+
15
+ Usage:
16
+
17
+ ```ts twoslash
18
+ import { Acryl } from 'acrylblends'
19
+ ```
20
+
21
+ Routers:
22
+
23
+ ```ts
24
+ this.router = new SmartRouter({
25
+ routers: [new RegExpRouter(), new TrieRouter()],
26
+ })
27
+ ```
28
+
29
+ ## `acrylblends/quick`
30
+
31
+ Usage:
32
+
33
+ ```ts twoslash
34
+ import { Acryl } from 'acrylblends/quick'
35
+ ```
36
+
37
+ Router:
38
+
39
+ ```ts
40
+ this.router = new SmartRouter({
41
+ routers: [new LinearRouter(), new TrieRouter()],
42
+ })
43
+ ```
44
+
45
+ ## `acrylblends/tiny`
46
+
47
+ Usage:
48
+
49
+ ```ts twoslash
50
+ import { Acryl } from 'acrylblends/tiny'
51
+ ```
52
+
53
+ Router:
54
+
55
+ ```ts
56
+ this.router = new PatternRouter()
57
+ ```
58
+
59
+ ## Which preset should I use?
60
+
61
+ | Preset | Suitable platforms |
62
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | `acrylblends` | This is highly recommended for most use cases. Although the registration phase may be slower than `acrylblends/quick`, it exhibits high performance once booted. It's ideal for long-life servers built with **Deno**, **Bun**, or **Node.js**. It is also suitable for **Fastly Compute**, as route registration occurs during the app build phase on that platform. For environments such as **Cloudflare Workers**, **Deno Deploy**, where v8 isolates are utilized, this preset is suitable as well because the isolations persist for a certain amount of time after booting. |
64
+ | `acrylblends/quick` | This preset is designed for environments where the application is initialized for every request. |
65
+ | `acrylblends/tiny` | This is the smallest router package and it's suitable for environments where resources are limited. |