alien-middleware 0.9.0 → 0.9.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.
@@ -1,4 +1,3 @@
1
- import { Any, noop } from 'radashi';
2
1
  import { AdapterRequestContext, HattipHandler } from '@hattip/core';
3
2
  import { InferParams } from 'pathic';
4
3
 
@@ -7,10 +6,7 @@ type Eval<T> = {} & {
7
6
  };
8
7
  type Awaitable<T> = T | Promise<T>;
9
8
  type OneOrMany<T> = T | readonly T[];
10
- /**
11
- * Converts a type `T` to something that can be intersected with an object.
12
- */
13
- type Intersectable<T extends object> = [T] extends [never] ? {} : [T] extends [Any] ? Record<PropertyKey, any> : T;
9
+ type CastNever<T, U> = [T] extends [never] ? U : T;
14
10
 
15
11
  type Keys<T> = T extends any ? keyof T : never;
16
12
  type IsOptional<T, K> = K extends keyof T ? T[K] extends Required<T>[K] ? false : true : true;
@@ -21,8 +17,8 @@ type MergeProperty<TSource, TOverrides, K> = (K extends keyof TOverrides ? Possi
21
17
  *
22
18
  * **FIXME:** Optional properties resolve as `foo: Foo | undefined` instead of `foo?: Foo`.
23
19
  */
24
- type Merge<TSource extends object, TOverrides extends object | undefined> = Eval<Omit<TSource, Keys<TOverrides>> & {
25
- [K in Keys<TOverrides>]: TOverrides extends any ? MergeProperty<TSource, TOverrides, K> : never;
20
+ type Merge<TSource extends object, TOverrides extends object | undefined> = Eval<Omit<CastNever<TSource, {}>, Keys<TOverrides>> & {
21
+ [K in Keys<TOverrides>]: TOverrides extends any ? MergeProperty<CastNever<TSource, {}>, TOverrides, K> : never;
26
22
  }>;
27
23
 
28
24
  type RequestEnvPlugin = {
@@ -67,13 +63,13 @@ type AnyMiddlewareTypes = {
67
63
  platform: any;
68
64
  };
69
65
  type AnyMiddlewareChain = MiddlewareChain<AnyMiddlewareTypes>;
70
- type Inputs<T extends AnyMiddlewareChain> = T['$']['initial'];
66
+ type Inputs<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['initial'];
71
67
  type InputProperties<T extends AnyMiddlewareChain> = Inputs<T>['properties'];
72
68
  type InputEnv<T extends AnyMiddlewareChain> = Inputs<T>['env'];
73
- type Current<T extends AnyMiddlewareChain> = T['$']['current'];
69
+ type Current<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['current'];
74
70
  type Properties<T extends AnyMiddlewareChain> = Current<T>['properties'];
75
71
  type Env<T extends AnyMiddlewareChain> = Current<T>['env'];
76
- type Platform<T extends AnyMiddlewareChain> = T['$']['platform'];
72
+ type Platform<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['platform'];
77
73
  interface HattipContext<TPlatform, TEnv extends object> extends AdapterRequestContext<TPlatform> {
78
74
  /**
79
75
  * The `request.url` string parsed into a `URL` object. Parsing is performed
@@ -96,7 +92,7 @@ interface HattipContext<TPlatform, TEnv extends object> extends AdapterRequestCo
96
92
  * should prefer `RequestContext<any>` over `RequestContext` (no type
97
93
  * parameters), as the default type is stricter.
98
94
  */
99
- type RequestContext<TEnv extends object = any, TProperties extends object = never, TPlatform = any> = HattipContext<TPlatform, TEnv> & Intersectable<TProperties>;
95
+ type RequestContext<TEnv extends object = any, TProperties extends object = never, TPlatform = any> = HattipContext<TPlatform, TEnv> & CastNever<TProperties, unknown>;
100
96
  /**
101
97
  * Extract a `RequestContext` type from a `MiddlewareChain` type.
102
98
  *
@@ -115,11 +111,20 @@ interface RequestHandler<T extends MiddlewareTypes = any> extends HattipHandler<
115
111
  * response middleware. This means it will run *after* a `Response` is generated
116
112
  * by a request middleware.
117
113
  */
118
- type Middleware<TEnv extends object = any, TProperties extends object = any, TPlatform = any> = (context: RequestContext<TEnv, TProperties, TPlatform>, response: Response) => Awaitable<Response | RequestPlugin | void>;
114
+ type Middleware<TEnv extends object = any, TProperties extends object = any, TPlatform = any> = {
115
+ (context: RequestContext<TEnv, TProperties, TPlatform>, response: Response): Awaitable<Response | RequestPlugin | void>;
116
+ /** This property won't exist at runtime. It contains type information for inference purposes. */
117
+ $Middleware?: MiddlewareTypes & {
118
+ initial: {
119
+ env: TEnv;
120
+ properties: TProperties;
121
+ };
122
+ };
123
+ };
119
124
  /**
120
125
  * Extract a `Middleware` type from a `MiddlewareChain` type.
121
126
  */
122
- type ExtractMiddleware<T extends MiddlewareChain> = Middleware<Env<T>, Properties<T>, Platform<T>>;
127
+ type ExtractMiddleware<T extends MiddlewareChain> = [T] extends [never] ? Middleware<{}, {}, any> : Middleware<Env<T>, Properties<T>, Platform<T>>;
123
128
  /**
124
129
  * Merge a request plugin into a middleware chain.
125
130
  */
@@ -129,20 +134,29 @@ type ApplyMiddlewareResult<TParent extends MiddlewareChain, TResult> = Eval<{
129
134
  } ? TEnv : undefined>;
130
135
  properties: Merge<Properties<TParent>, TResult extends RequestPlugin ? Omit<TResult, keyof RequestEnvPlugin> : undefined>;
131
136
  }>;
137
+ type ApplyMiddlewareOutputs<TFirst extends MiddlewareChain, TSecond extends Middleware> = TSecond extends MiddlewareChain ? {
138
+ env: Merge<Env<TFirst>, Env<TSecond>>;
139
+ properties: Merge<Properties<TFirst>, Properties<TSecond>>;
140
+ } : TSecond extends (...args: any[]) => Awaitable<infer TResult> ? ApplyMiddlewareResult<TFirst, TResult> : Current<TFirst>;
141
+ type MiddlewareInputs<T extends Middleware> = T extends Middleware<infer TEnv, infer TProperties> ? {
142
+ env: TEnv;
143
+ properties: TProperties;
144
+ } : never;
145
+ type MiddlewarePlatform<T extends Middleware> = T extends Middleware<any, any, infer TPlatform> ? TPlatform : never;
132
146
  /**
133
147
  * This applies a middleware to a chain. If the type `TMiddleware` is itself a
134
148
  * chain, it's treated as a nested chain, which won't leak its plugins into the
135
149
  * parent chain.
150
+ *
151
+ * The `TFirst` type is allowed to be `never`, which results in the middleware's
152
+ * output types being used as the request handler's input types.
136
153
  */
137
- type ApplyMiddleware<TFirst extends MiddlewareChain, TSecond extends Middleware<Env<TFirst>, Properties<TFirst>, Platform<TFirst>>> = (TSecond extends MiddlewareChain ? {
138
- env: Merge<Env<TFirst>, Env<TSecond>>;
139
- properties: Merge<Properties<TFirst>, Properties<TSecond>>;
140
- } : TSecond extends (...args: any[]) => Awaitable<infer TResult> ? ApplyMiddlewareResult<TFirst, TResult> : Current<TFirst>) extends infer TOutputs extends MiddlewareTypes['current'] ? RequestHandler<{
141
- initial: Inputs<TFirst>;
142
- current: TOutputs;
143
- platform: Platform<TFirst>;
154
+ type ApplyMiddleware<TFirst extends MiddlewareChain, TSecond extends Middleware> = ApplyMiddlewareOutputs<TFirst, TSecond> extends infer TCurrent extends MiddlewareTypes['current'] ? RequestHandler<{
155
+ initial: CastNever<Inputs<TFirst>, MiddlewareInputs<TSecond>>;
156
+ current: TCurrent;
157
+ platform: CastNever<Platform<TFirst>, MiddlewarePlatform<TSecond>>;
144
158
  }> : never;
145
- type EmptyMiddlewareChain = MiddlewareChain<{
159
+ type EmptyMiddlewareChain<TPlatform = unknown> = MiddlewareChain<{
146
160
  initial: {
147
161
  env: {};
148
162
  properties: {};
@@ -151,18 +165,18 @@ type EmptyMiddlewareChain = MiddlewareChain<{
151
165
  env: {};
152
166
  properties: {};
153
167
  };
154
- platform: unknown;
168
+ platform: TPlatform;
155
169
  }>;
156
- type ApplyFirstMiddleware<T extends Middleware> = T extends MiddlewareChain ? T : ApplyMiddleware<EmptyMiddlewareChain, T>;
170
+ type ApplyFirstMiddleware<T extends Middleware> = T extends MiddlewareChain ? T : ApplyMiddleware<EmptyMiddlewareChain<MiddlewarePlatform<T>>, T>;
157
171
  type RouteMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD' | (string & {});
158
- type RouteContext<T extends RouterTypes = any, TPathParams extends object = any, TMethod extends RouteMethod = RouteMethod> = MiddlewareContext<ApplyMiddleware<MiddlewareChain<T['$']>, () => {
172
+ type RouteContext<T extends RouterTypes = any, TPathParams extends object = any, TMethod extends RouteMethod = RouteMethod> = MiddlewareContext<ApplyMiddleware<MiddlewareChain<T['$Router']>, () => {
159
173
  params: TPathParams;
160
174
  method: TMethod;
161
175
  }>>;
162
176
  type RouteHandler<T extends RouterTypes = any, TPathParams extends object = any, TMethod extends RouteMethod = RouteMethod> = (context: RouteContext<T, TPathParams, TMethod>) => Awaitable<Response | void>;
163
177
  declare class RouterTypes<T extends MiddlewareChain = any> extends Function {
164
178
  /** This property won't exist at runtime. It contains type information for inference purposes. */
165
- $: T['$'];
179
+ $Router: T['$MiddlewareChain'];
166
180
  }
167
181
  interface Router<T extends MiddlewareChain = any> extends RouterTypes<T> {
168
182
  (context: AdapterRequestContext<Platform<T>>): Awaitable<void | Response>;
@@ -174,7 +188,7 @@ declare const kRequestChain: unique symbol;
174
188
  declare const kResponseChain: unique symbol;
175
189
  declare class MiddlewareChain<T extends MiddlewareTypes = any> {
176
190
  /** This property won't exist at runtime. It contains type information for inference purposes. */
177
- $: T;
191
+ $MiddlewareChain: T;
178
192
  /** The number of parameters when called as a function. */
179
193
  readonly length: 1;
180
194
  protected [kRequestChain]: RequestMiddleware[];
@@ -194,7 +208,7 @@ declare class MiddlewareChain<T extends MiddlewareTypes = any> {
194
208
  * Create a middleware function that encapsulates this middleware chain, so
195
209
  * any modifications it makes to the request context are not leaked.
196
210
  */
197
- isolate(): ((ctx: IsolatedContext<this>) => Promise<Response | void>) | typeof noop;
211
+ isolate(): (ctx: IsolatedContext<this>) => Awaitable<Response | void>;
198
212
  }
199
213
  declare function chain<TEnv extends object = {}, TProperties extends object = {}, TPlatform = unknown>(): MiddlewareChain<{
200
214
  initial: {
@@ -207,6 +221,6 @@ declare function chain<TEnv extends object = {}, TProperties extends object = {}
207
221
  };
208
222
  platform: TPlatform;
209
223
  }>;
210
- declare function chain<const T extends Middleware = Middleware>(middleware: T): ApplyFirstMiddleware<T>;
224
+ declare function chain<const T extends Middleware = Middleware<{}, {}, unknown>>(middleware: T): ApplyFirstMiddleware<T>;
211
225
 
212
226
  export { type ApplyMiddleware as A, type EmptyMiddlewareChain as E, type MiddlewareContext as M, type Router as R, MiddlewareChain as a, type RouteContext as b, type RouteHandler as c, chain as d, type ExtractMiddleware as e, type Middleware as f, type RequestContext as g, type RequestHandler as h, type RequestMiddleware as i, type RequestPlugin as j, type ResponseMiddleware as k };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import 'radashi';
2
- export { A as ApplyMiddleware, e as ExtractMiddleware, f as Middleware, a as MiddlewareChain, M as MiddlewareContext, g as RequestContext, h as RequestHandler, i as RequestMiddleware, j as RequestPlugin, k as ResponseMiddleware, d as chain } from './index-vRvlpUCy.js';
1
+ export { A as ApplyMiddleware, e as ExtractMiddleware, f as Middleware, a as MiddlewareChain, M as MiddlewareContext, g as RequestContext, h as RequestHandler, i as RequestMiddleware, j as RequestPlugin, k as ResponseMiddleware, d as chain } from './index-B5T_qCSA.js';
3
2
  import '@hattip/core';
4
3
  import 'pathic';
package/dist/router.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { R as Router, M as MiddlewareContext, a as MiddlewareChain, E as EmptyMiddlewareChain } from './index-vRvlpUCy.js';
2
- export { b as RouteContext, c as RouteHandler } from './index-vRvlpUCy.js';
3
- import 'radashi';
1
+ import { R as Router, M as MiddlewareContext, a as MiddlewareChain, E as EmptyMiddlewareChain } from './index-B5T_qCSA.js';
2
+ export { b as RouteContext, c as RouteHandler } from './index-B5T_qCSA.js';
4
3
  import '@hattip/core';
5
4
  import 'pathic';
6
5
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alien-middleware",
3
3
  "type": "module",
4
- "version": "0.9.0",
4
+ "version": "0.9.1",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",