Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/express/valibot/express.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from "express";
import { asAsync } from "../../../src/express";
import { pathMap } from "./spec";
import { pathMap } from "../../spec/valibot";
import { ToHandlers, typed } from "../../../src/express/valibot";

const emptyMiddleware = (
Expand Down
2 changes: 1 addition & 1 deletion examples/express/valibot/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PathMap } from "./spec";
import type { PathMap } from "../../spec/valibot";
import JSONT from "../../../src/json";
import { unreachable } from "../../../src/utils";
import type FetchT from "../../../src/fetch";
Expand Down
2 changes: 1 addition & 1 deletion examples/express/zod/express.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from "express";
import { asAsync } from "../../../src/express";
import { pathMap } from "./spec";
import { pathMap } from "../../spec/zod";
import { ToHandlers, typed } from "../../../src/express/zod";

const emptyMiddleware = (
Expand Down
2 changes: 1 addition & 1 deletion examples/express/zod/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PathMap } from "./spec";
import type { PathMap } from "../../spec/zod";
import JSONT from "../../../src/json";
import { unreachable } from "../../../src/utils";
import type FetchT from "../../../src/fetch";
Expand Down
86 changes: 86 additions & 0 deletions examples/fastify/zod/fastify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Import the framework and instantiate it
import Fastify, { FastifyError } from "fastify";
import {
serializerCompiler,
validatorCompiler,
ZodTypeProvider,
} from "fastify-type-provider-zod";
import { pathMap } from "../../spec/zod";
import { toRoutes } from "../../../src/fastify/zod";
import { ZodError } from "zod";
const fastify = Fastify({ logger: true });

fastify.setValidatorCompiler(validatorCompiler);
fastify.setSerializerCompiler(serializerCompiler);
const server = fastify.withTypeProvider<ZodTypeProvider>();
server.setErrorHandler<ZodError | FastifyError>((error, request, reply) => {
if (error instanceof ZodError) {
return reply
.status(400)
.type("application/json")
.send({ errorMessage: JSON.stringify(error.issues) });
}
return reply
.status(error.statusCode ?? 500)
.type("application/json")
.send({ errorMessage: error.message });
});
const routes = toRoutes(pathMap);

