Skip to content
This repository was archived by the owner on Mar 16, 2025. It is now read-only.

Commit 652e62d

Browse files
committed
Get rid of RequestCapabilities
`RequestCapability` is just enough.
1 parent 49f76d6 commit 652e62d

8 files changed

Lines changed: 178 additions & 232 deletions

src/core/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export * from './error.means';
22
export * from './request-body.means';
3-
export * from './request-capabilities';
43
export * from './request-capability';
54
export * from './request-context';
65
export * from './request-handler';

src/core/request-capabilities.ts

Lines changed: 0 additions & 129 deletions
This file was deleted.

src/core/request-capability.ts

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,76 @@
22
* @packageDocumentation
33
* @module @hatsy/hatsy/core
44
*/
5-
import { RequestCapabilities } from './request-capabilities';
6-
import { RequestContext } from './request-context';
75
import { RequestHandler } from './request-handler';
8-
import { RequestModification } from './request-modification';
96

107
/**
118
* Request processing capability.
129
*
1310
* Modifies request processing context in a certain way when delegates to handler.
1411
*
15-
* Request processing capabilities could be be {@link RequestCapabilities combined}.
12+
* Request processing capabilities could be {@link RequestCapability.combine combined}.
1613
*
1714
* @typeparam TInput A type of request processing means required in order to apply this capability.
1815
* @typeparam TExt A type of extension to request processing means this capability applies.
1916
*/
20-
export abstract class RequestCapability<TInput, TExt = object> implements RequestCapabilities<TInput, TExt> {
17+
export abstract class RequestCapability<TInput, TExt = object> {
2118

2219
/**
23-
* Builds request modification to apply by {@link for handler}.
20+
* Builds request capability by the given `provider`.
2421
*
25-
* @typeparam TMeans A type of request processing means to modify.
26-
* @param context Request processing context to modify.
22+
* @typeparam TInput A type of request processing means required by this provider.
23+
* @typeparam TExt A type of extension to request processing means this provider applies.
24+
* @param provider Request processing capability provider.
2725
*
28-
* @returns Request modifications to apply, or promise-like instance resolving to it.
26+
* @returns Request processing capability that call the given `provider` in order to apply.
2927
*/
30-
abstract modification<TMeans extends TInput>(
31-
context: RequestContext<TMeans>,
32-
): RequestModification<TMeans, TExt> | PromiseLike<RequestModification<TMeans, TExt>>;
28+
static of<TInput, TExt>(
29+
this: void,
30+
provider: RequestCapability.Provider<TInput, TExt>,
31+
): RequestCapability<TInput, TExt> {
32+
33+
const capability: RequestCapability<TInput, TExt> = {
34+
for: provider,
35+
and<TNext>(next: RequestCapability<TInput & TExt, TNext>): RequestCapability<TInput, TExt & TNext> {
36+
return RequestCapability.combine(capability, next);
37+
},
38+
};
39+
40+
return capability;
41+
}
42+
43+
/**
44+
* Combines two request processing capabilities.
45+
*
46+
* @typeparam TInput A type of request processing means expected by the `first` capability.
47+
* @typeparam TExt A type of request processing means extension applied by the `first` capability.
48+
* @typeparam TNext A type of request processing means extension applied by the `second` capability.
49+
* @param first First capability to combine.
50+
* @param second Second capability to combine. Receives requests modified by the `first` one.
51+
*
52+
* @return Combined request processing capability that applies modifications to request by the `first` capability,
53+
* and then - by the `second` one.
54+
*/
55+
static combine<TInput, TExt, TNext>(
56+
this: void,
57+
first: RequestCapability<TInput, TExt>,
58+
second: RequestCapability<TInput & TExt, TNext>,
59+
): RequestCapability<TInput, TExt & TNext> {
60+
61+
const chain: RequestCapability<TInput, TExt & TNext> = {
62+
63+
for<TMeans extends TInput>(delegate: RequestHandler<TMeans & TExt & TNext>): RequestHandler<TMeans> {
64+
return first.for(second.for(delegate));
65+
},
66+
67+
and<T>(next: RequestCapability<TInput & TExt & TNext, T>): RequestCapability<TInput, TExt & TNext & T> {
68+
return RequestCapability.combine<TInput, TExt & TNext, T>(chain, next);
69+
},
70+
71+
};
72+
73+
return chain;
74+
}
3375

3476
/**
3577
* Provides request processing capability to the given handler.
@@ -41,23 +83,46 @@ export abstract class RequestCapability<TInput, TExt = object> implements Reques
4183
*
4284
* @returns New request processing handler.
4385
*/
44-
for<TMeans extends TInput>(handler: RequestHandler<TMeans & TExt>): RequestHandler<TMeans> {
45-
return async context => context.next(handler, await this.modification(context));
46-
}
86+
abstract for<TMeans extends TInput>(handler: RequestHandler<TMeans & TExt>): RequestHandler<TMeans>;
4787

4888
/**
49-
* Combines this capability with the `next` capability set.
89+
* Combines this capability with the `next` one.
5090
*
51-
* @typeparam TNext A type of extension to request processing means applied by `next` capability set.
52-
* @param next Next capability set that receives requests modified by this capability.
91+
* @typeparam TNext A type of extension to request processing means applied by `next` capability.
92+
* @param next Next capability that receives requests modified by this capability.
5393
*
54-
* @return New request processing capability set that applies modifications to request by this capability,
55-
* and then - by the `next` capability set.
94+
* @return New request processing capability that applies modifications to request by this capability first,
95+
* and then - by the `next` one.
5696
*
57-
* @see RequestCapabilities.combine
97+
* @see RequestCapability.combine
5898
*/
59-
and<TNext>(next: RequestCapabilities<TInput & TExt, TNext>): RequestCapabilities<TInput, TExt & TNext> {
60-
return RequestCapabilities.combine<TInput, TExt, TNext>(this, next);
99+
and<TNext>(next: RequestCapability<TInput & TExt, TNext>): RequestCapability<TInput, TExt & TNext> {
100+
return RequestCapability.combine<TInput, TExt, TNext>(this, next);
61101
}
62102

63103
}
104+
105+
export namespace RequestCapability {
106+
107+
/**
108+
* Request processing capability provider signature.
109+
*
110+
* Builds a request processing handler that modifies request and delegates to another one.
111+
*
112+
* @typeparam TInput A type of request processing means required by this provider.
113+
* @typeparam TExt A type of extension to request processing means this provider applies.
114+
*/
115+
export type Provider<TInput, TExt = object> =
116+
/**
117+
* @typeparam TMeans A type of request processing means expected by constructed handler.
118+
*
119+
* @param handler Request processing handler that will receive modified request context.
120+
*
121+
* @returns New request processing handler.
122+
*/
123+
<TMeans extends TInput>(
124+
this: void,
125+
handler: RequestHandler<TMeans & TExt>,
126+
) => RequestHandler<TMeans>;
127+
128+
}

src/http/middleware.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @module @hatsy/hatsy
44
*/
55
import { IncomingMessage, ServerResponse } from 'http';
6-
import { RequestCapabilities, RequestContext, RequestHandler } from '../core';
6+
import { RequestCapability, RequestContext, RequestHandler } from '../core';
77
import { HttpMeans } from './http.means';
88

99
/**
@@ -52,12 +52,12 @@ export namespace Middleware {
5252
* @typeparam TInput A type of input HTTP request processing means.
5353
* @param middleware Middleware to apply.
5454
*
55-
* @returns New request processing capability set that processes HTTP requests by the given `middleware`.
55+
* @returns New request processing capability that processes HTTP requests by the given `middleware`.
5656
*/
5757
export function middleware<TInput extends HttpMeans>(
5858
middleware: Middleware<TInput['request'], TInput['response']>,
59-
): RequestCapabilities<TInput> {
60-
return RequestCapabilities.of(
59+
): RequestCapability<TInput> {
60+
return RequestCapability.of(
6161
<TMeans extends TInput>(handler: RequestHandler<TMeans>) => async (
6262
{ request, response, next }: RequestContext<TMeans>,
6363
) => new Promise<void>((resolve, reject) => {

src/http/render/rendering.capability.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @packageDocumentation
33
* @module @hatsy/hatsy
44
*/
5-
import { RequestCapability, RequestContext, requestExtension, RequestModification } from '../../core';
5+
import { RequestCapability, requestExtension, RequestHandler } from '../../core';
66
import { HttpMeans } from '../http.means';
77
import { HTML__MIME, JSON__MIME } from '../util';
88
import { RenderMeans } from './render.means';
@@ -12,40 +12,43 @@ import { RenderMeans } from './render.means';
1212
*/
1313
class RenderingCapability extends RequestCapability<HttpMeans, RenderMeans> {
1414

15-
modification<TMeans extends HttpMeans>(
16-
{
17-
request: { method },
18-
response,
19-
}: RequestContext<TMeans>,
20-
): RequestModification<TMeans, RenderMeans> {
15+
for<TMeans extends HttpMeans>(
16+
handler: RequestHandler<TMeans & RenderMeans>,
17+
): RequestHandler<TMeans> {
18+
return ({
19+
request: { method },
20+
response,
21+
next,
22+
}) => {
2123

22-
const renderBody = (body: string | Buffer, encoding: BufferEncoding = 'utf-8'): void => {
24+
const renderBody = (body: string | Buffer, encoding: BufferEncoding = 'utf-8'): void => {
2325

24-
const length = Buffer.isBuffer(body) ? body.byteLength : Buffer.byteLength(body, encoding);
26+
const length = Buffer.isBuffer(body) ? body.byteLength : Buffer.byteLength(body, encoding);
2527

26-
response.setHeader('Content-Length', length);
27-
if (method === 'HEAD') {
28-
response.end();
29-
} else {
30-
response.end(body, encoding);
31-
}
32-
};
28+
response.setHeader('Content-Length', length);
29+
if (method === 'HEAD') {
30+
response.end();
31+
} else {
32+
response.end(body, encoding);
33+
}
34+
};
3335

34-
return requestExtension<TMeans, RenderMeans>({
36+
return next(handler, requestExtension<TMeans, RenderMeans>({
3537

36-
renderBody,
38+
renderBody,
3739

38-
renderHtml(html: string | Buffer) {
39-
response.setHeader('Content-Type', `${HTML__MIME}; charset=utf-8`);
40-
renderBody(html);
41-
},
40+
renderHtml(html: string | Buffer) {
41+
response.setHeader('Content-Type', `${HTML__MIME}; charset=utf-8`);
42+
renderBody(html);
43+
},
4244

43-
renderJson(body: any) {
44-
response.setHeader('Content-Type', `${JSON__MIME}; charset=utf-8`);
45-
renderBody(JSON.stringify(body));
46-
},
45+
renderJson(body: any) {
46+
response.setHeader('Content-Type', `${JSON__MIME}; charset=utf-8`);
47+
renderBody(JSON.stringify(body));
48+
},
4749

48-
});
50+
}));
51+
};
4952
}
5053

5154
}

0 commit comments

Comments
 (0)