Skip to content

Commit 0f39391

Browse files
committed
Simplify
1 parent f3f55ce commit 0f39391

File tree

13 files changed

+201
-157
lines changed

13 files changed

+201
-157
lines changed

pkgs/typed-api-spec/package.json

-15
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,6 @@
107107
"types": "./dist/json/index.d.ts",
108108
"require": "./dist/json/index.js",
109109
"import": "./dist/json/index.mjs"
110-
},
111-
"./zod": {
112-
"types": "./dist/zod/index.d.ts",
113-
"require": "./dist/zod/index.js",
114-
"import": "./dist/zod/index.mjs"
115-
},
116-
"./valibot": {
117-
"types": "./dist/valibot/index.d.ts",
118-
"require": "./dist/valibot/index.js",
119-
"import": "./dist/valibot/index.mjs"
120-
},
121-
"./ss": {
122-
"types": "./dist/ss/index.d.ts",
123-
"require": "./dist/ss/index.js",
124-
"import": "./dist/ss/index.mjs"
125110
}
126111
},
127112
"main": "./dist/index.js",

pkgs/typed-api-spec/src/valibot/openapi.test.ts pkgs/typed-api-spec/src/core/openapi/openapi-valibot.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, it, expect } from "vitest";
22
import * as v from "valibot";
33
import { OpenAPIV3_1 } from "openapi-types";
4-
import { SSOpenApiEndpoints, toOpenApiDoc } from "../core";
4+
import { SSOpenApiEndpoints, toOpenApiDoc } from "..";
55

