@arikajs/dispatcher 0.1.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/LICENSE +21 -0
- package/README.md +224 -0
- package/dist/Contracts/Container.d.ts +4 -0
- package/dist/Contracts/Container.d.ts.map +1 -0
- package/dist/Contracts/Container.js +3 -0
- package/dist/Contracts/Container.js.map +1 -0
- package/dist/Contracts/Http.d.ts +10 -0
- package/dist/Contracts/Http.d.ts.map +1 -0
- package/dist/Contracts/Http.js +3 -0
- package/dist/Contracts/Http.js.map +1 -0
- package/dist/Contracts/Router.d.ts +9 -0
- package/dist/Contracts/Router.d.ts.map +1 -0
- package/dist/Contracts/Router.js +3 -0
- package/dist/Contracts/Router.js.map +1 -0
- package/dist/ControllerResolver.d.ts +12 -0
- package/dist/ControllerResolver.d.ts.map +1 -0
- package/dist/ControllerResolver.js +24 -0
- package/dist/ControllerResolver.js.map +1 -0
- package/dist/Dispatcher.d.ts +37 -0
- package/dist/Dispatcher.d.ts.map +1 -0
- package/dist/Dispatcher.js +107 -0
- package/dist/Dispatcher.js.map +1 -0
- package/dist/MethodInvoker.d.ts +11 -0
- package/dist/MethodInvoker.d.ts.map +1 -0
- package/dist/MethodInvoker.js +17 -0
- package/dist/MethodInvoker.js.map +1 -0
- package/dist/ResponseResolver.d.ts +8 -0
- package/dist/ResponseResolver.d.ts.map +1 -0
- package/dist/ResponseResolver.js +29 -0
- package/dist/ResponseResolver.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ArikaJs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
## Arika Dispatcher
|
|
2
|
+
|
|
3
|
+
`@arikajs/dispatcher` is the **execution engine** of the ArikaJS ecosystem.
|
|
4
|
+
|
|
5
|
+
Before the response is sent back to the client, this package handles the **journey from route to result**:
|
|
6
|
+
|
|
7
|
+
- Route handler resolution (Closures or Controllers)
|
|
8
|
+
- Dependency Injection for controllers
|
|
9
|
+
- Method invocation with parameter injection
|
|
10
|
+
- Middleware pipeline execution
|
|
11
|
+
- Response normalization
|
|
12
|
+
|
|
13
|
+
If the following works cleanly, the dispatcher is considered correct:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const dispatcher = new Dispatcher(container);
|
|
17
|
+
const response = await dispatcher.dispatch(matchedRoute, request, responseInstance);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Arika Dispatcher is to ArikaJS what `illuminate/routing`’s dispatcher is to Laravel: it takes a route and makes things happen.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### Status
|
|
25
|
+
|
|
26
|
+
- **Stage**: Experimental / v0.x
|
|
27
|
+
- **Scope (v0.x)**:
|
|
28
|
+
- Controller & Closure resolution
|
|
29
|
+
- Method parameter injection (Request + Route Params)
|
|
30
|
+
- Basic middleware pipeline
|
|
31
|
+
- Response normalization (String, Object, Response)
|
|
32
|
+
- **Out of scope (for this package)**:
|
|
33
|
+
- Route matching (see `@arikajs/router`)
|
|
34
|
+
- Request parsing (see `@arikajs/http`)
|
|
35
|
+
- Template rendering
|
|
36
|
+
|
|
37
|
+
The goal of this package is to be the **reliable executor** of application logic.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- **Handler Resolution**
|
|
44
|
+
- Support for basic closures: `(req) => 'Hello'`
|
|
45
|
+
- Support for class-based controllers: `[UserController, 'show']`
|
|
46
|
+
- Automatic instantiation of controllers via Service Container
|
|
47
|
+
|
|
48
|
+
- **Method Invocation**
|
|
49
|
+
- Resolves method dependencies
|
|
50
|
+
- Injects `Request` object automatically
|
|
51
|
+
- Maps route parameters (e.g., `{id}`) to method arguments
|
|
52
|
+
|
|
53
|
+
- **Middleware Pipeline**
|
|
54
|
+
- Executes route-specific middleware
|
|
55
|
+
- Onion-style execution flow (nested `next()` calls)
|
|
56
|
+
- Asynchronous middleware support
|
|
57
|
+
- Container-based middleware resolution
|
|
58
|
+
|
|
59
|
+
- **Response Normalization**
|
|
60
|
+
- Automatically converts return values to HTTP responses
|
|
61
|
+
- Objects/Arrays → JSON response
|
|
62
|
+
- Strings → Plain text response
|
|
63
|
+
- `null`/`undefined` → 204 No Content
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install @arikajs/dispatcher
|
|
71
|
+
# or
|
|
72
|
+
yarn add @arikajs/dispatcher
|
|
73
|
+
# or
|
|
74
|
+
pnpm add @arikajs/dispatcher
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This package is written in TypeScript and ships with type definitions.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
### 1. Simple Dispatching
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { Dispatcher } from '@arikajs/dispatcher';
|
|
87
|
+
|
|
88
|
+
const dispatcher = new Dispatcher();
|
|
89
|
+
const response = await dispatcher.dispatch(matchedRoute, request, response);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Using Controllers with DI
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { Dispatcher } from '@arikajs/dispatcher';
|
|
96
|
+
import { Container } from '@arikajs/foundation';
|
|
97
|
+
|
|
98
|
+
const container = new Container();
|
|
99
|
+
const dispatcher = new Dispatcher(container);
|
|
100
|
+
|
|
101
|
+
// Dispatch to [UserController, 'index']
|
|
102
|
+
const response = await dispatcher.dispatch(matchedRoute, request, response);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Dispatcher
|
|
108
|
+
|
|
109
|
+
The `Dispatcher` class is the central coordinator that manages the lifecycle of a request dispatch.
|
|
110
|
+
|
|
111
|
+
Core responsibilities:
|
|
112
|
+
|
|
113
|
+
- Resolves the handler (Closure or Controller)
|
|
114
|
+
- Manages the **middleware pipeline**
|
|
115
|
+
- Coordinates the **invocation** of the handler
|
|
116
|
+
- Ensures the return value is **normalized** into a Response
|
|
117
|
+
|
|
118
|
+
Minimal API:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
class Dispatcher {
|
|
122
|
+
constructor(container?: Container);
|
|
123
|
+
|
|
124
|
+
setContainer(container: Container): this;
|
|
125
|
+
dispatch(matchedRoute: MatchedRoute, request: Request, response: Response): Promise<Response>;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Typical usage:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { Dispatcher } from '@arikajs/dispatcher';
|
|
133
|
+
|
|
134
|
+
const dispatcher = new Dispatcher(app.container);
|
|
135
|
+
const response = await dispatcher.dispatch(matched, request, response);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Middleware Pipeline
|
|
141
|
+
|
|
142
|
+
The `MiddlewarePipeline` executes middleware in an "onion" pattern, where each layer can perform logic before and after the next layer.
|
|
143
|
+
|
|
144
|
+
Minimal API:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
pipeline.use(middleware);
|
|
148
|
+
pipeline.handle(request, destination);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Usage
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const pipeline = new MiddlewarePipeline(container);
|
|
155
|
+
|
|
156
|
+
pipeline.use(async (req, next) => {
|
|
157
|
+
const res = await next(req);
|
|
158
|
+
res.header('X-Processed-By', 'Arika');
|
|
159
|
+
return res;
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Response Resolver
|
|
166
|
+
|
|
167
|
+
The `ResponseResolver` ensures that your controller methods can stay clean by returning plain data.
|
|
168
|
+
|
|
169
|
+
Conversion Rules:
|
|
170
|
+
|
|
171
|
+
- **Objects**: Automatically converted to JSON via `response.json()`
|
|
172
|
+
- **Strings/Buffers**: Sent as the body via `response.send()`
|
|
173
|
+
- **null/undefined**: Sets status 204 (No Content)
|
|
174
|
+
- **Response**: Returned as-is
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Project Structure (recommended)
|
|
179
|
+
|
|
180
|
+
Inside the `arika-dispatcher` repository:
|
|
181
|
+
|
|
182
|
+
- `src/`
|
|
183
|
+
- `Dispatcher.ts` – Main coordinator
|
|
184
|
+
- `ControllerResolver.ts` – DI-aware handler resolution
|
|
185
|
+
- `MethodInvoker.ts` – Dynamic method execution
|
|
186
|
+
- `ResponseResolver.ts` – Logic for normalizing return values
|
|
187
|
+
- `MiddlewarePipeline.ts` – The execution stack for middleware
|
|
188
|
+
- `index.ts` – Public exports
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Versioning & Stability
|
|
193
|
+
|
|
194
|
+
- While in **v0.x**, the API may change between minor versions.
|
|
195
|
+
- Once the API stabilizes, `@arikajs/dispatcher` will move to **v1.0** and follow **semver** strictly.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Contributing
|
|
200
|
+
|
|
201
|
+
Contributions are welcome, especially around:
|
|
202
|
+
|
|
203
|
+
- Advanced dependency injection in controller methods
|
|
204
|
+
- Performance optimizations for middleware execution
|
|
205
|
+
- Enhanced error handling hooks
|
|
206
|
+
- Support for attribute-based routing
|
|
207
|
+
|
|
208
|
+
Before submitting a PR:
|
|
209
|
+
|
|
210
|
+
- Run the test suite
|
|
211
|
+
- Add tests for any new behavior
|
|
212
|
+
- Keep the public API focused and well-documented
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
`@arikajs/dispatcher` is open-sourced software licensed under the **MIT license**.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Philosophy
|
|
223
|
+
|
|
224
|
+
> “Routing decides the path. Dispatcher executes the journey.”
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Container.d.ts","sourceRoot":"","sources":["../../src/Contracts/Container.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,SAAS;IACtB,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC;CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Container.js","sourceRoot":"","sources":["../../src/Contracts/Container.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../src/Contracts/Http.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,OAAO;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Http.js","sourceRoot":"","sources":["../../src/Contracts/Http.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/Contracts/Router.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE;QACH,OAAO,EAAE,GAAG,CAAC;QACb,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.js","sourceRoot":"","sources":["../../src/Contracts/Router.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class ControllerResolver {
|
|
2
|
+
private container;
|
|
3
|
+
constructor(container: any);
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the controller instance and method name.
|
|
6
|
+
*/
|
|
7
|
+
resolve(handler: any[]): {
|
|
8
|
+
controller: any;
|
|
9
|
+
method: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ControllerResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ControllerResolver.d.ts","sourceRoot":"","sources":["../src/ControllerResolver.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;IACf,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,GAAG;IAElC;;OAEG;IACI,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG;QAAE,UAAU,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;CAiBtE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ControllerResolver = void 0;
|
|
4
|
+
class ControllerResolver {
|
|
5
|
+
constructor(container) {
|
|
6
|
+
this.container = container;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the controller instance and method name.
|
|
10
|
+
*/
|
|
11
|
+
resolve(handler) {
|
|
12
|
+
const [controllerClass, method] = handler;
|
|
13
|
+
if (!this.container) {
|
|
14
|
+
throw new Error('Container required for controller resolution.');
|
|
15
|
+
}
|
|
16
|
+
const controller = this.container.make(controllerClass);
|
|
17
|
+
if (typeof controller[method] !== 'function') {
|
|
18
|
+
throw new Error(`Controller method "${method}" not found on ${controllerClass.name || controllerClass}.`);
|
|
19
|
+
}
|
|
20
|
+
return { controller, method };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.ControllerResolver = ControllerResolver;
|
|
24
|
+
//# sourceMappingURL=ControllerResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ControllerResolver.js","sourceRoot":"","sources":["../src/ControllerResolver.ts"],"names":[],"mappings":";;;AAAA,MAAa,kBAAkB;IAC3B,YAAoB,SAAc;QAAd,cAAS,GAAT,SAAS,CAAK;IAAI,CAAC;IAEvC;;OAEG;IACI,OAAO,CAAC,OAAc;QACzB,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;QAE1C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAQ,CAAC;QAE/D,IAAI,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CACX,sBAAsB,MAAM,kBAAkB,eAAe,CAAC,IAAI,IAAI,eAAe,GAAG,CAC3F,CAAC;QACN,CAAC;QAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC;CACJ;AAvBD,gDAuBC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Request, Response } from './Contracts/Http';
|
|
2
|
+
import { MatchedRoute } from './Contracts/Router';
|
|
3
|
+
export declare class Dispatcher {
|
|
4
|
+
private container?;
|
|
5
|
+
private controllerResolver?;
|
|
6
|
+
private invoker;
|
|
7
|
+
private responseResolver;
|
|
8
|
+
private middlewareGroups;
|
|
9
|
+
private routeMiddleware;
|
|
10
|
+
private parameterBinders;
|
|
11
|
+
constructor(container?: any | undefined);
|
|
12
|
+
/**
|
|
13
|
+
* Set the container for resolving controllers.
|
|
14
|
+
*/
|
|
15
|
+
setContainer(container: any): this;
|
|
16
|
+
/**
|
|
17
|
+
* Set the middleware groups mapping.
|
|
18
|
+
*/
|
|
19
|
+
setMiddlewareGroups(groups: Record<string, any[]>): this;
|
|
20
|
+
/**
|
|
21
|
+
* Set the route middleware mapping.
|
|
22
|
+
*/
|
|
23
|
+
setRouteMiddleware(middleware: Record<string, any>): this;
|
|
24
|
+
/**
|
|
25
|
+
* Register a route parameter binder.
|
|
26
|
+
*/
|
|
27
|
+
bind(key: string, resolver: any): this;
|
|
28
|
+
/**
|
|
29
|
+
* Dispatch the matched route to its handler.
|
|
30
|
+
*/
|
|
31
|
+
dispatch(matchedRoute: MatchedRoute, request: Request, response: Response): Promise<Response>;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve route parameters using registered binders.
|
|
34
|
+
*/
|
|
35
|
+
private resolveParameters;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=Dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dispatcher.d.ts","sourceRoot":"","sources":["../src/Dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,qBAAa,UAAU;IAQP,OAAO,CAAC,SAAS,CAAC;IAP9B,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,gBAAgB,CAAwD;gBAE5D,SAAS,CAAC,EAAE,GAAG,YAAA;IAQnC;;OAEG;IACI,YAAY,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAMzC;;OAEG;IACI,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI;IAK/D;;OAEG;IACI,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAKhE;;OAEG;IACI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI;IAS7C;;OAEG;IACU,QAAQ,CACjB,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,GACnB,OAAO,CAAC,QAAQ,CAAC;IAyCpB;;OAEG;YACW,iBAAiB;CAYlC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Dispatcher = void 0;
|
|
4
|
+
const ControllerResolver_1 = require("./ControllerResolver");
|
|
5
|
+
const MethodInvoker_1 = require("./MethodInvoker");
|
|
6
|
+
const ResponseResolver_1 = require("./ResponseResolver");
|
|
7
|
+
const middleware_1 = require("@arikajs/middleware");
|
|
8
|
+
class Dispatcher {
|
|
9
|
+
constructor(container) {
|
|
10
|
+
this.container = container;
|
|
11
|
+
this.middlewareGroups = {};
|
|
12
|
+
this.routeMiddleware = {};
|
|
13
|
+
this.parameterBinders = new Map();
|
|
14
|
+
this.invoker = new MethodInvoker_1.MethodInvoker();
|
|
15
|
+
this.responseResolver = new ResponseResolver_1.ResponseResolver();
|
|
16
|
+
if (container) {
|
|
17
|
+
this.controllerResolver = new ControllerResolver_1.ControllerResolver(container);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Set the container for resolving controllers.
|
|
22
|
+
*/
|
|
23
|
+
setContainer(container) {
|
|
24
|
+
this.container = container;
|
|
25
|
+
this.controllerResolver = new ControllerResolver_1.ControllerResolver(container);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Set the middleware groups mapping.
|
|
30
|
+
*/
|
|
31
|
+
setMiddlewareGroups(groups) {
|
|
32
|
+
this.middlewareGroups = groups;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Set the route middleware mapping.
|
|
37
|
+
*/
|
|
38
|
+
setRouteMiddleware(middleware) {
|
|
39
|
+
this.routeMiddleware = middleware;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register a route parameter binder.
|
|
44
|
+
*/
|
|
45
|
+
bind(key, resolver) {
|
|
46
|
+
if (resolver && typeof resolver.findOrFail === 'function') {
|
|
47
|
+
this.parameterBinders.set(key, (value) => resolver.findOrFail(value));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.parameterBinders.set(key, resolver);
|
|
51
|
+
}
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Dispatch the matched route to its handler.
|
|
56
|
+
*/
|
|
57
|
+
async dispatch(matchedRoute, request, response) {
|
|
58
|
+
const { route, params } = matchedRoute;
|
|
59
|
+
const handler = route.handler;
|
|
60
|
+
// 0. Resolve Route Parameters (Model Binding)
|
|
61
|
+
const resolvedParams = await this.resolveParameters(params);
|
|
62
|
+
// 1. Resolve Handler
|
|
63
|
+
let resolvedHandler;
|
|
64
|
+
if (Array.isArray(handler)) {
|
|
65
|
+
if (!this.controllerResolver) {
|
|
66
|
+
throw new Error('Container required for controller resolution.');
|
|
67
|
+
}
|
|
68
|
+
resolvedHandler = this.controllerResolver.resolve(handler);
|
|
69
|
+
}
|
|
70
|
+
else if (typeof handler === 'function') {
|
|
71
|
+
resolvedHandler = handler;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw new Error('Invalid route handler.');
|
|
75
|
+
}
|
|
76
|
+
// 2. Prepare Middleware Pipeline
|
|
77
|
+
const pipeline = new middleware_1.Pipeline(this.container);
|
|
78
|
+
pipeline.setMiddlewareGroups(this.middlewareGroups);
|
|
79
|
+
pipeline.setAliases(this.routeMiddleware);
|
|
80
|
+
// Add route-level middleware
|
|
81
|
+
if (route.middleware && route.middleware.length > 0) {
|
|
82
|
+
pipeline.pipe(route.middleware);
|
|
83
|
+
}
|
|
84
|
+
// 3. Execute Pipeline
|
|
85
|
+
return await pipeline.handle(request, async (req) => {
|
|
86
|
+
// 4. Invoke Handler
|
|
87
|
+
const result = await this.invoker.invoke(resolvedHandler, req, resolvedParams);
|
|
88
|
+
// 5. Normalize Response
|
|
89
|
+
return this.responseResolver.resolve(result, response);
|
|
90
|
+
}, response);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve route parameters using registered binders.
|
|
94
|
+
*/
|
|
95
|
+
async resolveParameters(params) {
|
|
96
|
+
const resolved = { ...params };
|
|
97
|
+
for (const [key, value] of Object.entries(params)) {
|
|
98
|
+
if (this.parameterBinders.has(key)) {
|
|
99
|
+
const resolver = this.parameterBinders.get(key);
|
|
100
|
+
resolved[key] = await resolver(value);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return resolved;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.Dispatcher = Dispatcher;
|
|
107
|
+
//# sourceMappingURL=Dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dispatcher.js","sourceRoot":"","sources":["../src/Dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Request } from './Contracts/Http';
|
|
2
|
+
export declare class MethodInvoker {
|
|
3
|
+
/**
|
|
4
|
+
* Invoke the handler (closure or controller method) with injected parameters.
|
|
5
|
+
*/
|
|
6
|
+
invoke(handler: Function | {
|
|
7
|
+
controller: any;
|
|
8
|
+
method: string;
|
|
9
|
+
}, request: Request, params: Record<string, any>): Promise<any>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=MethodInvoker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MethodInvoker.d.ts","sourceRoot":"","sources":["../src/MethodInvoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,qBAAa,aAAa;IACtB;;OAEG;IACU,MAAM,CACf,OAAO,EAAE,QAAQ,GAAG;QAAE,UAAU,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EACvD,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC5B,OAAO,CAAC,GAAG,CAAC;CAQlB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MethodInvoker = void 0;
|
|
4
|
+
class MethodInvoker {
|
|
5
|
+
/**
|
|
6
|
+
* Invoke the handler (closure or controller method) with injected parameters.
|
|
7
|
+
*/
|
|
8
|
+
async invoke(handler, request, params) {
|
|
9
|
+
if (typeof handler === 'function') {
|
|
10
|
+
return await handler(request, ...Object.values(params));
|
|
11
|
+
}
|
|
12
|
+
const { controller, method } = handler;
|
|
13
|
+
return await controller[method](request, ...Object.values(params));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.MethodInvoker = MethodInvoker;
|
|
17
|
+
//# sourceMappingURL=MethodInvoker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MethodInvoker.js","sourceRoot":"","sources":["../src/MethodInvoker.ts"],"names":[],"mappings":";;;AAEA,MAAa,aAAa;IACtB;;OAEG;IACI,KAAK,CAAC,MAAM,CACf,OAAuD,EACvD,OAAgB,EAChB,MAA2B;QAE3B,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAChC,OAAO,MAAM,OAAO,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QACvC,OAAO,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACvE,CAAC;CACJ;AAhBD,sCAgBC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Response } from './Contracts/Http';
|
|
2
|
+
export declare class ResponseResolver {
|
|
3
|
+
/**
|
|
4
|
+
* Resolve and normalize the handler return value into a Response object.
|
|
5
|
+
*/
|
|
6
|
+
resolve(value: any, response: Response): Response;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=ResponseResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseResolver.d.ts","sourceRoot":"","sources":["../src/ResponseResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,qBAAa,gBAAgB;IACzB;;OAEG;IACI,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ;CAuB3D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResponseResolver = void 0;
|
|
4
|
+
class ResponseResolver {
|
|
5
|
+
/**
|
|
6
|
+
* Resolve and normalize the handler return value into a Response object.
|
|
7
|
+
*/
|
|
8
|
+
resolve(value, response) {
|
|
9
|
+
// If it's already a Response object (basic duck typing check for framework response)
|
|
10
|
+
if (value && typeof value.send === 'function' && typeof value.status === 'function') {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
if (typeof value === 'object' && value !== null) {
|
|
14
|
+
return response.json(value);
|
|
15
|
+
}
|
|
16
|
+
// If it's a string, return as text or buffer
|
|
17
|
+
if (typeof value === 'string' || Buffer.isBuffer(value)) {
|
|
18
|
+
return response.send(value);
|
|
19
|
+
}
|
|
20
|
+
// Handle null or undefined (empty response)
|
|
21
|
+
if (value === null || value === undefined) {
|
|
22
|
+
return response.status(204).send('');
|
|
23
|
+
}
|
|
24
|
+
// Default to string conversion
|
|
25
|
+
return response.send(String(value));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.ResponseResolver = ResponseResolver;
|
|
29
|
+
//# sourceMappingURL=ResponseResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseResolver.js","sourceRoot":"","sources":["../src/ResponseResolver.ts"],"names":[],"mappings":";;;AAEA,MAAa,gBAAgB;IACzB;;OAEG;IACI,OAAO,CAAC,KAAU,EAAE,QAAkB;QACzC,qFAAqF;QACrF,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClF,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC9C,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,6CAA6C;QAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,4CAA4C;QAC5C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,+BAA+B;QAC/B,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;CACJ;AA3BD,4CA2BC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Dispatcher"), exports);
|
|
18
|
+
__exportStar(require("./ControllerResolver"), exports);
|
|
19
|
+
__exportStar(require("./MethodInvoker"), exports);
|
|
20
|
+
__exportStar(require("./ResponseResolver"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,uDAAqC;AACrC,kDAAgC;AAChC,qDAAmC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arikajs/dispatcher",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Request dispatching and handler execution layer of the ArikaJS framework.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.json",
|
|
10
|
+
"clean": "rm -rf dist",
|
|
11
|
+
"prepare": "echo skip",
|
|
12
|
+
"test": "npx tsx tests/Dispatcher.test.ts",
|
|
13
|
+
"test:watch": "npx tsx --watch tests/Dispatcher.test.ts"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"arika",
|
|
20
|
+
"arika-js",
|
|
21
|
+
"framework",
|
|
22
|
+
"dispatcher",
|
|
23
|
+
"controller",
|
|
24
|
+
"middleware"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.0.0"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/arikajs/dispatcher.git"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/arikajs/dispatcher/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/arikajs/dispatcher#readme",
|
|
37
|
+
"dependencies": {},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^20.11.24",
|
|
40
|
+
"typescript": "^5.3.3"
|
|
41
|
+
},
|
|
42
|
+
"author": "Prakash Tank"
|
|
43
|
+
}
|