// Define by using route object
server.route({
...routes["/users"]["get"],
handler: async (request, reply) => {
const page = request.query.page;
if (Number.isNaN(Number(page))) {
return reply.status(400).send({ errorMessage: "page is not a number" });
}
return { userNames: [`page${page}#user1`] };
},
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _noExecution = () => {
// Or you can also define by using RouteShorthandMethod
server.get(
"/users",
{
schema: routes["/users"]["get"]["schema"],
},
async (request) => {
{
// @ts-expect-error noexist is not defined in pathMap["/users"]["get"]
request.query.noexist;
}
Comment on lines +51 to +54
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the redundant block statement.

The standalone block statement at line range 51-54 is redundant and can be safely removed to simplify the code.

Apply this diff to remove the redundant block statement:

-      {
-        // @ts-expect-error noexist is not defined in pathMap["/users"]["get"]
-        request.query.noexist;
-      }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
// @ts-expect-error noexist is not defined in pathMap["/users"]["get"]
request.query.noexist;
}
Tools
Biome

[error] 51-54: This block statement doesn't serve any purpose and can be safely removed.

Standalone block statements without any block-level declarations are redundant in JavaScript and can be removed to simplify the code.
Safe fix: Remove redundant block.

(lint/complexity/noUselessLoneBlockStatements)

const page = request.query.page;
return { userNames: [`page${page}#user1`] };
},
);
};

server.route({
...routes["/users"]["post"],
handler: async (request, reply) => {
const userName = request.body.userName;
return reply
.header("Content-Type", "application/json")
.send({ userId: userName + "#0" });
},
});

server.route({
...routes["/users/:userId"]["get"],
handler: async (request) => {
const userId = request.params.userId;
return { userName: `user#${userId}` };
},
});

(async () => {
try {
await fastify.listen({ port: 3000 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
})();
79 changes: 79 additions & 0 deletions examples/fastify/zod/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import JSONT from "../../../src/json";
import { unreachable } from "../../../src/utils";
import type FetchT from "../../../src/fetch";
import { PathMap } from "../../spec/zod";

const fetchT = fetch as FetchT<typeof origin, PathMap>;
const origin = "http://localhost:3000";
const headers = { "Content-Type": "application/json" } as const;
const JSONT = JSON as JSONT;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the unnecessary redeclaration of JSONT.

The JSONT constant is already imported at the beginning of the file. Redeclaring it here is redundant and can lead to confusion.

Apply this diff to remove the constant declaration:

-const JSONT = JSON as JSONT;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const JSONT = JSON as JSONT;
Tools
Biome

[error] 9-9: Shouldn't redeclare 'JSONT'. Consider to delete it or rename it.

'JSONT' is defined here:

(lint/suspicious/noRedeclare)


const main = async () => {
{
const path = `${origin}/users?page=1`;
const method = "get";
const res = await fetchT(path, { method });
switch (res.status) {
case 200: {
// r is the response schema defined in pathMap["/users"]["get"].res["200"]
const r = await res.json();
console.log(`${path}:${method} => ${r.userNames}`);
break;
}
case 400: {
// e is the response schema defined in pathMap["/users"]["get"].res["400"]
const e = await res.json();
console.log(`${path}:${method} => ${e.errorMessage}`);
break;
}
default:
unreachable(res);
}
}
{
// case-insensitive method example
await fetchT(`${origin}/users?page=1`, { method: "GET" });
}

{
const path = `${origin}/users`;
const method = "post";
const res = await fetchT(path, {
method,
headers,
// body is the request schema defined in pathMap["/users"]["post"].body
// stringify is same as JSON.stringify but with common information
body: JSONT.stringify({ userName: "user1" }),
});
if (res.ok) {
// r is the response schema defined in pathMap["/users"]["post"].res["20X"]
const r = await res.json();
console.log(`${path}:${method} => ${r.userId}`);
console.log(res.headers.get("Content-Type"));
} else {
// e is the response schema defined in pathMap["/users"]["post"].res other than "20X"
const e = await res.text();
console.log(`error:${path}:${method} => ${JSON.stringify(e)}`);
console.log(res.status);
}
}

{
// path parameter example
// "/users/:userId" accepts `/users/${string}` pattern
const path = `${origin}/users/1`;
const method = "get";
const res = await fetchT(path, { method });
if (res.ok) {
// r is the response schema defined in pathMap["/users/:userId"]["get"].res["20X"]
const r = await res.json();
console.log(`${path}:${method} => ${r.userName}`);
} else {
// e is the response schema defined in pathMap["/users/:userId"]["get"].res other than "20X"
const e = await res.json();
console.log(`${path}:${method} => ${e.errorMessage}`);
}
}
};

main();
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as v from "valibot";
import { ToApiEndpoints, ValibotApiEndpoints } from "../../../src/valibot";
import { ToApiEndpoints, ValibotApiEndpoints } from "../../src/valibot";

const JsonHeader = v.object({
"Content-Type": v.literal("application/json"),
Expand Down
9 changes: 5 additions & 4 deletions examples/express/zod/spec.ts → examples/spec/zod.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { z } from "zod";
import { ToApiEndpoints, ZodApiEndpoints } from "../../../src";
import { ToApiEndpoints, ZodApiEndpoints } from "../../src";

const JsonHeader = z.object({
"Content-Type": z.literal("application/json"),
});
const JsonHeader = z.union([
z.object({ "content-type": z.string() }),
z.object({ "Content-Type": z.string() }),
]);
export const pathMap = {
"/users": {
get: {
Expand Down
Loading