Skip to content

Commit 48c55a4

Browse files
committed
feat: add emoji versions API endpoint and error handling
1 parent f63ab67 commit 48c55a4

File tree

5 files changed

+83
-14
lines changed

5 files changed

+83
-14
lines changed

src/index.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ import { OpenAPIHono } from "@hono/zod-openapi";
44
import { apiReference } from "@scalar/hono-api-reference";
55
import { env } from "hono/adapter";
66
import { HTTPException } from "hono/http-exception";
7+
import { VERSIONS_ROUTER } from "./routes/versions";
78

89
const app = new OpenAPIHono<HonoContext>();
910

10-
app.get("/", async (c) => {
11-
return c.json({
12-
message: "Hello, World!",
13-
});
14-
});
11+
app.route("/api/v1", VERSIONS_ROUTER);
1512

1613
app.get(
1714
"/scalar",
@@ -21,15 +18,6 @@ app.get(
2118
},
2219
layout: "classic",
2320
customCss: /* css */`
24-
.section.introduction-section {
25-
padding: 16px 0 !important;
26-
}
27-
28-
.section-container {
29-
border: none !important;
30-
padding: 0 !important;
31-
}
32-
3321
.tag-section {
3422
padding: 0 !important;
3523
}

src/routes/versions.openapi.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { createRoute, z } from "@hono/zod-openapi";
2+
import { ApiErrorSchema, EmojiVersion } from "../schemas";
3+
4+
export const ALL_EMOJI_VERSIONS_ROUTE = createRoute({
5+
method: "get",
6+
path: "/versions",
7+
tags: ["Misc"],
8+
responses: {
9+
200: {
10+
content: {
11+
"application/json": {
12+
schema: z.array(EmojiVersion),
13+
},
14+
},
15+
description: "Retrieve a list of all emoji versions available",
16+
},
17+
500: {
18+
content: {
19+
"application/json": {
20+
schema: ApiErrorSchema,
21+
},
22+
},
23+
description: "Internal Server Error",
24+
},
25+
},
26+
});

src/routes/versions.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { HonoContext } from "../types";
2+
import { OpenAPIHono, z } from "@hono/zod-openapi";
3+
import { createError } from "../utils";
4+
import { ALL_EMOJI_VERSIONS_ROUTE } from "./versions.openapi";
5+
6+
export const VERSIONS_ROUTER = new OpenAPIHono<HonoContext>();
7+
8+
const EMOJI_LOCK_SCHEMA = z.object({
9+
versions: z.array(z.string()),
10+
});
11+
12+
VERSIONS_ROUTER.openapi(ALL_EMOJI_VERSIONS_ROUTE, async (c) => {
13+
const res = await fetch("https://raw.githubusercontent.com/mojisdev/emoji-data/refs/heads/main/emojis.lock");
14+
15+
if (!res.ok) {
16+
return createError(c, 500, "failed to fetch emoji data");
17+
}
18+
19+
const data = await res.json();
20+
21+
const result = EMOJI_LOCK_SCHEMA.safeParse(data);
22+
23+
if (!result.success) {
24+
return createError(c, 500, "invalid emoji data schema");
25+
}
26+
27+
return c.json(
28+
result.data.versions.map((version: string) => ({
29+
version,
30+
})),
31+
200,
32+
);
33+
});

src/schemas.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { z } from "@hono/zod-openapi";
22

3+
export const EmojiVersion = z.object({
4+
version: z.string().openapi({
5+
description: "The emoji version",
6+
example: "16.0",
7+
}),
8+
});
9+
310
export const ApiErrorSchema = z.object({
411
path: z.string().openapi({
512
description: "The path of the request",

src/utils.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { Context } from "hono";
2+
import type { ContentfulStatusCode } from "hono/utils/http-status";
3+
import type { ApiError } from "./schemas";
4+
5+
export function createError<TCtx extends Context, TStatus extends ContentfulStatusCode>(ctx: TCtx, status: TStatus, message: string) {
6+
const url = new URL(ctx.req.url);
7+
return ctx.json({
8+
path: url.pathname,
9+
message,
10+
status,
11+
timestamp: new Date().toISOString(),
12+
} satisfies ApiError, status, {
13+
"Content-Type": "application/json",
14+
});
15+
}

0 commit comments

Comments
 (0)