@asterflow/adapter 1.0.14 → 2.0.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 +20 -143
- package/dist/cjs/index.cjs +11 -11
- package/dist/mjs/index.js +6 -6
- package/package.json +16 -6
package/README.md
CHANGED
|
@@ -10,177 +10,54 @@
|
|
|
10
10
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
>
|
|
13
|
+
> Wires a runtime's native server (Bun.serve, Node's `http`, Express, Fastify) into AsterFlow, converting native requests to `Request` and sending back `AsterResponse` the same way regardless of runtime.
|
|
14
14
|
|
|
15
15
|
## 📦 Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
npm install @asterflow/adapter
|
|
19
|
-
# or
|
|
20
18
|
bun install @asterflow/adapter
|
|
21
19
|
```
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
### ✨ Features
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
- **`adapters`** - a ready-made `Adapter` instance for each runtime: `adapters.bun`, `adapters.node`, `adapters.express`, `adapters.fastify`
|
|
24
|
+
- **`Runtime`** - the enum (`Bun`, `Node`, `Express`, `Fastify`) that types requests, listen arguments, and adapters to their runtime
|
|
25
|
+
- **`Adapter`** - a small class holding a `runtime`, a `listen(...)` function typed to that runtime's native `listen`/`serve` signature, and an `onRequest` hook that AsterFlow assigns to route native requests into its handler
|
|
26
|
+
- **Request conversion per runtime** - each adapter calls the matching `create*Request` factory from `@asterflow/request` (`createBunRequest`, `createNodeRequest`, `createExpressRequest`, `createFastifyRequest`) before handing the request to `onRequest`
|
|
27
|
+
- **Fallback response** - if `listen()` is called before `onRequest` is set, every adapter responds with a 500 instead of crashing
|
|
28
|
+
- **Error-to-response conversion** - `toErrorResponse(err)` turns a thrown value (an `Error`, an already-built `AsterResponse`, or anything else) into a JSON `AsterResponse`; the Node adapter uses it to catch per-request errors and return a 500 instead of hanging the connection
|
|
26
29
|
|
|
27
|
-
##
|
|
30
|
+
## ❓ How to Use
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
- Node.js HTTP Server
|
|
31
|
-
- Bun
|
|
32
|
-
- Express
|
|
33
|
-
- Fastify
|
|
34
|
-
- **Unified Interface:** Consistent API regardless of runtime
|
|
35
|
-
- **Error Handling:** Robust error handling system with standardized responses
|
|
36
|
-
- **Strong Typing:** Full TypeScript support with type inference
|
|
37
|
-
- **Router Integration:** Works seamlessly with AsterFlow's routing system
|
|
38
|
-
- **Zero Configuration:** Works immediately after installation
|
|
39
|
-
- **Middleware Support:** Compatible with runtime-specific middleware
|
|
32
|
+
Pick an adapter and pass it as the `driver` when creating an AsterFlow app — everything else (routes, `.listen()`) stays the same:
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
### Basic Example
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
import { AsterFlow } from 'asterflow'
|
|
47
|
-
import { adapters } from '@asterflow/adapter'
|
|
48
|
-
import { Router } from '@asterflow/router'
|
|
49
|
-
|
|
50
|
-
// Create an AsterFlow instance with the desired adapter
|
|
51
|
-
const app = new AsterFlow({
|
|
52
|
-
driver: adapters.node // or adapters.bun, adapters.express, adapters.fastify
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
// Define your routes
|
|
56
|
-
const router = new Router({
|
|
57
|
-
path: '/hello',
|
|
58
|
-
methods: {
|
|
59
|
-
get({ response }) {
|
|
60
|
-
return response.send('Hello World!')
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
// Register routes
|
|
66
|
-
app.controller(router)
|
|
67
|
-
|
|
68
|
-
// Start the server
|
|
69
|
-
app.listen({ port: 3000 })
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Available Adapters
|
|
73
|
-
|
|
74
|
-
#### Node.js HTTP Server
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
import { AsterFlow } from 'asterflow'
|
|
78
|
-
import { adapters } from '@asterflow/adapter'
|
|
79
|
-
|
|
80
|
-
const app = new AsterFlow({
|
|
81
|
-
driver: adapters.node
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
app.listen({ port: 3000 })
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
#### Bun
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
34
|
+
```ts
|
|
90
35
|
import { AsterFlow } from 'asterflow'
|
|
91
36
|
import { adapters } from '@asterflow/adapter'
|
|
92
37
|
|
|
93
|
-
const app = new AsterFlow({
|
|
94
|
-
driver: adapters.bun
|
|
95
|
-
})
|
|
38
|
+
const app = new AsterFlow({ driver: adapters.bun }) // or adapters.node, adapters.express, adapters.fastify
|
|
96
39
|
|
|
97
40
|
app.listen({ port: 3000 })
|
|
98
41
|
```
|
|
99
42
|
|
|
100
|
-
|
|
43
|
+
Express and Fastify need their own instance passed through `listen`, since AsterFlow mounts a catch-all route on it rather than starting its own server:
|
|
101
44
|
|
|
102
|
-
```
|
|
45
|
+
```ts
|
|
103
46
|
import { AsterFlow } from 'asterflow'
|
|
104
47
|
import { adapters } from '@asterflow/adapter'
|
|
105
48
|
import express from 'express'
|
|
106
49
|
|
|
107
|
-
const
|
|
108
|
-
const app = new AsterFlow({
|
|
109
|
-
driver: adapters.express
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
// Use Express middleware
|
|
113
|
-
expressApp.use(express.json())
|
|
114
|
-
|
|
115
|
-
app.listen(expressApp, 3000)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
#### Fastify
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { AsterFlow } from 'asterflow'
|
|
122
|
-
import { adapters } from '@asterflow/adapter'
|
|
123
|
-
import fastify from 'fastify'
|
|
124
|
-
|
|
125
|
-
const server = fastify()
|
|
126
|
-
const app = new AsterFlow({
|
|
127
|
-
driver: adapters.fastify
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
app.listen(server, { port: 3000 }, (err) => {
|
|
131
|
-
if (err) {
|
|
132
|
-
console.error(err)
|
|
133
|
-
process.exit(1)
|
|
134
|
-
}
|
|
135
|
-
console.log('Server listening!')
|
|
136
|
-
})
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## 🔧 Architecture
|
|
140
|
-
|
|
141
|
-
### Adapter System
|
|
142
|
-
|
|
143
|
-
The package uses an adapter system that implements the `Adapter` interface:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
class Adapter<Type extends Runtime> {
|
|
147
|
-
readonly runtime: Type
|
|
148
|
-
readonly listen: OptionsDriver<Type>['listen']
|
|
149
|
-
onRequest?: (request: Request, response: Response) => Promise<Response> | Response
|
|
150
|
-
}
|
|
151
|
-
```
|
|
50
|
+
const app = new AsterFlow({ driver: adapters.express })
|
|
152
51
|
|
|
153
|
-
|
|
154
|
-
- Runtime-specific server initialization
|
|
155
|
-
- Request conversion to AsterFlow format
|
|
156
|
-
- Standardized error handling
|
|
157
|
-
- Integration with the routing system
|
|
158
|
-
|
|
159
|
-
### Error Handling
|
|
160
|
-
|
|
161
|
-
The system includes robust error handling that:
|
|
162
|
-
- Standardizes error responses
|
|
163
|
-
- Provides stack traces in development environment
|
|
164
|
-
- Logs errors for diagnostics
|
|
165
|
-
- Maintains security by not exposing sensitive details in production
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
interface ErrorPayload {
|
|
169
|
-
statusCode: number
|
|
170
|
-
error: string
|
|
171
|
-
message: string
|
|
172
|
-
details?: unknown
|
|
173
|
-
}
|
|
52
|
+
app.listen(express(), 3000)
|
|
174
53
|
```
|
|
175
54
|
|
|
176
55
|
## 🔗 Related Packages
|
|
177
56
|
|
|
178
|
-
- [asterflow](https://www.npmjs.com/package/
|
|
179
|
-
- [@asterflow/
|
|
180
|
-
- [
|
|
181
|
-
- [@asterflow/response](https://www.npmjs.com/package/@asterflow/response) - Type-safe HTTP response system
|
|
182
|
-
- [@asterflow/plugin](https://www.npmjs.com/package/@asterflow/plugin) - A modular and typed plugin system
|
|
57
|
+
- [@asterflow/request](https://www.npmjs.com/package/@asterflow/request) - supplies the `create*Request` factories each adapter calls to build a typed `Request` from the runtime's native one
|
|
58
|
+
- [@asterflow/response](https://www.npmjs.com/package/@asterflow/response) - `AsterResponse` is what `onRequest` must return; adapters convert it to the runtime's native response and use it to build fallback/error responses
|
|
59
|
+
- Depended on by [asterflow](https://www.npmjs.com/package/asterflow) - the core framework picks a `driver` from `adapters`, sets its `onRequest`, and delegates `app.listen(...)` to `driver.listen(...)`
|
|
183
60
|
|
|
184
61
|
## 📄 License
|
|
185
62
|
|
|
186
|
-
|
|
63
|
+
This project is licensed under the [MIT License](../../LICENSE).
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -14,13 +14,13 @@ var T = (e, r) => {
|
|
|
14
14
|
};
|
|
15
15
|
var B = (e) => S(a({}, "__esModule", { value: !0 }), e);
|
|
16
16
|
// packages/adapter/src/index.ts
|
|
17
|
-
var
|
|
18
|
-
T(
|
|
17
|
+
var I = {};
|
|
18
|
+
T(I, {
|
|
19
19
|
Adapter: () => n,
|
|
20
20
|
Runtime: () => p,
|
|
21
|
-
adapters: () =>
|
|
21
|
+
adapters: () => k
|
|
22
22
|
});
|
|
23
|
-
module.exports = B(
|
|
23
|
+
module.exports = B(I);
|
|
24
24
|
// packages/adapter/src/controllers/Adapter.ts
|
|
25
25
|
var P = require("@asterflow/response");
|
|
26
26
|
// packages/adapter/src/types/adapter.ts
|
|
@@ -54,13 +54,13 @@ var l = new n({
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
// packages/adapter/src/adapters/express.ts
|
|
57
|
-
var c = require("@asterflow/request"),
|
|
58
|
-
var
|
|
57
|
+
var c = require("@asterflow/request"), R = require("@asterflow/response"), H = require("express");
|
|
58
|
+
var y = new n({
|
|
59
59
|
runtime: "express",
|
|
60
60
|
listen(e, ...r) {
|
|
61
61
|
return e.all("/{*path}", async (t, o) => {
|
|
62
62
|
if (!this.onRequest) {
|
|
63
|
-
let i = new
|
|
63
|
+
let i = new R.AsterResponse().notFound({
|
|
64
64
|
statusCode: 500,
|
|
65
65
|
error: "Internal Server Error",
|
|
66
66
|
message: "The onRequest() function must be defined before the listen() function."
|
|
@@ -116,7 +116,7 @@ function h(e) {
|
|
|
116
116
|
}));
|
|
117
117
|
}
|
|
118
118
|
// packages/adapter/src/adapters/node.ts
|
|
119
|
-
var
|
|
119
|
+
var w = new n({
|
|
120
120
|
runtime: "node",
|
|
121
121
|
listen(e, r) {
|
|
122
122
|
return new Promise((t, o) => {
|
|
@@ -128,8 +128,8 @@ var b = new n({
|
|
|
128
128
|
});
|
|
129
129
|
try {
|
|
130
130
|
return (await this.onRequest((0, v.createNodeRequest)(i))).toServerResponse(m);
|
|
131
|
-
} catch (
|
|
132
|
-
return h(
|
|
131
|
+
} catch (b) {
|
|
132
|
+
return h(b).toServerResponse(m);
|
|
133
133
|
}
|
|
134
134
|
});
|
|
135
135
|
s.on("error", (i) => {
|
|
@@ -141,7 +141,7 @@ var b = new n({
|
|
|
141
141
|
}
|
|
142
142
|
});
|
|
143
143
|
// packages/adapter/src/index.ts
|
|
144
|
-
var
|
|
144
|
+
var k = { bun: l, fastify: A, node: w, express: y };
|
|
145
145
|
0 && (module.exports = {
|
|
146
146
|
Adapter,
|
|
147
147
|
Runtime,
|
package/dist/mjs/index.js
CHANGED
|
@@ -12,7 +12,7 @@ var i = class {
|
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
// packages/adapter/src/adapters/bun.ts
|
|
15
|
-
import { createBunRequest as
|
|
15
|
+
import { createBunRequest as y } from "@asterflow/request";
|
|
16
16
|
import { AsterResponse as x } from "@asterflow/response";
|
|
17
17
|
var u = new i({
|
|
18
18
|
runtime: "bun",
|
|
@@ -20,7 +20,7 @@ var u = new i({
|
|
|
20
20
|
try {
|
|
21
21
|
Bun.serve({
|
|
22
22
|
...e,
|
|
23
|
-
fetch: async (t) => this.onRequest ? (await this.onRequest(
|
|
23
|
+
fetch: async (t) => this.onRequest ? (await this.onRequest(y(t))).toResponse() : new x().notFound({
|
|
24
24
|
statusCode: 500,
|
|
25
25
|
error: "Internal Server Error",
|
|
26
26
|
message: "The onRequest() function must be defined before the listen() function."
|
|
@@ -77,7 +77,7 @@ var f = new i({
|
|
|
77
77
|
// packages/adapter/src/adapters/node.ts
|
|
78
78
|
import { createNodeRequest as q } from "@asterflow/request";
|
|
79
79
|
import { AsterResponse as g } from "@asterflow/response";
|
|
80
|
-
import { createServer as
|
|
80
|
+
import { createServer as w } from "http";
|
|
81
81
|
// packages/adapter/src/utils/errorHandler.ts
|
|
82
82
|
import { AsterResponse as d } from "@asterflow/response";
|
|
83
83
|
function l(e) {
|
|
@@ -103,7 +103,7 @@ var c = new i({
|
|
|
103
103
|
runtime: "node",
|
|
104
104
|
listen(e, r) {
|
|
105
105
|
return new Promise((t, s) => {
|
|
106
|
-
let o =
|
|
106
|
+
let o = w(async (n, a) => {
|
|
107
107
|
if (!this.onRequest) return new g().notFound({
|
|
108
108
|
statusCode: 500,
|
|
109
109
|
error: "Internal Server Error",
|
|
@@ -111,8 +111,8 @@ var c = new i({
|
|
|
111
111
|
});
|
|
112
112
|
try {
|
|
113
113
|
return (await this.onRequest(q(n))).toServerResponse(a);
|
|
114
|
-
} catch (
|
|
115
|
-
return l(
|
|
114
|
+
} catch (R) {
|
|
115
|
+
return l(R).toServerResponse(a);
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
o.on("error", (n) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asterflow/adapter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Wires a runtime's native server (Bun.serve, Node's http, Express, Fastify) into AsterFlow, converting native requests to Request and sending back AsterResponse the same way regardless of runtime.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"asterflow",
|
|
7
|
+
"adapter",
|
|
8
|
+
"http",
|
|
9
|
+
"bun",
|
|
10
|
+
"node",
|
|
11
|
+
"express",
|
|
12
|
+
"fastify"
|
|
13
|
+
],
|
|
4
14
|
"main": "dist/cjs/index.cjs",
|
|
5
15
|
"module": "dist/mjs/index.js",
|
|
6
16
|
"types": "dist/types/index.d.ts",
|
|
@@ -27,16 +37,16 @@
|
|
|
27
37
|
"node": ">=20"
|
|
28
38
|
},
|
|
29
39
|
"devDependencies": {
|
|
30
|
-
"@types/express": "^5.0.
|
|
31
|
-
"@asterflow/router": "
|
|
40
|
+
"@types/express": "^5.0.6",
|
|
41
|
+
"@asterflow/router": "^2.0.1"
|
|
32
42
|
},
|
|
33
43
|
"peerDependencies": {
|
|
34
|
-
"fastify": "^5.
|
|
44
|
+
"fastify": "^5.12.1",
|
|
35
45
|
"express": "^5.1.0",
|
|
36
46
|
"typescript": "^5.8.3"
|
|
37
47
|
},
|
|
38
48
|
"dependencies": {
|
|
39
|
-
"@asterflow/response": "
|
|
40
|
-
"@asterflow/request": "
|
|
49
|
+
"@asterflow/response": "^2.0.1",
|
|
50
|
+
"@asterflow/request": "^2.0.1"
|
|
41
51
|
}
|
|
42
52
|
}
|