66
describe("openapi", () => {
77
const endpoints = {

pkgs/typed-api-spec/src/zod/openapi.test.ts pkgs/typed-api-spec/src/core/openapi/openapi-zod.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
22
import { OpenAPIV3_1 } from "openapi-types";
33
import "zod-openapi/extend";
44
import z from "zod";
5-
import { SSOpenApiEndpoints, toOpenApiDoc } from "../core";
5+
import { SSOpenApiEndpoints, toOpenApiDoc } from "..";
66
describe("openapi", () => {
77
const endpoints = {
88
"/pets": {

pkgs/typed-api-spec/src/express/index.ts

+86-16
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { IRouter, RequestHandler } from "express";
1+
import { IRouter, RequestHandler, Router } from "express";
22
import {
33
Method,
44
AnyApiResponses,
55
ApiResBody,
66
ApiSpec,
7-
AnyApiSpec,
87
AnyApiEndpoints,
98
} from "../index";
109
import {
@@ -15,9 +14,14 @@ import {
1514
} from "express-serve-static-core";
1615
import { StatusCode } from "../core";
1716
import { ParsedQs } from "qs";
18-
import { AnySpecValidator, SpecValidatorMap } from "../core/validator/request";
17+
import { AnySpecValidator } from "../core/validator/request";
1918
import { StandardSchemaV1 } from "@standard-schema/spec";
20-
import { newSSValidator, SSApiEndpoints } from "../core/ss";
19+
import {
20+
newSSValidator,
21+
SSApiEndpoints,
22+
ToApiEndpoints,
23+
ToSSValidators,
24+
} from "../core/ss";
2125

2226
/**
2327
* Express Request Handler, but with more strict type information.
@@ -37,23 +41,64 @@ export type Handler<
3741
) => void;
3842

3943
export type ToHandler<
40-
Spec extends AnyApiSpec | undefined,
41-
Validators extends AnySpecValidator | undefined,
44+
E extends SSApiEndpoints,
45+
Path extends keyof E & string,
46+
M extends Method,
4247
> = Handler<
43-
Spec,
48+
ToApiEndpoints<E>[Path][M],
4449
ValidateLocals<
45-
Validators extends AnySpecValidator ? Validators : Record<string, never>
50+
ToSSValidators<E, Path, M> extends AnySpecValidator
51+
? ToSSValidators<E, Path, M>
52+
: Record<string, never>
4653
>
4754
>;
55+
// export type ToHandler<
56+
// Spec extends AnyApiSpec | undefined,
57+
// Validators extends AnySpecValidator | undefined,
58+
// > = Handler<
59+
// Spec,
60+
// ValidateLocals<
61+
// Validators extends AnySpecValidator ? Validators : Record<string, never>
62+
// >
63+
// >;
4864

49-
export type ToHandlers<
50-
E extends AnyApiEndpoints,
51-
V extends SpecValidatorMap,
52-
> = {
65+
/**
66+
* Convert ZodApiSpec to Express Request Handler type.
67+
*/
68+
// export type ToHandler<
69+
// ZodE extends SSApiEndpoints,
70+
// Path extends keyof ZodE & string,
71+
// M extends Method,
72+
// > = ToPureHandler<ToApiEndpoints<ZodE>[Path][M], ToSSValidators<ZodE, Path, M>>;
73+
74+
export type ToHandlers<E extends SSApiEndpoints> = {
5375
[Path in keyof E & string]: {
54-
[M in Method]: ToHandler<E[Path][M], V[Path][M]>;
76+
[M in Method]: ToHandler<E, Path, M>;
5577
};
5678
};
79+
// export type ToHandlers<
80+
// E extends AnyApiEndpoints,
81+
// V extends SpecValidatorMap,
82+
// > = {
83+
// [Path in keyof E & string]: {
84+
// [M in Method]: ToHandler<E[Path][M], V[Path][M]>;
85+
// };
86+
// };
87+
88+
/**
89+
* Convert SSApiEndpoints to Express Request Handler type map.
90+
*/
91+
// export type ToHandlers<
92+
// ZodE extends SSApiEndpoints,
93+
// E extends ToApiEndpoints<ZodE> = ToApiEndpoints<ZodE>,
94+
// V extends ToValidatorsMap<ZodE> = ToValidatorsMap<ZodE>,
95+
// > = ToPureHandlers<E, V>;
96+
97+
// export type ToValidatorsMap<ESchema extends SSApiEndpoints> = {
98+
// [Path in keyof ESchema & string]: {
99+
// [M in Method]: ToSSValidators<ESchema, Path, M>;
100+
// };
101+
// };
57102

58103
/**
59104
* Express Response, but with more strict type information.
@@ -80,7 +125,6 @@ export type ValidateLocals<
80125
*/
81126
export type RouterT<
82127
E extends AnyApiEndpoints,
83-
V extends SpecValidatorMap,
84128
SC extends StatusCode = StatusCode,
85129
> = Omit<IRouter, Method> & {
86130
[M in Method]: <Path extends string & keyof E>(
@@ -89,9 +133,9 @@ export type RouterT<
89133
// Middlewareは複数のエンドポイントで実装を使い回されることがあるので、型チェックはゆるくする
90134
...Array<RequestHandler>,
91135
// Handlerは厳密に型チェックする
92-
ToHandler<E[Path][M], V[Path][M]>,
136+
ToHandler<E, Path, M>,
93137
]
94-
) => RouterT<E, V, SC>;
138+
) => RouterT<E, SC>;
95139
};
96140

97141
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -212,3 +256,29 @@ export const asAsync = <Router extends IRouter | RouterT<any, any>>(
212256
},
213257
});
214258
};
259+
260+
/**
261+
* Set validator and add more strict type information to router.
262+
*
263+
* @param pathMap API endpoints
264+
* @param router Express Router
265+
*
266+
* @example
267+
* ```
268+
* const router = typed(pathMap, express.Router())
269+
* router.get('/path', (req, res) => {
270+
* const {data, error} = res.locals.validate(req).query()
271+
* if (error) {
272+
* return res.status(400).json({ message: 'Invalid query' })
273+
* }
274+
* return res.status(200).json({ message: 'success', value: r.data.value })
275+
* })
276+
* ```
277+
*/
278+
export const typed = <const Endpoints extends SSApiEndpoints>(
279+
pathMap: Endpoints,
280+
router: Router,
281+
): RouterT<Endpoints> => {
282+
router.use(validatorMiddleware(pathMap));
283+
return router;
284+
};

pkgs/typed-api-spec/src/express/ss.ts

+58-58
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,62 @@
1-
import { Method } from "../core";
2-
import { SSApiEndpoints, ToApiEndpoints, ToSSValidators } from "../core/ss";
3-
import {
4-
RouterT,
5-
ToHandler as ToPureHandler,
6-
ToHandlers as ToPureHandlers,
7-
validatorMiddleware,
8-
} from "./index";
9-
import { Router } from "express";
1+
// import { Method } from "../core";
2+
// import { SSApiEndpoints, ToApiEndpoints, ToSSValidators } from "../core/ss";
3+
// import {
4+
// RouterT,
5+
// ToHandler as ToPureHandler,
6+
// ToHandlers as ToPureHandlers,
7+
// validatorMiddleware,
8+
// } from "./index";
9+
// import { Router } from "express";
1010

11-
/**
12-
* Convert ZodApiSpec to Express Request Handler type.
13-
*/
14-
export type ToHandler<
15-
ZodE extends SSApiEndpoints,
16-
Path extends keyof ZodE & string,
17-
M extends Method,
18-
> = ToPureHandler<ToApiEndpoints<ZodE>[Path][M], ToSSValidators<ZodE, Path, M>>;
11+
// /**
12+
// * Convert ZodApiSpec to Express Request Handler type.
13+
// */
14+
// export type ToHandler<
15+
// ZodE extends SSApiEndpoints,
16+
// Path extends keyof ZodE & string,
17+
// M extends Method,
18+
// > = ToPureHandler<ToApiEndpoints<ZodE>[Path][M], ToSSValidators<ZodE, Path, M>>;
1919

20-
/**
21-
* Convert SSApiEndpoints to Express Request Handler type map.
22-
*/
23-
export type ToHandlers<
24-
ZodE extends SSApiEndpoints,
25-
E extends ToApiEndpoints<ZodE> = ToApiEndpoints<ZodE>,
26-
V extends ToValidatorsMap<ZodE> = ToValidatorsMap<ZodE>,
27-
> = ToPureHandlers<E, V>;
20+
// /**
21+
// * Convert SSApiEndpoints to Express Request Handler type map.
22+
// */
23+
// export type ToHandlers<
24+
// ZodE extends SSApiEndpoints,
25+
// E extends ToApiEndpoints<ZodE> = ToApiEndpoints<ZodE>,
26+
// V extends ToValidatorsMap<ZodE> = ToValidatorsMap<ZodE>,
27+
// > = ToPureHandlers<E, V>;
2828

29-
export type ToValidatorsMap<ZodE extends SSApiEndpoints> = {
30-
[Path in keyof ZodE & string]: {
31-
[M in Method]: ToSSValidators<ZodE, Path, M>;
32-
};
33-
};
29+
// export type ToValidatorsMap<ZodE extends SSApiEndpoints> = {
30+
// [Path in keyof ZodE & string]: {
31+
// [M in Method]: ToSSValidators<ZodE, Path, M>;
32+
// };
33+
// };
3434

35-
/**
36-
* Set validator and add more strict type information to router.
37-
*
38-
* @param pathMap API endpoints
39-
* @param router Express Router
40-
*
41-
* @example
42-
* ```
43-
* const router = typed(pathMap, express.Router())
44-
* router.get('/path', (req, res) => {
45-
* const {data, error} = res.locals.validate(req).query()
46-
* if (error) {
47-
* return res.status(400).json({ message: 'Invalid query' })
48-
* }
49-
* return res.status(200).json({ message: 'success', value: r.data.value })
50-
* })
51-
* ```
52-
*/
53-
export const typed = <const Endpoints extends SSApiEndpoints>(
54-
pathMap: Endpoints,
55-
router: Router,
56-
): RouterT<ToApiEndpoints<Endpoints>, ToValidatorsMap<Endpoints>> => {
57-
// const { req: reqValidator } = newSSValidator(pathMap);
58-
// router.use(validatorMiddleware(reqValidator));
59-
// const { req: reqValidator } = newSSValidator(pathMap);
60-
router.use(validatorMiddleware(pathMap));
61-
return router;
62-
};
35+
// /**
36+
// * Set validator and add more strict type information to router.
37+
// *
38+
// * @param pathMap API endpoints
39+
// * @param router Express Router
40+
// *
41+
// * @example
42+
// * ```
43+
// * const router = typed(pathMap, express.Router())
44+
// * router.get('/path', (req, res) => {
45+
// * const {data, error} = res.locals.validate(req).query()
46+
// * if (error) {
47+
// * return res.status(400).json({ message: 'Invalid query' })
48+
// * }
49+
// * return res.status(200).json({ message: 'success', value: r.data.value })
50+
// * })
51+
// * ```
52+
// */
53+
// export const typed = <const Endpoints extends SSApiEndpoints>(
54+
// pathMap: Endpoints,
55+
// router: Router,
56+
// ): RouterT<ToApiEndpoints<Endpoints>, ToValidatorsMap<Endpoints>> => {
57+
// // const { req: reqValidator } = newSSValidator(pathMap);
58+
// // router.use(validatorMiddleware(reqValidator));
59+
// // const { req: reqValidator } = newSSValidator(pathMap);
60+
// router.use(validatorMiddleware(pathMap));
61+
// return router;
62+
// };

pkgs/typed-api-spec/src/express/valibot.test.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { describe, it, expect, vi, assert } from "vitest";
22
import request from "supertest";
33
import express from "express";
4-
import { asAsync, ValidateLocals, validatorMiddleware } from "./index";
4+
import {
5+
asAsync,
6+
ToHandlers,
7+
typed,
8+
ValidateLocals,
9+
validatorMiddleware,
10+
} from "./index";
511
import * as v from "valibot";
612
import { Request } from "express";
713
import { ParseUrlParams } from "../core";
@@ -10,7 +16,6 @@ import {
1016
newValidatorPathNotFoundError,
1117
} from "../core/validator/validate";
1218
import { SSApiEndpoints, SSApiSpec, SSValidators } from "../core/ss";
13-
import { ToHandlers, typed } from "./ss";
1419

1520
type SSValidateLocals<
1621
AS extends SSApiSpec,

pkgs/typed-api-spec/src/express/zod.test.ts

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import { describe, it, expect, vi, assert } from "vitest";
22
import request from "supertest";
33
import express from "express";
4-
import { asAsync, ValidateLocals, validatorMiddleware } from "./index";
4+
import {
5+
asAsync,
6+
RouterT,
7+
ToHandlers,
8+
typed,
9+
ValidateLocals,
10+
validatorMiddleware,
11+
} from "./index";
512
import { z } from "zod";
613
import { Request } from "express";
714
import { ParseUrlParams } from "../core";
@@ -10,7 +17,6 @@ import {
1017
newValidatorPathNotFoundError,
1118
} from "../core/validator/validate";
1219
import { SSApiEndpoints, SSApiSpec, SSValidators } from "../core/ss";
13-
import { ToHandlers, typed } from "./ss";
1420

1521
type SSValidateLocals<
1622
AS extends SSApiSpec,
@@ -50,8 +56,7 @@ describe("validatorMiddleware", () => {
5056
},
5157
},
5258
} satisfies SSApiEndpoints;
53-
// const { req: reqValidator } = newSSValidator(pathMap);
54-
// const middleware = validatorMiddleware(reqValidator);
59+
5560
const middleware = validatorMiddleware(pathMap);
5661
const next = vi.fn();
5762

@@ -278,6 +283,25 @@ describe("typed", () => {
278283
},
279284
} satisfies SSApiEndpoints;
280285

286+
type R = RouterT<typeof pathMap, 200>;
287+
const r = {} as R;
288+
r.get("/users", (req, res) => {
289+
res.json([{ id: "1", name: "alice" }]);
290+
});
291+
// type A = ToHandlers<typeof pathMap>["/users"]["get"];
292+
// const a: A = (req, res) => {
293+
// res.json([{ id: "1", name: "alice" }]);
294+
// };
295+
// type A = ToHandler<typeof pathMap, "/users", "get">;
296+
// type B = ToApiEndpoints<
297+
// typeof pathMap
298+
// >["/users"]["get"]["responses"][200]["body"];
299+
// type ERes = ExpressResponse<
300+
// ToApiEndpoints<typeof pathMap>["/users"]["get"]["responses"],
301+
// 200
302+
// >;
303+
// const eres = {} as ERes;
304+
// eres.json([{ id: "1", name: "alice" }]);
281305
it("ok", async () => {
282306
const app = newApp();
283307
const wApp = typed(pathMap, app);

0 commit comments

Comments
 (0)