Skip to content
Snippets Groups Projects
Commit 4841e052 authored by Paolo.Brasolin's avatar Paolo.Brasolin
Browse files

feat: #be sketch cleanly typed API

parent 7cddffe5
No related branches found
No related tags found
No related merge requests found
import { FastifyPluginCallback } from "fastify";
import { FromSchema } from "json-schema-to-ts";
import { connection } from "./db";
// NOTE: see https://www.npmjs.com/package/fastify-plugin for TS plugin definition
const ParamsSchema = {
type: "object",
properties: {
id: {
type: "string",
format: "uuid",
},
},
required: ["id"],
} as const;
const GameSchema = {
type: "object",
properties: {
id: {
type: "string",
format: "uuid",
},
},
required: ["id"],
} as const;
const WordSchema = {
type: "object",
properties: {
id: { type: "string", format: "uuid" },
image: { type: "string" },
ocr_confidence: { type: "number", minimum: 0, maximum: 1 },
ocr_transcript: { type: "string" },
},
required: ["id"],
} as const;
const apiPlugin: FastifyPluginCallback = (fastify, options, next) => {
fastify.route<{
Reply: FromSchema<typeof WordSchema>;
}>({
method: "GET",
url: "/word",
schema: {
response: {
200: WordSchema,
404: {}, // TODO: JSend error
},
},
handler: async (request, reply) => {
// TODO: scope this to game to avoid collisions
const word = await connection<FromSchema<typeof WordSchema>>("words")
.whereBetween("ocr_confidence", [0.4, 0.8]) // i.e. needs improvement but it's not trash
.whereRaw(`"ocr_transcript" ~ '^[[:alpha:]]+$'`) // i.e. no numbers nor symbols
.orderByRaw("RANDOM()")
.first();
if (word === undefined) {
reply.code(404);
} else {
reply.send({
id: word.id,
image: word.image,
ocr_confidence: word.ocr_confidence,
ocr_transcript: word.ocr_transcript,
});
}
},
});
fastify.route<{
Params: FromSchema<typeof ParamsSchema>;
Reply: FromSchema<typeof GameSchema>;
}>({
method: "GET",
url: "/games/:id",
schema: {
params: ParamsSchema,
response: {
200: GameSchema,
404: {}, // TODO: JSend error
},
},
handler: async (request, reply) => {
const game = await connection<FromSchema<typeof GameSchema>>("games")
.where("id", request.params.id)
.first();
if (game === undefined) {
reply.code(404);
} else {
reply.send({
id: game.id,
});
}
},
});
next();
};
export default apiPlugin;
...@@ -48,6 +48,9 @@ server.get("/", function (request, reply) { ...@@ -48,6 +48,9 @@ server.get("/", function (request, reply) {
reply.code(200).send("Hello, World!"); reply.code(200).send("Hello, World!");
}); });
import apiRoutes from "./api";
server.register(apiRoutes, { prefix: "api" });
server.route({ server.route({
method: "POST", method: "POST",
url: "/GetImage", url: "/GetImage",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment