From d42fb44a0a813147fd2e9a8c10759186fb925bf3 Mon Sep 17 00:00:00 2001 From: Grant Date: Sun, 19 Apr 2026 00:27:19 -0600 Subject: [PATCH] add homepage for api + redocly --- .gitignore | 3 ++- .vscode/extensions.json | 8 ++++++++ .vscode/settings.json | 9 +++++++++ Dockerfile | 2 ++ bun.lock | 1 + docker-compose.yml | 1 + openapi/spec.yml | 8 ++++++++ package.json | 2 +- public/index.html | 29 +++++++++++++++++++++++++++++ src/index.ts | 14 ++++++-------- 10 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 public/index.html diff --git a/.gitignore b/.gitignore index 0bd76f7..639a1d1 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json # dynamicly generated files src/types/openapi.d.ts /src/generated/prisma -/data \ No newline at end of file +/data +/public/docs.html \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..6c90c60 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "redhat.vscode-yaml", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "prisma.prisma" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e1b4e4e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "yaml.schemas": { + "https://raw.githubusercontent.com/docker/vscode-extension/6a88caada42b57090df7ce91ec2a6561b422afe1/misc/empty.json": [ + "compose*y*ml", + "docker-compose*y*ml" + ], + "https://www.schemastore.org/openapi-3.X.json": "/openapi/spec.yml" + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2f90d45..2616684 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,7 @@ RUN bunx prisma generate RUN bun run dev:api-ts ARG VERSION RUN bun run build +RUN bun run build:api-doc # copy production dependencies and source code into final image FROM base AS release @@ -35,6 +36,7 @@ COPY --from=install /temp/prod/node_modules node_modules COPY prisma ./prisma COPY --from=prerelease /usr/src/app/src/demo-data/events.json ./src/demo-data/events.json COPY --from=prerelease /usr/src/app/src/generated ./src/generated +COPY --from=prerelease /usr/src/app/public ./public COPY --from=prerelease /usr/src/app/dist ./dist COPY --from=prerelease /usr/src/app/package.json . diff --git a/bun.lock b/bun.lock index a651202..c789ef8 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "fediverse.events-api", diff --git a/docker-compose.yml b/docker-compose.yml index c17b9e4..a4f61b1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,7 @@ services: - "3001:3000" environment: - DATABASE_URL=postgres://postgres@postgres:5432/fedievents-api + - PORT=3000 env_file: - .env depends_on: diff --git a/openapi/spec.yml b/openapi/spec.yml index ef5d833..36321a9 100644 --- a/openapi/spec.yml +++ b/openapi/spec.yml @@ -2,6 +2,12 @@ openapi: "3.1.1" info: title: Fediverse Events API version: "0.0.1" + description: | + This API provides metadata information for the events hosted by [fediverse.events](https://fediverse.events) + + [![Source](https://img.shields.io/badge/sc07.dev-source-blue?logo=git)](https://sc07.dev/fediverse.events/fediverse.events-api) + [![Wiki](https://img.shields.io/badge/sc07.dev-wiki-blue?logo=gitlab)](https://sc07.dev/fediverse.events/fediverse.events-api/-/wikis/home) + [![Matrix](https://img.shields.io/matrix/fediverse-app-devs%3Aaftermath.gg?server_fqdn=aftermath.gg)](https://matrix.to/#/#fediverse-app-devs:aftermath.gg?via=matrix.org) license: name: MIT identifier: MIT @@ -9,6 +15,8 @@ info: servers: - url: https://api.fediverse.events/v1 description: Production + - url: https://test-api.fediverse.events/v1 + description: Testing # default: no authentication security: [] diff --git a/package.json b/package.json index e3150b0..fca5e0f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dev": "bun run --define process.env.VERSION=\"'$(git rev-parse HEAD)'\" --hot src/index.ts", "build": "bun build src/index.ts --outdir ./dist --target=bun --sourcemap=inline --minify --packages=external --define process.env.VERSION=\"'$(if [ -v VERSION ]; then echo \"$VERSION\"; else git rev-parse HEAD; fi)'\"", "bundle:api-doc": "redocly bundle openapi/spec.yml -o openapi/openapi.yaml && sed -i '1s/^/# AUTOGENERATED FILE\\n# Run bun run bundle:api-doc\\n/' openapi/openapi.yaml", - "build:api-doc": "redocly build-docs openapi/spec.yml -o public/index.html --title \"Fediverse Events API\"", + "build:api-doc": "redocly build-docs openapi/spec.yml -o public/docs.html --title \"Fediverse Events API\"", "dev:api-doc": "redocly preview-docs openapi/spec.yml", "dev:api-ts": "openapi-typescript openapi/spec.yml -o src/types/openapi.d.ts" } diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..4aa3364 --- /dev/null +++ b/public/index.html @@ -0,0 +1,29 @@ + + + + + + fediverse.events API + + + +

fediverse.events API

+

This API provides metadata information for the events hosted by fediverse.events

+ + + \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index f4ddda5..66ab448 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ import type { } from "./generated/prisma"; import type { InputJsonValue } from "@prisma/client/runtime/library"; import type { paths } from "./types/openapi"; +import path from "path"; if (process.env.DEMO_MODE) { DemoDataManager.get().initialize(); @@ -27,6 +28,7 @@ HandoffProvider.get() }); const app = express(); +app.use(express.static(path.join(__dirname, "../public"))); app.use(cors()); app.get("/favicon.ico", (req, res) => { @@ -50,10 +52,6 @@ app.get("/metrics", async (req, res) => { }); app.use(promBundle({ autoregister: false, includePath: true })); -app.get("/", (req, res) => { - res.send("fediverse.events-api"); -}); - app.get("/_internal/sync", async (req, res) => { if ( !process.env.ADMIN_TOKEN || @@ -156,7 +154,7 @@ app.use("/v1", v1 as any); v1.get("/calendar.ics", (async ( req: express.Request, - res: express.Response + res: express.Response, ) => { const events = await Event.query({}); const rendered = ics.createEvents(events.map((e) => e.toICS())); @@ -164,7 +162,7 @@ v1.get("/calendar.ics", (async ( // cache for 24 hours res.setHeader( "Cache-Control", - `public, max-age=${60 * 60 * 24}, must-revalidate` + `public, max-age=${60 * 60 * 24}, must-revalidate`, ); res.contentType("text/calendar").send(Buffer.from(rendered.value!)); }) as any); @@ -215,7 +213,7 @@ v1.get("/events", async (req, res) => { // cache for 24 hours res.setHeader( "Cache-Control", - `public, max-age=${60 * 60 * 24}, must-revalidate` + `public, max-age=${60 * 60 * 24}, must-revalidate`, ); res.json({ events: events.map((e) => e.toJSON()), @@ -234,7 +232,7 @@ v1.get("/events/{id}.ics", async (req, res: express.Response) => { // cache for 24 hours res.setHeader( "Cache-Control", - `public, max-age=${60 * 60 * 24}, must-revalidate` + `public, max-age=${60 * 60 * 24}, must-revalidate`, ); res.contentType("text/calendar").send(Buffer.from(rendered.value!)); }); -- GitLab