@di-framework/di-framework-http 0.0.0-prerelease.306 → 0.0.0-prerelease.308
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/dist/src/typed-router.d.ts +11 -1
- package/package.json +2 -2
- package/src/cli.test.ts +2 -2
- package/src/typed-router.test.ts +21 -0
- package/src/typed-router.ts +13 -1
|
@@ -8,6 +8,12 @@ export type Multipart<T> = {
|
|
|
8
8
|
readonly __kind: "multipart";
|
|
9
9
|
readonly __type?: T;
|
|
10
10
|
};
|
|
11
|
+
export type PathParams<T> = {
|
|
12
|
+
readonly __pathParams?: T;
|
|
13
|
+
};
|
|
14
|
+
export type QueryParams<T> = {
|
|
15
|
+
readonly __queryParams?: T;
|
|
16
|
+
};
|
|
11
17
|
/** Spec types you’ll use in generics */
|
|
12
18
|
export type RequestSpec<BodySpec = unknown> = {
|
|
13
19
|
readonly __req?: BodySpec;
|
|
@@ -17,9 +23,13 @@ export type ResponseSpec<Body = unknown> = {
|
|
|
17
23
|
};
|
|
18
24
|
/** Map a BodySpec to the actual req.content type */
|
|
19
25
|
type ContentOf<BodySpec> = BodySpec extends Json<infer T> ? T : BodySpec extends Multipart<infer _T> ? FormData : unknown;
|
|
26
|
+
type PathParamsOf<BodySpec> = BodySpec extends PathParams<infer T> ? T : Record<string, string>;
|
|
27
|
+
type QueryParamsOf<BodySpec> = BodySpec extends QueryParams<infer T> ? T : Record<string, string | string[] | undefined>;
|
|
20
28
|
/** The actual request type your handlers receive */
|
|
21
|
-
export type TypedRequest<ReqSpec> = IRequest & {
|
|
29
|
+
export type TypedRequest<ReqSpec> = Omit<IRequest, "params" | "query"> & {
|
|
22
30
|
content: ContentOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
31
|
+
params: PathParamsOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
32
|
+
query: QueryParamsOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
23
33
|
};
|
|
24
34
|
/** Typed response helper (phantom only) */
|
|
25
35
|
export type TypedResponse<ResSpec> = globalThis.Response & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@di-framework/di-framework-http",
|
|
3
|
-
"version": "0.0.0-prerelease.
|
|
3
|
+
"version": "0.0.0-prerelease.308",
|
|
4
4
|
"description": "Extends di-framework with HTTP features",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typescript": "^5"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@di-framework/di-framework": "^0.0.0-prerelease.
|
|
43
|
+
"@di-framework/di-framework": "^0.0.0-prerelease.308",
|
|
44
44
|
"typescript": "^5"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/cli.test.ts
CHANGED
|
@@ -29,7 +29,7 @@ describe("CLI", () => {
|
|
|
29
29
|
it("should generate OpenAPI spec with --controllers and --output", () => {
|
|
30
30
|
const controllersPath = path.resolve(
|
|
31
31
|
import.meta.dir,
|
|
32
|
-
"../../examples/http-router/index.ts",
|
|
32
|
+
"../../examples/packages/http-router/index.ts",
|
|
33
33
|
);
|
|
34
34
|
const { stdout, status } = spawnSync("bun", [
|
|
35
35
|
CLI_PATH,
|
|
@@ -58,7 +58,7 @@ describe("CLI", () => {
|
|
|
58
58
|
|
|
59
59
|
const controllersPath = path.resolve(
|
|
60
60
|
import.meta.dir,
|
|
61
|
-
"../../examples/http-router/index.ts",
|
|
61
|
+
"../../examples/packages/http-router/index.ts",
|
|
62
62
|
);
|
|
63
63
|
const { status } = spawnSync("bun", [
|
|
64
64
|
CLI_PATH,
|
package/src/typed-router.test.ts
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
type Multipart,
|
|
6
6
|
type RequestSpec,
|
|
7
7
|
type ResponseSpec,
|
|
8
|
+
type PathParams,
|
|
9
|
+
type QueryParams,
|
|
8
10
|
} from "./typed-router.ts";
|
|
9
11
|
|
|
10
12
|
describe("TypedRouter", () => {
|
|
@@ -192,4 +194,23 @@ describe("TypedRouter", () => {
|
|
|
192
194
|
const res = await router.fetch(req);
|
|
193
195
|
expect(res.status).toBe(415);
|
|
194
196
|
});
|
|
197
|
+
|
|
198
|
+
it("should type params and query from RequestSpec", async () => {
|
|
199
|
+
const router = TypedRouter();
|
|
200
|
+
router.get<
|
|
201
|
+
RequestSpec<PathParams<{ id: string }> & QueryParams<{ search?: string }>>,
|
|
202
|
+
ResponseSpec<{ id: string; search?: string }>
|
|
203
|
+
>("/item/:id", (req) => {
|
|
204
|
+
// Type testing:
|
|
205
|
+
const id: string = req.params.id;
|
|
206
|
+
const search: string | undefined = req.query.search;
|
|
207
|
+
return json({ id, search });
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const req = new Request("http://localhost/item/123?search=test");
|
|
211
|
+
const res = await router.fetch(req);
|
|
212
|
+
expect(res.status).toBe(200);
|
|
213
|
+
const body = (await res.json()) as any;
|
|
214
|
+
expect(body).toEqual({ id: "123", search: "test" });
|
|
215
|
+
});
|
|
195
216
|
});
|
package/src/typed-router.ts
CHANGED
|
@@ -11,6 +11,8 @@ export type Multipart<T> = {
|
|
|
11
11
|
readonly __kind: "multipart";
|
|
12
12
|
readonly __type?: T;
|
|
13
13
|
};
|
|
14
|
+
export type PathParams<T> = { readonly __pathParams?: T };
|
|
15
|
+
export type QueryParams<T> = { readonly __queryParams?: T };
|
|
14
16
|
|
|
15
17
|
/** Spec types you’ll use in generics */
|
|
16
18
|
export type RequestSpec<BodySpec = unknown> = { readonly __req?: BodySpec };
|
|
@@ -24,9 +26,19 @@ type ContentOf<BodySpec> =
|
|
|
24
26
|
? FormData
|
|
25
27
|
: unknown;
|
|
26
28
|
|
|
29
|
+
type PathParamsOf<BodySpec> = BodySpec extends PathParams<infer T>
|
|
30
|
+
? T
|
|
31
|
+
: Record<string, string>;
|
|
32
|
+
|
|
33
|
+
type QueryParamsOf<BodySpec> = BodySpec extends QueryParams<infer T>
|
|
34
|
+
? T
|
|
35
|
+
: Record<string, string | string[] | undefined>;
|
|
36
|
+
|
|
27
37
|
/** The actual request type your handlers receive */
|
|
28
|
-
export type TypedRequest<ReqSpec> = IRequest & {
|
|
38
|
+
export type TypedRequest<ReqSpec> = Omit<IRequest, "params" | "query"> & {
|
|
29
39
|
content: ContentOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
40
|
+
params: PathParamsOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
41
|
+
query: QueryParamsOf<ReqSpec extends RequestSpec<infer B> ? B : never>;
|
|
30
42
|
};
|
|
31
43
|
|
|
32
44
|
/** Typed response helper (phantom only) */
|