11/* eslint import/no-nodejs-modules: ["error", {"allow": ["crypto"]}] */
2+ import "zod-openapi/extend";
23import { randomUUID } from "crypto";
34import fastify, { FastifyInstance } from "fastify";
45import FastifyAuthProvider from "@fastify/auth";
@@ -10,9 +11,9 @@ import { RunEnvironment, runEnvironments } from "../common/roles.js";
1011import { InternalServerError } from "../common/errors/index.js";
1112import eventsPlugin from "./routes/events.js";
1213import cors from "@fastify/cors";
13- import fastifyZodValidationPlugin from "./plugins/validate.js";
1414import { environmentConfig, genericConfig } from "../common/config.js";
1515import organizationsPlugin from "./routes/organizations.js";
16+ import authorizeFromSchemaPlugin from "./plugins/authorizeFromSchema.js";
1617import icalPlugin from "./routes/ics.js";
1718import vendingPlugin from "./routes/vending.js";
1819import * as dotenv from "dotenv";
@@ -29,6 +30,17 @@ import membershipPlugin from "./routes/membership.js";
2930import path from "path"; // eslint-disable-line import/no-nodejs-modules
3031import roomRequestRoutes from "./routes/roomRequests.js";
3132import logsPlugin from "./routes/logs.js";
33+ import fastifySwagger from "@fastify/swagger";
34+ import fastifySwaggerUI from "@fastify/swagger-ui";
35+ import {
36+   fastifyZodOpenApiPlugin,
37+   fastifyZodOpenApiTransform,
38+   fastifyZodOpenApiTransformObject,
39+   serializerCompiler,
40+   validatorCompiler,
41+ } from "fastify-zod-openapi";
42+ import { ZodOpenApiVersion } from "zod-openapi";
43+ import { withTags } from "./components/index.js";
3244
3345dotenv.config();
3446
@@ -81,10 +93,68 @@ async function init(prettyPrint: boolean = false) {
8193      return event.requestContext.requestId;
8294    },
8395  });
96+   app.setValidatorCompiler(validatorCompiler);
97+   app.setSerializerCompiler(serializerCompiler);
98+   await app.register(authorizeFromSchemaPlugin);
8499  await app.register(fastifyAuthPlugin);
85-   await app.register(fastifyZodValidationPlugin);
86100  await app.register(FastifyAuthProvider);
87101  await app.register(errorHandlerPlugin);
102+   await app.register(fastifyZodOpenApiPlugin);
103+   await app.register(fastifySwagger, {
104+     openapi: {
105+       info: {
106+         title: "ACM @ UIUC Core API",
107+         description: "ACM @ UIUC Core Management Platform",
108+         version: "1.0.0",
109+       },
110+       servers: [
111+         app.runEnvironment === "prod"
112+           ? {
113+               url: "https://core.acm.illinois.edu",
114+               description: "Production API server",
115+             }
116+           : {
117+               url: "https://core.aws.qa.acmuiuc.org",
118+               description: "QA API server",
119+             },
120+       ],
121+       tags: [
122+         {
123+           name: "Events",
124+           description:
125+             "Retrieve ACM @ UIUC-wide and organization-specific calendars and event metadata.",
126+         },
127+         {
128+           name: "Generic",
129+           description: "Retrieve metadata about a user or ACM @ UIUC .",
130+         },
131+         {
132+           name: "iCalendar Integration",
133+           description:
134+             "Retrieve Events calendars in iCalendar format (for integration with external calendar clients).",
135+         },
136+         {
137+           name: "IAM",
138+           description: "Identity and Access Management for internal services.",
139+         },
140+         { name: "Linkry", description: "Link Shortener." },
141+         {
142+           name: "Logging",
143+           description: "View audit logs for various services.",
144+         },
145+         {
146+           name: "Membership",
147+           description: "Purchasing or checking ACM @ UIUC membership.",
148+         },
149+       ],
150+       openapi: "3.0.3" satisfies ZodOpenApiVersion, // If this is not specified, it will default to 3.1.0
151+     },
152+     transform: fastifyZodOpenApiTransform,
153+     transformObject: fastifyZodOpenApiTransformObject,
154+   });
155+   await app.register(fastifySwaggerUI, {
156+     routePrefix: "/api/documentation",
157+   });
88158  await app.register(fastifyStatic, {
89159    root: path.join(__dirname, "public"),
90160    prefix: "/",
@@ -122,7 +192,11 @@ async function init(prettyPrint: boolean = false) {
122192    );
123193    done();
124194  });
125-   app.get("/api/v1/healthz", (_, reply) => reply.send({ message: "UP" }));
195+   app.get(
196+     "/api/v1/healthz",
197+     { schema: withTags(["Generic"], {}) },
198+     (_, reply) => reply.send({ message: "UP" }),
199+   );
126200  await app.register(
127201    async (api, _options) => {
128202      api.register(protectedRoute, { prefix: "/protected" });
0 commit comments