@wooksjs/express-adapter 0.4.10 → 0.7.0

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 CHANGED
@@ -1,6 +1,4 @@
1
- # Express Adapter (Wooks Composables)
2
-
3
- **!!! This is work-in-progress library, breaking changes are expected !!!**
1
+ # @wooksjs/express-adapter
4
2
 
5
3
  <p align="center">
6
4
  <img src="./docs/wooksjs-express.png" height="156px"><br>
@@ -9,76 +7,167 @@
9
7
  </a>
10
8
  </p>
11
9
 
12
- Want to use [@wooksjs/event-http](https://www.npmjs.com/package/@wooksjs/event-http) but your project is coupled with express? This is not a problem with this Express Adapter for [wooks](https://www.npmjs.com/package/wooks)
10
+ Use [Wooks](https://wooks.moost.org) composables with [Express](https://expressjs.com). This adapter lets you register Wooks-style route handlers on top of an existing Express app unmatched requests automatically fall through to Express middleware.
13
11
 
14
12
  ## Install
15
13
 
16
- `npm install @wooksjs/express-adapter @wooksjs/event-http`
17
-
18
- ## Usage
14
+ ```bash
15
+ npm install @wooksjs/express-adapter @wooksjs/event-http wooks express
16
+ ```
19
17
 
20
- There are two options to use express with wooks
18
+ ## Quick Start
21
19
 
22
- ### 1. Adapter for express API:
23
- This one will modify express `get`, `post`, ..., methods. Take this one if you want to keep using express app API.
24
20
  ```ts
25
21
  import express from 'express'
26
- import { applyExpressAdapter } from '@wooksjs/express-adapter'
27
- import { useBody } from '@wooksjs/http-body'
28
- import { HttpError } from '@wooksjs/event-http'
29
- import { useRouteParams } from '@wooksjs/event-core'
22
+ import { WooksExpress } from '@wooksjs/express-adapter'
23
+ import { useRouteParams, useRequest, HttpError } from '@wooksjs/event-http'
30
24
 
31
25
  const app = express()
26
+ const wooks = new WooksExpress(app)
32
27
 
33
- applyExpressAdapter(app)
34
-
35
- app.get('/test/:param', () => {
28
+ // Return values become the response body
29
+ wooks.get('/hello/:name', () => {
36
30
  const { get } = useRouteParams()
37
- return { message: 'it works', param: get('param') }
31
+ return { hello: get('name') }
38
32
  })
39
33
 
40
- app.post('/post', () => {
41
- const { parseBody } = useBody()
42
- return parseBody()
34
+ // Async handlers work out of the box
35
+ wooks.post('/upload', async () => {
36
+ const { rawBody } = useRequest()
37
+ const body = await rawBody()
38
+ return { received: body.length }
43
39
  })
44
40
 
45
- app.get('/error', () => {
46
- throw new HttpError(400, 'test error')
41
+ // Throw HttpError for error responses
42
+ wooks.get('/protected', () => {
43
+ throw new HttpError(403, 'Forbidden')
47
44
  })
48
45
 
49
- app.listen(3000, () => console.log('listening 3000'))
46
+ app.listen(3000, () => console.log('listening on 3000'))
50
47
  ```
51
48
 
52
- ### 2. Adapter for WooksHttp API:
53
- This one does not modify anything. It just applies express middleware and reroutes requests through wooks. Use this one if you want to use wooks app API (compatible with [@moostjs/event-http](https://www.npmjs.com/package/@moostjs/event-http))
49
+ ## How It Works
50
+
51
+ `WooksExpress` extends `WooksHttp` and registers itself as Express middleware. When a request comes in:
52
+
53
+ 1. Wooks checks if a matching route is registered
54
+ 2. If matched — the Wooks handler runs with full composable support
55
+ 3. If not matched — the request falls through to the next Express middleware
56
+
57
+ This means you can **mix Wooks routes with regular Express routes and middleware**:
54
58
 
55
59
  ```ts
56
60
  import express from 'express'
57
61
  import { WooksExpress } from '@wooksjs/express-adapter'
58
- import { useBody } from '@wooksjs/http-body'
59
- import { HttpError } from '@wooksjs/event-http'
60
- import { useRouteParams } from '@wooksjs/event-core'
62
+ import cors from 'cors'
61
63
 
62
- const expressApp = express()
64
+ const app = express()
63
65
 
64
- const wooksApp = new WooksExpress(expressApp, { raise404: true })
66
+ // Express middleware works as usual
67
+ app.use(cors())
68
+ app.use(express.json())
65
69
 
66
- wooksApp.get('/test/:param', () => {
67
- const { get } = useRouteParams()
68
- return { message: 'it works', param: get('param') }
70
+ // Wooks handles these routes
71
+ const wooks = new WooksExpress(app)
72
+ wooks.get('/api/users', () => {
73
+ return [{ id: 1, name: 'Alice' }]
69
74
  })
70
75
 
71
- wooksApp.post('/post', () => {
72
- const { parseBody } = useBody()
73
- return parseBody()
76
+ // Express handles this route
77
+ app.get('/legacy', (req, res) => {
78
+ res.send('handled by express')
74
79
  })
75
80
 
76
- wooksApp.get('/error', () => {
77
- throw new HttpError(400, 'test error')
81
+ app.listen(3000)
82
+ ```
83
+
84
+ ## API
85
+
86
+ ### `new WooksExpress(expressApp, options?)`
87
+
88
+ Creates a new adapter instance and registers Wooks middleware on the Express app.
89
+
90
+ | Option | Type | Default | Description |
91
+ | ---------------- | -------------------------- | ------- | -------------------------------------------------------------------------------- |
92
+ | `raise404` | `boolean` | `false` | Return 404 from Wooks for unmatched routes instead of falling through to Express |
93
+ | `onNotFound` | `() => unknown` | — | Custom handler for unmatched routes |
94
+ | `logger` | `TConsoleBase` | — | Custom logger instance |
95
+ | `router` | `object` | — | Router options (`ignoreTrailingSlash`, `ignoreCase`, `cacheLimit`) |
96
+ | `requestLimits` | `object` | — | Default request body size limits |
97
+ | `defaultHeaders` | `Record<string, string>` | — | Headers added to every response |
98
+ | `responseClass` | `typeof WooksHttpResponse` | — | Custom response class |
99
+
100
+ ### Route Methods
101
+
102
+ ```ts
103
+ wooks.get(path, handler)
104
+ wooks.post(path, handler)
105
+ wooks.put(path, handler)
106
+ wooks.patch(path, handler)
107
+ wooks.delete(path, handler)
108
+ wooks.head(path, handler)
109
+ wooks.options(path, handler)
110
+ wooks.all(path, handler)
111
+ ```
112
+
113
+ Handlers take **no arguments** — use composables to access request data:
114
+
115
+ ```ts
116
+ wooks.get('/users/:id', () => {
117
+ const { get } = useRouteParams()
118
+ const { method, url, rawBody, getIp } = useRequest()
119
+ const headers = useHeaders()
120
+ const response = useResponse()
121
+
122
+ response.setHeader('x-custom', 'value')
123
+ return { id: get('id') }
78
124
  })
125
+ ```
126
+
127
+ ### `wooks.listen(port)`
128
+
129
+ Starts the Express server and returns a promise that resolves when listening.
130
+
131
+ ```ts
132
+ await wooks.listen(3000)
133
+ ```
134
+
135
+ ### `wooks.close()`
136
+
137
+ Stops the server.
138
+
139
+ ```ts
140
+ await wooks.close()
141
+ ```
142
+
143
+ ## Available Composables
144
+
145
+ These come from `@wooksjs/event-http` and work inside any Wooks handler:
146
+
147
+ | Composable | Purpose |
148
+ | -------------------- | ------------------------------------------- |
149
+ | `useRequest()` | Request method, URL, headers, body, IP |
150
+ | `useRouteParams()` | Route parameters (`:id`, etc.) |
151
+ | `useHeaders()` | Request headers |
152
+ | `useResponse()` | Set status, headers, cookies, cache control |
153
+ | `useCookies()` | Read request cookies |
154
+ | `useUrlParams()` | URL query parameters |
155
+ | `useAuthorization()` | Parse Authorization header |
156
+ | `useAccept()` | Check Accept header |
157
+ | `useLogger()` | Event-scoped logger |
158
+
159
+ See the [Wooks documentation](https://wooks.moost.org) for full composable reference.
160
+
161
+ ## Development
79
162
 
80
- wooksApp.listen(3000, () => console.log('listening 3000'))
163
+ ```bash
164
+ npm install # install dependencies
165
+ npm test # run tests (vitest)
166
+ npm run build # build for distribution
167
+ npm run lint # lint with oxlint
168
+ npm run fmt # format with oxfmt
81
169
  ```
82
170
 
171
+ ## License
83
172
 
84
- ⚠️ Check out official [wooks documentation](https://wooksjs.org/guide/http/express.html).
173
+ [MIT](./LICENSE)
package/dist/index.cjs CHANGED
@@ -1,101 +1,69 @@
1
1
  'use strict';
2
2
 
3
3
  const eventHttp = require('@wooksjs/event-http');
4
-
5
- const methods = [
6
- "get",
7
- "post",
8
- "delete",
9
- "put",
10
- "patch",
11
- "options",
12
- "head",
13
- "all"
14
- ];
15
- function applyExpressAdapter(app, eventOptions) {
16
- const responder = eventHttp.createWooksResponder();
17
- function useWooksDecorator(fn) {
18
- return async () => {
19
- const { restoreCtx, clearCtx } = eventHttp.useHttpContext();
20
- try {
21
- const result = await fn();
22
- restoreCtx();
23
- await responder.respond(result);
24
- } catch (e) {
25
- restoreCtx();
26
- await responder.respond(e);
27
- }
28
- clearCtx();
29
- };
30
- }
31
- app.use(wooksContext(eventOptions));
32
- for (const m of methods) {
33
- const defFn = app[m].bind(app);
34
- const newFn = ((...args) => {
35
- return defFn(...args.map((a) => typeof a === "function" ? useWooksDecorator(a) : a));
36
- }).bind(app);
37
- Object.defineProperty(app, m, { value: newFn });
38
- }
39
- }
40
- function wooksContext(eventOptions) {
41
- return (req, res, next) => {
42
- const { store } = eventHttp.createHttpContext({ req, res }, eventOptions || {});
43
- store("routeParams").value = new Proxy({}, {
44
- get(target, prop, receiver) {
45
- return req.params && req.params[prop];
46
- }
47
- });
48
- next();
49
- };
50
- }
4
+ const eventCore = require('@wooksjs/event-core');
51
5
 
52
6
  class WooksExpress extends eventHttp.WooksHttp {
7
+ expressApp;
8
+ expressOpts;
53
9
  constructor(expressApp, opts) {
54
10
  super(opts);
55
11
  this.expressApp = expressApp;
56
- this.opts = opts;
57
- expressApp.use(this.getServerCb());
12
+ this.expressOpts = opts ?? {};
13
+ this.expressApp.use(this.getExpressMiddleware());
58
14
  }
15
+ /**
16
+ * Start the Express server and return a promise that resolves when listening.
17
+ */
59
18
  listen(...args) {
60
- const server = this.server = this.expressApp.listen(...args);
19
+ const server = this.server = this.expressApp.listen(
20
+ ...args
21
+ );
61
22
  return new Promise((resolve, reject) => {
62
- server.once("listening", resolve);
23
+ server.once("listening", () => resolve());
63
24
  server.once("error", reject);
64
25
  });
65
26
  }
66
- getServerCb() {
67
- return async (req, res, next) => {
68
- const { restoreCtx, clearCtx } = eventHttp.createHttpContext(
69
- { req, res },
70
- this.mergeEventOptions(this.opts?.eventOptions)
71
- );
72
- const { handlers } = this.wooks.lookup(req.method, req.url);
73
- if (handlers || this.opts?.onNotFound) {
74
- try {
75
- await this.processHandlers(handlers || [this.opts?.onNotFound]);
76
- } catch (e) {
77
- console.error("Internal error, please report: ", e);
78
- if (e.stack) {
79
- console.warn(e.stack);
27
+ /**
28
+ * Returns Express middleware that routes requests through Wooks.
29
+ * Matched routes are handled by Wooks; unmatched requests call `next()`.
30
+ */
31
+ getExpressMiddleware() {
32
+ const ctxOptions = this.eventContextOptions;
33
+ const requestLimits = this.expressOpts.requestLimits;
34
+ const defaultHeaders = this.expressOpts.defaultHeaders;
35
+ const notFoundHandler = this.expressOpts.onNotFound;
36
+ const raise404 = this.expressOpts.raise404;
37
+ return (req, res, next) => {
38
+ const response = new this.ResponseClass(res, req, ctxOptions.logger, defaultHeaders);
39
+ const method = req.method || "";
40
+ const url = req.url || "";
41
+ eventHttp.createHttpContext(ctxOptions, { req, response, requestLimits }, () => {
42
+ const ctx = eventCore.current();
43
+ const handlers = this.wooks.lookupHandlers(method, url, ctx);
44
+ if (handlers || notFoundHandler) {
45
+ const result = this.processHandlers(
46
+ handlers || [notFoundHandler],
47
+ ctx,
48
+ response
49
+ );
50
+ if (result !== null && result !== void 0 && typeof result.then === "function") {
51
+ result.catch((error) => {
52
+ this.logger.error("Internal error, please report", error);
53
+ this.respond(error, response, ctx);
54
+ });
80
55
  }
81
- restoreCtx();
82
- this.respond(e);
83
- clearCtx();
56
+ return result;
84
57
  }
85
- } else {
86
- this.logger.debug(
87
- `404 Not found (${req.method})${req.url}`
88
- );
89
- if (this.opts?.raise404) {
90
- this.respond(new eventHttp.HttpError(404));
91
- clearCtx();
92
- } else if (next) {
93
- next();
58
+ if (raise404) {
59
+ const error = new eventHttp.HttpError(404);
60
+ this.respond(error, response, ctx);
61
+ return error;
94
62
  }
95
- }
63
+ next();
64
+ });
96
65
  };
97
66
  }
98
67
  }
99
68
 
100
69
  exports.WooksExpress = WooksExpress;
101
- exports.applyExpressAdapter = applyExpressAdapter;
@@ -0,0 +1,53 @@
1
+ import { TWooksHttpOptions, WooksHttp } from '@wooksjs/event-http';
2
+ import { Application, NextFunction } from 'express';
3
+ import { IncomingMessage, ServerResponse } from 'http';
4
+
5
+ interface TWooksExpressOptions extends TWooksHttpOptions {
6
+ /**
7
+ * When true, respond with 404 for unmatched Wooks routes
8
+ * instead of passing to the next Express middleware.
9
+ * @default false
10
+ */
11
+ raise404?: boolean;
12
+ }
13
+ /**
14
+ * Express adapter for Wooks.
15
+ *
16
+ * Uses Wooks routing and composables on top of an Express application.
17
+ * Registers itself as Express middleware — requests matching Wooks routes
18
+ * are handled by Wooks; unmatched requests fall through to Express.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import express from 'express'
23
+ * import { WooksExpress } from '@wooksjs/express-adapter'
24
+ * import { useRouteParams } from '@wooksjs/event-http'
25
+ *
26
+ * const app = express()
27
+ * const wooks = new WooksExpress(app)
28
+ *
29
+ * wooks.get('/hello/:name', () => {
30
+ * const { get } = useRouteParams()
31
+ * return { hello: get('name') }
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ */
37
+ declare class WooksExpress extends WooksHttp {
38
+ protected expressApp: Application;
39
+ protected expressOpts: TWooksExpressOptions;
40
+ constructor(expressApp: Application, opts?: TWooksExpressOptions);
41
+ /**
42
+ * Start the Express server and return a promise that resolves when listening.
43
+ */
44
+ listen(...args: unknown[]): Promise<void>;
45
+ /**
46
+ * Returns Express middleware that routes requests through Wooks.
47
+ * Matched routes are handled by Wooks; unmatched requests call `next()`.
48
+ */
49
+ getExpressMiddleware(): (req: IncomingMessage, res: ServerResponse, next: NextFunction) => void;
50
+ }
51
+
52
+ export { WooksExpress };
53
+ export type { TWooksExpressOptions };
@@ -0,0 +1,53 @@
1
+ import { TWooksHttpOptions, WooksHttp } from '@wooksjs/event-http';
2
+ import { Application, NextFunction } from 'express';
3
+ import { IncomingMessage, ServerResponse } from 'http';
4
+
5
+ interface TWooksExpressOptions extends TWooksHttpOptions {
6
+ /**
7
+ * When true, respond with 404 for unmatched Wooks routes
8
+ * instead of passing to the next Express middleware.
9
+ * @default false
10
+ */
11
+ raise404?: boolean;
12
+ }
13
+ /**
14
+ * Express adapter for Wooks.
15
+ *
16
+ * Uses Wooks routing and composables on top of an Express application.
17
+ * Registers itself as Express middleware — requests matching Wooks routes
18
+ * are handled by Wooks; unmatched requests fall through to Express.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import express from 'express'
23
+ * import { WooksExpress } from '@wooksjs/express-adapter'
24
+ * import { useRouteParams } from '@wooksjs/event-http'
25
+ *
26
+ * const app = express()
27
+ * const wooks = new WooksExpress(app)
28
+ *
29
+ * wooks.get('/hello/:name', () => {
30
+ * const { get } = useRouteParams()
31
+ * return { hello: get('name') }
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ */
37
+ declare class WooksExpress extends WooksHttp {
38
+ protected expressApp: Application;
39
+ protected expressOpts: TWooksExpressOptions;
40
+ constructor(expressApp: Application, opts?: TWooksExpressOptions);
41
+ /**
42
+ * Start the Express server and return a promise that resolves when listening.
43
+ */
44
+ listen(...args: unknown[]): Promise<void>;
45
+ /**
46
+ * Returns Express middleware that routes requests through Wooks.
47
+ * Matched routes are handled by Wooks; unmatched requests call `next()`.
48
+ */
49
+ getExpressMiddleware(): (req: IncomingMessage, res: ServerResponse, next: NextFunction) => void;
50
+ }
51
+
52
+ export { WooksExpress };
53
+ export type { TWooksExpressOptions };
package/dist/index.d.ts CHANGED
@@ -1,19 +1,53 @@
1
1
  import { TWooksHttpOptions, WooksHttp } from '@wooksjs/event-http';
2
- import Express$1, { Express } from 'express';
3
- import { Server, IncomingMessage, ServerResponse } from 'http';
4
-
5
- declare function applyExpressAdapter(app: Express, eventOptions?: TWooksHttpOptions['eventOptions']): void;
2
+ import { Application, NextFunction } from 'express';
3
+ import { IncomingMessage, ServerResponse } from 'http';
6
4
 
5
+ interface TWooksExpressOptions extends TWooksHttpOptions {
6
+ /**
7
+ * When true, respond with 404 for unmatched Wooks routes
8
+ * instead of passing to the next Express middleware.
9
+ * @default false
10
+ */
11
+ raise404?: boolean;
12
+ }
13
+ /**
14
+ * Express adapter for Wooks.
15
+ *
16
+ * Uses Wooks routing and composables on top of an Express application.
17
+ * Registers itself as Express middleware — requests matching Wooks routes
18
+ * are handled by Wooks; unmatched requests fall through to Express.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import express from 'express'
23
+ * import { WooksExpress } from '@wooksjs/express-adapter'
24
+ * import { useRouteParams } from '@wooksjs/event-http'
25
+ *
26
+ * const app = express()
27
+ * const wooks = new WooksExpress(app)
28
+ *
29
+ * wooks.get('/hello/:name', () => {
30
+ * const { get } = useRouteParams()
31
+ * return { hello: get('name') }
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ */
7
37
  declare class WooksExpress extends WooksHttp {
8
- protected expressApp: Express$1.Application;
9
- protected opts?: (TWooksHttpOptions & {
10
- raise404?: boolean | undefined;
11
- }) | undefined;
12
- constructor(expressApp: Express$1.Application, opts?: (TWooksHttpOptions & {
13
- raise404?: boolean | undefined;
14
- }) | undefined);
15
- listen(...args: Parameters<Server['listen']>): Promise<unknown>;
16
- getServerCb(): (req: IncomingMessage, res: ServerResponse, next?: Express$1.NextFunction) => Promise<void>;
38
+ protected expressApp: Application;
39
+ protected expressOpts: TWooksExpressOptions;
40
+ constructor(expressApp: Application, opts?: TWooksExpressOptions);
41
+ /**
42
+ * Start the Express server and return a promise that resolves when listening.
43
+ */
44
+ listen(...args: unknown[]): Promise<void>;
45
+ /**
46
+ * Returns Express middleware that routes requests through Wooks.
47
+ * Matched routes are handled by Wooks; unmatched requests call `next()`.
48
+ */
49
+ getExpressMiddleware(): (req: IncomingMessage, res: ServerResponse, next: NextFunction) => void;
17
50
  }
18
51
 
19
- export { WooksExpress, applyExpressAdapter };
52
+ export { WooksExpress };
53
+ export type { TWooksExpressOptions };
package/dist/index.mjs CHANGED
@@ -1,98 +1,67 @@
1
- import { createWooksResponder, createHttpContext, useHttpContext, WooksHttp, HttpError } from '@wooksjs/event-http';
2
-
3
- const methods = [
4
- "get",
5
- "post",
6
- "delete",
7
- "put",
8
- "patch",
9
- "options",
10
- "head",
11
- "all"
12
- ];
13
- function applyExpressAdapter(app, eventOptions) {
14
- const responder = createWooksResponder();
15
- function useWooksDecorator(fn) {
16
- return async () => {
17
- const { restoreCtx, clearCtx } = useHttpContext();
18
- try {
19
- const result = await fn();
20
- restoreCtx();
21
- await responder.respond(result);
22
- } catch (e) {
23
- restoreCtx();
24
- await responder.respond(e);
25
- }
26
- clearCtx();
27
- };
28
- }
29
- app.use(wooksContext(eventOptions));
30
- for (const m of methods) {
31
- const defFn = app[m].bind(app);
32
- const newFn = ((...args) => {
33
- return defFn(...args.map((a) => typeof a === "function" ? useWooksDecorator(a) : a));
34
- }).bind(app);
35
- Object.defineProperty(app, m, { value: newFn });
36
- }
37
- }
38
- function wooksContext(eventOptions) {
39
- return (req, res, next) => {
40
- const { store } = createHttpContext({ req, res }, eventOptions || {});
41
- store("routeParams").value = new Proxy({}, {
42
- get(target, prop, receiver) {
43
- return req.params && req.params[prop];
44
- }
45
- });
46
- next();
47
- };
48
- }
1
+ import { WooksHttp, createHttpContext, HttpError } from '@wooksjs/event-http';
2
+ import { current } from '@wooksjs/event-core';
49
3
 
50
4
  class WooksExpress extends WooksHttp {
5
+ expressApp;
6
+ expressOpts;
51
7
  constructor(expressApp, opts) {
52
8
  super(opts);
53
9
  this.expressApp = expressApp;
54
- this.opts = opts;
55
- expressApp.use(this.getServerCb());
10
+ this.expressOpts = opts ?? {};
11
+ this.expressApp.use(this.getExpressMiddleware());
56
12
  }
13
+ /**
14
+ * Start the Express server and return a promise that resolves when listening.
15
+ */
57
16
  listen(...args) {
58
- const server = this.server = this.expressApp.listen(...args);
17
+ const server = this.server = this.expressApp.listen(
18
+ ...args
19
+ );
59
20
  return new Promise((resolve, reject) => {
60
- server.once("listening", resolve);
21
+ server.once("listening", () => resolve());
61
22
  server.once("error", reject);
62
23
  });
63
24
  }
64
- getServerCb() {
65
- return async (req, res, next) => {
66
- const { restoreCtx, clearCtx } = createHttpContext(
67
- { req, res },
68
- this.mergeEventOptions(this.opts?.eventOptions)
69
- );
70
- const { handlers } = this.wooks.lookup(req.method, req.url);
71
- if (handlers || this.opts?.onNotFound) {
72
- try {
73
- await this.processHandlers(handlers || [this.opts?.onNotFound]);
74
- } catch (e) {
75
- console.error("Internal error, please report: ", e);
76
- if (e.stack) {
77
- console.warn(e.stack);
25
+ /**
26
+ * Returns Express middleware that routes requests through Wooks.
27
+ * Matched routes are handled by Wooks; unmatched requests call `next()`.
28
+ */
29
+ getExpressMiddleware() {
30
+ const ctxOptions = this.eventContextOptions;
31
+ const requestLimits = this.expressOpts.requestLimits;
32
+ const defaultHeaders = this.expressOpts.defaultHeaders;
33
+ const notFoundHandler = this.expressOpts.onNotFound;
34
+ const raise404 = this.expressOpts.raise404;
35
+ return (req, res, next) => {
36
+ const response = new this.ResponseClass(res, req, ctxOptions.logger, defaultHeaders);
37
+ const method = req.method || "";
38
+ const url = req.url || "";
39
+ createHttpContext(ctxOptions, { req, response, requestLimits }, () => {
40
+ const ctx = current();
41
+ const handlers = this.wooks.lookupHandlers(method, url, ctx);
42
+ if (handlers || notFoundHandler) {
43
+ const result = this.processHandlers(
44
+ handlers || [notFoundHandler],
45
+ ctx,
46
+ response
47
+ );
48
+ if (result !== null && result !== void 0 && typeof result.then === "function") {
49
+ result.catch((error) => {
50
+ this.logger.error("Internal error, please report", error);
51
+ this.respond(error, response, ctx);
52
+ });
78
53
  }
79
- restoreCtx();
80
- this.respond(e);
81
- clearCtx();
54
+ return result;
82
55
  }
83
- } else {
84
- this.logger.debug(
85
- `404 Not found (${req.method})${req.url}`
86
- );
87
- if (this.opts?.raise404) {
88
- this.respond(new HttpError(404));
89
- clearCtx();
90
- } else if (next) {
91
- next();
56
+ if (raise404) {
57
+ const error = new HttpError(404);
58
+ this.respond(error, response, ctx);
59
+ return error;
92
60
  }
93
- }
61
+ next();
62
+ });
94
63
  };
95
64
  }
96
65
  }
97
66
 
98
- export { WooksExpress, applyExpressAdapter };
67
+ export { WooksExpress };
package/package.json CHANGED
@@ -1,91 +1,70 @@
1
1
  {
2
2
  "name": "@wooksjs/express-adapter",
3
- "version": "0.4.10",
4
- "description": "Express Adapter for Wooks Composables",
5
- "main": "dist/index.cjs",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist"
3
+ "version": "0.7.0",
4
+ "description": "Express Adapter for Wooks — use Wooks composables with Express",
5
+ "keywords": [
6
+ "adapter",
7
+ "api",
8
+ "app",
9
+ "composables",
10
+ "express",
11
+ "framework",
12
+ "http",
13
+ "rest",
14
+ "restful",
15
+ "web",
16
+ "wooks"
10
17
  ],
11
- "scripts": {
12
- "build": "unbuild",
13
- "release": "node ./scripts/release",
14
- "test": "jest --runInBand",
15
- "test:cov": "jest --runInBand --coverage",
16
- "lint": "eslint --ext .ts src/**/**.ts",
17
- "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
18
- "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md"
18
+ "homepage": "https://github.com/wooksjs/express-adapter#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/wooksjs/express-adapter/issues"
19
21
  },
22
+ "license": "MIT",
23
+ "author": "Artem Maltsev",
20
24
  "repository": {
21
25
  "type": "git",
22
26
  "url": "git+https://github.com/wooksjs/express-adapter.git"
23
27
  },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "main": "dist/index.cjs",
32
+ "module": "dist/index.mjs",
33
+ "types": "dist/index.d.ts",
24
34
  "exports": {
25
35
  ".": {
26
- "require": "./dist/index.cjs",
36
+ "types": "./dist/index.d.ts",
27
37
  "import": "./dist/index.mjs",
28
- "types": "./dist/index.d.ts"
38
+ "require": "./dist/index.cjs"
29
39
  }
30
40
  },
31
- "keywords": [
32
- "http",
33
- "wooks",
34
- "composables",
35
- "express",
36
- "adapter",
37
- "web",
38
- "framework",
39
- "app",
40
- "api",
41
- "rest",
42
- "restful",
43
- "prostojs"
44
- ],
45
- "buildOptions": {
46
- "formats": [
47
- "esm-bundler",
48
- "cjs"
49
- ]
50
- },
51
- "gitHooks": {
52
- "commit-msg": "node scripts/verifyCommit.js"
53
- },
54
- "author": "Artem Maltsev",
55
- "license": "MIT",
56
- "bugs": {
57
- "url": "https://github.com/wooksjs/express-adapter/issues"
41
+ "devDependencies": {
42
+ "@types/express": "^5.0.0",
43
+ "@types/node": "^22.0.0",
44
+ "@wooksjs/event-core": "^0.7.4",
45
+ "@wooksjs/event-http": "^0.7.4",
46
+ "express": "^5.0.0",
47
+ "oxfmt": "^0.35.0",
48
+ "oxlint": "^1.50.0",
49
+ "typescript": "^5.7.0",
50
+ "unbuild": "^3.5.0",
51
+ "vitest": "^3.0.0",
52
+ "wooks": "^0.7.4"
58
53
  },
59
- "homepage": "https://github.com/wooksjs/express-adapter#readme",
60
54
  "peerDependencies": {
61
- "@wooksjs/event-http": "^0.4.8",
62
- "wooks": "^0.4.8",
63
- "express": "^4.0.0"
55
+ "@wooksjs/event-core": ">=0.7.0",
56
+ "@wooksjs/event-http": ">=0.7.0",
57
+ "express": ">=4.0.0",
58
+ "wooks": ">=0.7.0"
64
59
  },
65
- "devDependencies": {
66
- "@prostojs/dye": "^0.3.0",
67
- "@types/express": "^4.17.14",
68
- "@types/jest": "^29.2.0",
69
- "@types/node": "^18.11.0",
70
- "@typescript-eslint/eslint-plugin": "^5.42.0",
71
- "@typescript-eslint/parser": "^5.0.0",
72
- "@wooksjs/event-http": "^0.4.8",
73
- "@wooksjs/http-body": "^0.4.8",
74
- "conventional-changelog": "^3.1.24",
75
- "conventional-changelog-cli": "^2.1.1",
76
- "enquirer": "^2.3.6",
77
- "eslint": "^7.32.0",
78
- "eslint-config-prettier": "^8.3.0",
79
- "eslint-plugin-import": "^2.24.2",
80
- "execa": "^5.1.1",
81
- "express": "^4.18.2",
82
- "jest": "^29.2.2",
83
- "minimist": "^1.2.6",
84
- "semver": "^7.3.5",
85
- "ts-jest": "^29.0.3",
86
- "tslib": "^2.4.1",
87
- "typescript": "^4.8.4",
88
- "unbuild": "^0.9.4",
89
- "yorkie": "^2.0.0"
60
+ "scripts": {
61
+ "build": "unbuild",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest",
64
+ "test:cov": "vitest run --coverage",
65
+ "lint": "oxlint",
66
+ "lint:fix": "oxlint --fix",
67
+ "fmt": "oxfmt",
68
+ "fmt:check": "oxfmt --check"
90
69
  }
91
- }
70
+ }