diff --git a/.gitignore b/.gitignore index 0bd76f7314ca5324fd2f069b133931dfb50ff437..639a1d1516df70e8ec18458061c95b49f76c1af6 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 0000000000000000000000000000000000000000..6c90c602b23d2eb99673dff8e799992649394af5 --- /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 0000000000000000000000000000000000000000..e1b4e4efc14e5a59fa4e060c8bdf35f2e3c891d3 --- /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 2f90d45bffa9087d15850cb426264dfd215d3529..26166845c73948d07721d74006e763f7fe9c76c6 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 a6512025143b70c128b77b92b2962ba61658e05f..c789ef8c0bd6170e640241e149735b7f30c746b3 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 c17b9e4379fdbf1493fc35d49f64b6226c186ecf..a4f61b1aadb41b8c4eb656754b62ecbed5c9f99b 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 ef5d833c37e65c1c485722c586178a26e0017376..36321a94cdbaa5d879a4ba75e1c4bc9e1a92956a 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) + + [](https://sc07.dev/fediverse.events/fediverse.events-api) + [](https://sc07.dev/fediverse.events/fediverse.events-api/-/wikis/home) + [](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 e3150b0a431012c92138ae88987f8352e676062f..fca5e0f424c891c2282f005dbb9fd6a6f42f1786 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 0000000000000000000000000000000000000000..4aa336402e78f84df899b86aead101522cfc9609 --- /dev/null +++ b/public/index.html @@ -0,0 +1,29 @@ + + +
+ + +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 f4ddda5634c4f1087a1216c1a84094503c0b8b7f..66ab448f03debcf829f5a4cdef177e8d682bf946 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!)); });