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.
- package/README.md +61 -2
- package/bin/create-acrylblends.js +4 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +274 -0
- package/dist/index.js.map +1 -0
- package/docs/framework/LICENSE +23 -0
- package/docs/framework/README.md +63 -0
- package/docs/framework/UPSTREAM.md +3 -0
- package/docs/framework/agents/index.md +24 -0
- package/docs/framework/api/acryl.md +259 -0
- package/docs/framework/api/context.md +527 -0
- package/docs/framework/api/exception.md +80 -0
- package/docs/framework/api/index.md +12 -0
- package/docs/framework/api/presets.md +65 -0
- package/docs/framework/api/request.md +396 -0
- package/docs/framework/api/routing.md +303 -0
- package/docs/framework/api/summary.md +140 -0
- package/docs/framework/concepts/benchmarks.md +26 -0
- package/docs/framework/concepts/developer-experience.md +5 -0
- package/docs/framework/concepts/middleware.md +21 -0
- package/docs/framework/concepts/motivation.md +14 -0
- package/docs/framework/concepts/routers.md +63 -0
- package/docs/framework/concepts/stacks.md +235 -0
- package/docs/framework/concepts/web-standard.md +37 -0
- package/docs/framework/cordis/acryl-in-a-cordis-app.md +146 -0
- package/docs/framework/cordis/concepts.md +105 -0
- package/docs/framework/cordis/middleware.md +8 -0
- package/docs/framework/cordis/migration-from-0-3.md +111 -0
- package/docs/framework/cordis/migration-from-0-4.md +14 -0
- package/docs/framework/cordis/migration-from-dsh-webserver.md +109 -0
- package/docs/framework/cordis/mounting.md +85 -0
- package/docs/framework/cordis/node-server.md +75 -0
- package/docs/framework/cordis/plugin-lifecycle.md +111 -0
- package/docs/framework/cordis/surfaces.md +71 -0
- package/docs/framework/cordis/transport-and-cancellation.md +57 -0
- package/docs/framework/cordis/validation.md +135 -0
- package/docs/framework/getting-started/basic.md +196 -0
- package/docs/framework/getting-started/bun.md +221 -0
- package/docs/framework/getting-started/nodejs.md +344 -0
- package/docs/framework/getting-started/other-runtimes.md +23 -0
- package/docs/framework/guides/best-practices.md +231 -0
- package/docs/framework/guides/create-acrylblends.md +79 -0
- package/docs/framework/guides/examples.md +3 -0
- package/docs/framework/guides/faq.md +19 -0
- package/docs/framework/guides/helpers.md +33 -0
- package/docs/framework/guides/jsx-dom.md +299 -0
- package/docs/framework/guides/jsx.md +440 -0
- package/docs/framework/guides/middleware.md +253 -0
- package/docs/framework/guides/rpc.md +886 -0
- package/docs/framework/guides/testing.md +133 -0
- package/docs/framework/guides/validation.md +383 -0
- package/docs/framework/helpers/accepts.md +60 -0
- package/docs/framework/helpers/adapter.md +87 -0
- package/docs/framework/helpers/conninfo.md +112 -0
- package/docs/framework/helpers/cookie.md +232 -0
- package/docs/framework/helpers/css.md +285 -0
- package/docs/framework/helpers/dev.md +67 -0
- package/docs/framework/helpers/factory.md +180 -0
- package/docs/framework/helpers/html.md +123 -0
- package/docs/framework/helpers/jwt.md +184 -0
- package/docs/framework/helpers/proxy.md +118 -0
- package/docs/framework/helpers/route.md +143 -0
- package/docs/framework/helpers/ssg.md +393 -0
- package/docs/framework/helpers/streaming.md +119 -0
- package/docs/framework/helpers/testing.md +101 -0
- package/docs/framework/helpers/websocket.md +215 -0
- package/docs/framework/middleware/builtin/basic-auth.md +165 -0
- package/docs/framework/middleware/builtin/bearer-auth.md +138 -0
- package/docs/framework/middleware/builtin/body-limit.md +71 -0
- package/docs/framework/middleware/builtin/cache.md +122 -0
- package/docs/framework/middleware/builtin/combine.md +94 -0
- package/docs/framework/middleware/builtin/compress.md +59 -0
- package/docs/framework/middleware/builtin/context-storage.md +78 -0
- package/docs/framework/middleware/builtin/cors.md +135 -0
- package/docs/framework/middleware/builtin/csrf.md +105 -0
- package/docs/framework/middleware/builtin/etag.md +54 -0
- package/docs/framework/middleware/builtin/ip-restriction.md +69 -0
- package/docs/framework/middleware/builtin/jsx-renderer.md +286 -0
- package/docs/framework/middleware/builtin/jwk.md +192 -0
- package/docs/framework/middleware/builtin/jwt.md +145 -0
- package/docs/framework/middleware/builtin/language.md +232 -0
- package/docs/framework/middleware/builtin/logger.md +74 -0
- package/docs/framework/middleware/builtin/loopback-only.md +31 -0
- package/docs/framework/middleware/builtin/method-not-allowed.md +48 -0
- package/docs/framework/middleware/builtin/method-override.md +80 -0
- package/docs/framework/middleware/builtin/mount.md +106 -0
- package/docs/framework/middleware/builtin/pretty-json.md +53 -0
- package/docs/framework/middleware/builtin/request-id.md +94 -0
- package/docs/framework/middleware/builtin/secure-headers.md +247 -0
- package/docs/framework/middleware/builtin/timeout.md +98 -0
- package/docs/framework/middleware/builtin/timing.md +101 -0
- package/docs/framework/middleware/builtin/trailing-slash.md +74 -0
- package/docs/framework/middleware/third-party.md +4 -0
- package/docs/framework/upstream.json +9 -0
- package/package.json +47 -3
- package/templates/bun/gitignore +1 -0
- package/templates/bun/package.json +19 -0
- package/templates/bun/src/index.ts +7 -0
- package/templates/bun/test/app.test.ts +8 -0
- package/templates/bun/tsconfig.json +15 -0
- package/templates/nodejs/gitignore +1 -0
- package/templates/nodejs/package.json +22 -0
- package/templates/nodejs/src/app.ts +7 -0
- package/templates/nodejs/src/index.ts +9 -0
- package/templates/nodejs/test/app.test.ts +9 -0
- package/templates/nodejs/tsconfig.json +16 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Bun
|
|
2
|
+
|
|
3
|
+
> **Experimental.** Bun is not a verified runtime yet: the Acryl application code is the same, but the `bun` template and this guide are not covered by the release checks. Node.js is the verified runtime.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[Bun](https://bun.com) is another JavaScript runtime. It's not Node.js. Bun includes a transcompiler, so we can write the code in TypeScript or plain JavaScript.
|
|
7
|
+
Acryl also works on Bun.
|
|
8
|
+
|
|
9
|
+
## 1. Install Bun
|
|
10
|
+
|
|
11
|
+
To install `bun` command, follow the instruction in [the official web site](https://bun.com).
|
|
12
|
+
|
|
13
|
+
## 2. Setup
|
|
14
|
+
|
|
15
|
+
### 2.1. Setup a new project
|
|
16
|
+
|
|
17
|
+
A starter for Bun is available. Start your project with "bun create" command.
|
|
18
|
+
Select `bun` template for this example.
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
bun create acrylblends@latest my-app
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Move into my-app and install the dependencies.
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
cd my-app
|
|
28
|
+
bun install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2.2. Setup an existing project
|
|
32
|
+
|
|
33
|
+
On an existing Bun project, we only need to install `acrylblends` dependencies on the project root directory via
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
bun add acrylblends
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then add the `dev` command to your existing `package.json`.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"scripts": {
|
|
44
|
+
"dev": "bun run --hot src/index.ts"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
See the Bun starter template for a minimal example setup. This is the output of running `bun create acrylblends@latest`.
|
|
50
|
+
|
|
51
|
+
## 3. Hello World
|
|
52
|
+
|
|
53
|
+
"Hello World" script is below. Almost the same as writing on other platforms.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { Acryl } from 'acrylblends'
|
|
57
|
+
|
|
58
|
+
const app = new Acryl()
|
|
59
|
+
app.get('/', (c) => c.text('Hello Bun!'))
|
|
60
|
+
|
|
61
|
+
export default app
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If you are setting up Acryl on an existing project, the `bun run dev` command expects the "Hello World" script to be placed in `src/index.ts`
|
|
65
|
+
|
|
66
|
+
## 4. Run
|
|
67
|
+
|
|
68
|
+
Run the command.
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
bun run dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Then, access `http://localhost:3000` in your browser.
|
|
75
|
+
|
|
76
|
+
## Change port number
|
|
77
|
+
|
|
78
|
+
You can specify the port number with exporting the `port`.
|
|
79
|
+
|
|
80
|
+
<!-- prettier-ignore -->
|
|
81
|
+
```ts
|
|
82
|
+
import { Acryl } from 'acrylblends'
|
|
83
|
+
|
|
84
|
+
const app = new Acryl()
|
|
85
|
+
app.get('/', (c) => c.text('Hello Bun!'))
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
port: 3000,
|
|
89
|
+
fetch: app.fetch,
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Serve static files
|
|
94
|
+
|
|
95
|
+
To serve static files, use `serveStatic` from `acrylblends/bun`.
|
|
96
|
+
|
|
97
|
+
> **Not yet available.** The Bun adapter, `acrylblends/bun`, is not part of acrylblends yet. The code below shows the planned usage.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { serveStatic } from 'acrylblends/bun'
|
|
101
|
+
|
|
102
|
+
const app = new Acryl()
|
|
103
|
+
|
|
104
|
+
app.use('/static/*', serveStatic({ root: './' }))
|
|
105
|
+
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
|
|
106
|
+
app.get('/', (c) => c.text('You can access: /static/hello.txt'))
|
|
107
|
+
app.get('*', serveStatic({ path: './static/fallback.txt' }))
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
For the above code, it will work well with the following directory structure.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
./
|
|
114
|
+
├── favicon.ico
|
|
115
|
+
├── src
|
|
116
|
+
└── static
|
|
117
|
+
├── demo
|
|
118
|
+
│ └── index.html
|
|
119
|
+
├── fallback.txt
|
|
120
|
+
├── hello.txt
|
|
121
|
+
└── images
|
|
122
|
+
└── dinotocat.png
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `rewriteRequestPath`
|
|
126
|
+
|
|
127
|
+
If you want to map `http://localhost:3000/static/*` to `./statics`, you can use the `rewriteRequestPath` option:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
app.get(
|
|
131
|
+
'/static/*',
|
|
132
|
+
serveStatic({
|
|
133
|
+
root: './',
|
|
134
|
+
rewriteRequestPath: (path) =>
|
|
135
|
+
path.replace(/^\/static/, '/statics'),
|
|
136
|
+
})
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `mimes`
|
|
141
|
+
|
|
142
|
+
You can add MIME types with `mimes`:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
app.get(
|
|
146
|
+
'/static/*',
|
|
147
|
+
serveStatic({
|
|
148
|
+
mimes: {
|
|
149
|
+
m3u8: 'application/vnd.apple.mpegurl',
|
|
150
|
+
ts: 'video/mp2t',
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `onFound`
|
|
157
|
+
|
|
158
|
+
You can specify handling when the requested file is found with `onFound`:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
app.get(
|
|
162
|
+
'/static/*',
|
|
163
|
+
serveStatic({
|
|
164
|
+
// ...
|
|
165
|
+
onFound: (_path, c) => {
|
|
166
|
+
c.header('Cache-Control', `public, immutable, max-age=31536000`)
|
|
167
|
+
},
|
|
168
|
+
})
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `onNotFound`
|
|
173
|
+
|
|
174
|
+
You can specify handling when the requested file is not found with `onNotFound`:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
app.get(
|
|
178
|
+
'/static/*',
|
|
179
|
+
serveStatic({
|
|
180
|
+
onNotFound: (path, c) => {
|
|
181
|
+
console.log(`${path} is not found, you access ${c.req.path}`)
|
|
182
|
+
},
|
|
183
|
+
})
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### `precompressed`
|
|
188
|
+
|
|
189
|
+
The `precompressed` option checks if files with extensions like `.br` or `.gz` are available and serves them based on the `Accept-Encoding` header. It prioritizes Brotli, then Zstd, and Gzip. If none are available, it serves the original file.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
app.get(
|
|
193
|
+
'/static/*',
|
|
194
|
+
serveStatic({
|
|
195
|
+
precompressed: true,
|
|
196
|
+
})
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Testing
|
|
201
|
+
|
|
202
|
+
You can use `bun:test` for testing on Bun.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
import { describe, expect, it } from 'bun:test'
|
|
206
|
+
import app from '.'
|
|
207
|
+
|
|
208
|
+
describe('My first test', () => {
|
|
209
|
+
it('Should return 200 Response', async () => {
|
|
210
|
+
const req = new Request('http://localhost/')
|
|
211
|
+
const res = await app.fetch(req)
|
|
212
|
+
expect(res.status).toBe(200)
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Then, run the command.
|
|
218
|
+
|
|
219
|
+
```sh
|
|
220
|
+
bun test index.test.ts
|
|
221
|
+
```
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Node.js
|
|
2
|
+
|
|
3
|
+
[Node.js](https://nodejs.org/) is an open-source, cross-platform JavaScript runtime environment.
|
|
4
|
+
|
|
5
|
+
On Node.js, Acryl runs through the Node.js adapter, `acrylblends/node-server`.
|
|
6
|
+
|
|
7
|
+
> **Note.** Verified on Node.js 22.19 and newer, which runs TypeScript files directly.
|
|
8
|
+
|
|
9
|
+
## 1. Setup
|
|
10
|
+
|
|
11
|
+
A starter for Node.js is available.
|
|
12
|
+
Start your project with "create-acrylblends" command.
|
|
13
|
+
Select `nodejs` template for this example.
|
|
14
|
+
|
|
15
|
+
**npm**
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm create acrylblends@latest my-app
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**yarn**
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
yarn create acrylblends my-app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**pnpm**
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
pnpm create acrylblends my-app
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**bun**
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
bun create acrylblends@latest my-app
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Move to `my-app` and install the dependencies.
|
|
40
|
+
|
|
41
|
+
**npm**
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
cd my-app
|
|
45
|
+
npm i
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**yarn**
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
cd my-app
|
|
52
|
+
yarn
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**pnpm**
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
cd my-app
|
|
59
|
+
pnpm i
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**bun**
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
cd my-app
|
|
66
|
+
bun i
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 2. Hello World
|
|
70
|
+
|
|
71
|
+
Edit `src/index.ts`:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { serve } from 'acrylblends/node-server'
|
|
75
|
+
import { Acryl } from 'acrylblends'
|
|
76
|
+
|
|
77
|
+
const app = new Acryl()
|
|
78
|
+
app.get('/', (c) => c.text('Hello Node.js!'))
|
|
79
|
+
|
|
80
|
+
serve(app)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If you want to gracefully shut down the server, write it like this:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
const server = serve(app)
|
|
87
|
+
|
|
88
|
+
// graceful shutdown
|
|
89
|
+
process.on('SIGINT', () => {
|
|
90
|
+
server.close()
|
|
91
|
+
process.exit(0)
|
|
92
|
+
})
|
|
93
|
+
process.on('SIGTERM', () => {
|
|
94
|
+
server.close((err) => {
|
|
95
|
+
if (err) {
|
|
96
|
+
console.error(err)
|
|
97
|
+
process.exit(1)
|
|
98
|
+
}
|
|
99
|
+
process.exit(0)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> **Note.** On Node.js, `serve()` wraps the `node:http` module and returns the underlying server instance, so closing it is up to you. Bun serves Fetch handlers natively and manages the server itself, which is why its guide doesn't include this step.
|
|
105
|
+
|
|
106
|
+
## 3. Run
|
|
107
|
+
|
|
108
|
+
Run the development server locally. Then, access `http://localhost:3000` in your Web browser.
|
|
109
|
+
|
|
110
|
+
**npm**
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
npm run dev
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**yarn**
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
yarn dev
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**pnpm**
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
pnpm dev
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Change port number
|
|
129
|
+
|
|
130
|
+
You can specify the port number with the `port` option.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
serve({
|
|
134
|
+
fetch: app.fetch,
|
|
135
|
+
port: 8787,
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## WebSocket
|
|
140
|
+
|
|
141
|
+
WebSocket support is built into `acrylblends/node-server`. Install `ws` and, if you use TypeScript, `@types/ws`. Then create a `WebSocketServer` with `{ noServer: true }` and pass it to `serve()` with the `websocket` option.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { serve, upgradeWebSocket } from 'acrylblends/node-server'
|
|
145
|
+
import { Acryl } from 'acrylblends'
|
|
146
|
+
import { WebSocketServer } from 'ws'
|
|
147
|
+
|
|
148
|
+
const app = new Acryl()
|
|
149
|
+
|
|
150
|
+
app.get(
|
|
151
|
+
'/ws',
|
|
152
|
+
upgradeWebSocket(() => ({
|
|
153
|
+
onMessage(event, ws) {
|
|
154
|
+
ws.send(String(event.data))
|
|
155
|
+
},
|
|
156
|
+
}))
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
const wss = new WebSocketServer({ noServer: true })
|
|
160
|
+
|
|
161
|
+
serve({
|
|
162
|
+
fetch: app.fetch,
|
|
163
|
+
websocket: { server: wss },
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Access the raw Node.js APIs
|
|
168
|
+
|
|
169
|
+
You can access the Node.js APIs from `c.env.incoming` and `c.env.outgoing`.
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { Acryl } from 'acrylblends'
|
|
173
|
+
import { serve, type HttpBindings } from 'acrylblends/node-server'
|
|
174
|
+
// or `Http2Bindings` if you use HTTP2
|
|
175
|
+
|
|
176
|
+
type Bindings = HttpBindings & {
|
|
177
|
+
/* ... */
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const app = new Acryl<{ Bindings: Bindings }>()
|
|
181
|
+
|
|
182
|
+
app.get('/', (c) => {
|
|
183
|
+
return c.json({
|
|
184
|
+
remoteAddress: c.env.incoming.socket.remoteAddress,
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
serve(app)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Serve static files
|
|
192
|
+
|
|
193
|
+
You can use `serveStatic` to serve static files from the local file system. For example, suppose the directory structure is as follows:
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
./
|
|
197
|
+
├── favicon.ico
|
|
198
|
+
├── index.ts
|
|
199
|
+
└── static
|
|
200
|
+
├── hello.txt
|
|
201
|
+
└── image.png
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
If a request to the path `/static/*` comes in and you want to return a file under `./static`, you can write the following:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { serveStatic } from 'acrylblends/node-server'
|
|
208
|
+
|
|
209
|
+
app.use('/static/*', serveStatic({ root: './' }))
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Warning.**
|
|
213
|
+
|
|
214
|
+
The `root` option resolves paths relative to the current working directory (`process.cwd()`). This means the behavior depends on **where you run your Node.js process from**, not where your source file is located. If you start your server from a different directory, file resolution may fail.
|
|
215
|
+
|
|
216
|
+
For reliable path resolution that always points to the same directory as your source file, use `import.meta.url`:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { fileURLToPath } from 'node:url'
|
|
220
|
+
import { serveStatic } from 'acrylblends/node-server'
|
|
221
|
+
|
|
222
|
+
app.use(
|
|
223
|
+
'/static/*',
|
|
224
|
+
serveStatic({ root: fileURLToPath(new URL('./', import.meta.url)) })
|
|
225
|
+
)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Use the `path` option to serve `favicon.ico` in the directory root:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
If a request to the path `/hello.txt` or `/image.png` comes in and you want to return a file named `./static/hello.txt` or `./static/image.png`, you can use the following:
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
app.use('*', serveStatic({ root: './static' }))
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### `rewriteRequestPath`
|
|
241
|
+
|
|
242
|
+
If you want to map `http://localhost:3000/static/*` to `./statics`, you can use the `rewriteRequestPath` option:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
app.get(
|
|
246
|
+
'/static/*',
|
|
247
|
+
serveStatic({
|
|
248
|
+
root: './',
|
|
249
|
+
rewriteRequestPath: (path) =>
|
|
250
|
+
path.replace(/^\/static/, '/statics'),
|
|
251
|
+
})
|
|
252
|
+
)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## http2
|
|
256
|
+
|
|
257
|
+
You can run acrylblends on a [Node.js http2 Server](https://nodejs.org/api/http2.html).
|
|
258
|
+
|
|
259
|
+
### unencrypted http2
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { createServer } from 'node:http2'
|
|
263
|
+
|
|
264
|
+
const server = serve({
|
|
265
|
+
fetch: app.fetch,
|
|
266
|
+
createServer,
|
|
267
|
+
})
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### encrypted http2
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
import { createSecureServer } from 'node:http2'
|
|
274
|
+
import { readFileSync } from 'node:fs'
|
|
275
|
+
|
|
276
|
+
const server = serve({
|
|
277
|
+
fetch: app.fetch,
|
|
278
|
+
createServer: createSecureServer,
|
|
279
|
+
serverOptions: {
|
|
280
|
+
key: readFileSync('localhost-privkey.pem'),
|
|
281
|
+
cert: readFileSync('localhost-cert.pem'),
|
|
282
|
+
},
|
|
283
|
+
})
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Building & Deployment
|
|
287
|
+
|
|
288
|
+
**npm**
|
|
289
|
+
|
|
290
|
+
```sh
|
|
291
|
+
npm run build
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**yarn**
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
yarn run build
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**pnpm**
|
|
301
|
+
|
|
302
|
+
```sh
|
|
303
|
+
pnpm run build
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**bun**
|
|
307
|
+
|
|
308
|
+
```sh
|
|
309
|
+
bun run build
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Dockerfile
|
|
313
|
+
|
|
314
|
+
Here is an example of a Node.js Dockerfile.
|
|
315
|
+
|
|
316
|
+
```Dockerfile
|
|
317
|
+
FROM node:22-alpine AS base
|
|
318
|
+
|
|
319
|
+
FROM base AS builder
|
|
320
|
+
|
|
321
|
+
RUN apk add --no-cache gcompat
|
|
322
|
+
WORKDIR /app
|
|
323
|
+
|
|
324
|
+
COPY package*json tsconfig.json src ./
|
|
325
|
+
|
|
326
|
+
RUN npm ci && \
|
|
327
|
+
npm run build && \
|
|
328
|
+
npm prune --production
|
|
329
|
+
|
|
330
|
+
FROM base AS runner
|
|
331
|
+
WORKDIR /app
|
|
332
|
+
|
|
333
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
334
|
+
RUN adduser --system --uid 1001 acrylblends
|
|
335
|
+
|
|
336
|
+
COPY --from=builder --chown=acrylblends:nodejs /app/node_modules /app/node_modules
|
|
337
|
+
COPY --from=builder --chown=acrylblends:nodejs /app/dist /app/dist
|
|
338
|
+
COPY --from=builder --chown=acrylblends:nodejs /app/package.json /app/package.json
|
|
339
|
+
|
|
340
|
+
USER acrylblends
|
|
341
|
+
EXPOSE 3000
|
|
342
|
+
|
|
343
|
+
CMD ["node", "/app/dist/index.js"]
|
|
344
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Other runtimes
|
|
2
|
+
|
|
3
|
+
Acryl is built on Web Standards, so the same application code is expected to run wherever a `fetch`-style handler can run. Only Node.js ([guide](nodejs.md)) is verified so far. Bun is experimental ([guide](bun.md)).
|
|
4
|
+
|
|
5
|
+
The following runtimes and platforms are **not yet verified**. There are no getting-started pages for them yet, and their adapters (for example `acrylblends/cloudflare-workers`
|
|
6
|
+
or `acrylblends/aws-lambda`) are not part of acrylblends yet:
|
|
7
|
+
|
|
8
|
+
- Deno, and Deno Deploy
|
|
9
|
+
- Cloudflare Workers, and Cloudflare Pages
|
|
10
|
+
- Fastly Compute
|
|
11
|
+
- AWS Lambda, and Lambda@Edge
|
|
12
|
+
- Vercel
|
|
13
|
+
- Netlify
|
|
14
|
+
- Next.js
|
|
15
|
+
- Supabase Functions
|
|
16
|
+
- Google Cloud Run
|
|
17
|
+
- Azure Functions
|
|
18
|
+
- Alibaba Cloud Function Compute
|
|
19
|
+
- CloudBase
|
|
20
|
+
- Service Worker
|
|
21
|
+
- WebAssembly (WASI)
|
|
22
|
+
|
|
23
|
+
A page is added here, with a getting-started guide, when a platform has been verified with a test that runs on it.
|