Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/build/plugins/route-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export async function routeMeta(nitro: Nitro) {
return {
name: "nitro:route-meta",
resolveId: {
order: "pre",
// eslint-disable-next-line no-control-regex
filter: { id: /^(?!\u0000)(.+)\?meta$/ },
async handler(id, importer, resolveOpts) {
Expand All @@ -25,6 +26,7 @@ export async function routeMeta(nitro: Nitro) {
},
},
load: {
order: "pre",
filter: {
id: new RegExp(`^${escapeRegExp(PREFIX)}`),
},
Expand All @@ -40,6 +42,7 @@ export async function routeMeta(nitro: Nitro) {
},
},
transform: {
order: "pre",
filter: {
id: new RegExp(`^${escapeRegExp(PREFIX)}`),
},
Expand Down
14 changes: 14 additions & 0 deletions test/vite/openapi-fixture/api/meta/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineRouteMeta } from "nitro";

defineRouteMeta({
openAPI: {
tags: ["test"],
description: "Vite builder route description",
parameters: [{ in: "query", name: "vite-test", required: true }],
responses: {
200: { description: "result" },
},
},
});

export default () => ({ status: "OK" });
17 changes: 17 additions & 0 deletions test/vite/openapi-fixture/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from "vite";
import { nitro } from "nitro/vite";

export default defineConfig({
plugins: [
nitro({
serverDir: "./",
experimental: { openAPI: true },
openAPI: {
meta: {
title: "OpenAPI Test API",
description: "OpenAPI Test Description",
},
},
}),
],
});
59 changes: 59 additions & 0 deletions test/vite/openapi.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { fileURLToPath } from "node:url";
import type { ViteDevServer } from "vite";
import { describe, test, expect, beforeAll, afterAll } from "vitest";

const { createServer } = (await import(
process.env.NITRO_VITE_PKG || "vite"
)) as typeof import("vite");

describe("openapi", () => {
let server: ViteDevServer;
let serverURL: string;

const rootDir = fileURLToPath(new URL("./openapi-fixture", import.meta.url));

beforeAll(async () => {
server = await createServer({ root: rootDir });
await server.listen("0" as unknown as number);
const addr = server.httpServer?.address() as {
port: number;
address: string;
family: string;
};
serverURL = `http://${addr.family === "IPv6" ? `[${addr.address}]` : addr.address}:${addr.port}`;
Comment thread
kyjus25 marked this conversation as resolved.
}, 30_000);

afterAll(async () => {
await server?.close();
});

test("extracts defineRouteMeta", async () => {
const res = await fetch(`${serverURL}/_openapi.json`);
const spec: Record<string, any> = await res.json();

expect(spec.openapi).toMatch(/^3\.\d+\.\d+$/);
expect(spec.paths?.["/api/meta/test"]).toBeDefined();
expect(spec.paths["/api/meta/test"].get.description).toBe("Vite builder route description");
expect(spec.paths["/api/meta/test"].get.tags).toEqual(["test"]);

const routeRes = await fetch(`${serverURL}/api/meta/test`);
expect(routeRes.status).toBe(200);
expect(await routeRes.json()).toEqual({ status: "OK" });
});

test("serves swagger UI with meta", async () => {
const res = await fetch(`${serverURL}/_swagger`);
expect(res.status).toBe(200);
const html = await res.text();
expect(html).toContain("<title>OpenAPI Test API</title>");
expect(html).toContain('<meta name="description" content="OpenAPI Test Description"');
});

test("serves scalar UI with meta", async () => {
const res = await fetch(`${serverURL}/_scalar`);
expect(res.status).toBe(200);
const html = await res.text();
expect(html).toContain("<title>OpenAPI Test API</title>");
expect(html).toContain('<meta name="description" content="OpenAPI Test Description"');
});
});