Fix: Use standard Vercel serverless function format (req, res)

Response.json() is for Edge Functions, not Node.js serverless functions.
Switched all API handlers to use res.status().json() format which is
the standard for Vercel Node.js functions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2025-12-16 15:00:08 -08:00
co-authored by Claude Opus 4.5
parent 13f4714b5d
commit 73a3367e0a
5 changed files with 128 additions and 35 deletions
+3 -8
View File
@@ -6,17 +6,12 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = join(__dirname, "..");
export default function handler(request) {
export default function handler(req, res) {
try {
const sourceDir = join(PROJECT_ROOT, "source");
const commandsDir = join(sourceDir, "commands");
console.log("PROJECT_ROOT:", PROJECT_ROOT);
console.log("commandsDir:", commandsDir);
const files = readdirSync(commandsDir);
console.log("Files found:", files.length);
const commands = [];
for (const file of files) {
@@ -38,10 +33,10 @@ export default function handler(request) {
}
}
return Response.json(commands);
res.status(200).json(commands);
} catch (error) {
console.error("Error in /api/commands:", error);
return Response.json({ error: error.message, stack: error.stack }, { status: 500 });
res.status(500).json({ error: error.message, stack: error.stack });
}
}
+59 -9
View File
@@ -1,14 +1,64 @@
import { handleFileDownload } from "../../../server/lib/api-handlers.js";
import { readFileSync, existsSync } from "fs";
import { join, dirname, basename } from "path";
import { fileURLToPath } from "url";
export default async function handler(request) {
const url = new URL(request.url);
const pathParts = url.pathname.split('/').filter(Boolean);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = join(__dirname, "../../../..");
// Extract params from path: /api/download/[type]/[provider]/[id]
const type = pathParts[2]; // after 'api', 'download'
const provider = pathParts[3];
const id = pathParts[4];
function getFilePath(type, provider, id) {
const distDir = join(PROJECT_ROOT, "dist");
return handleFileDownload(type, provider, id);
if (type === "skill") {
if (provider === "cursor") {
return join(distDir, "cursor", ".cursor", "rules", `${id}.md`);
} else if (provider === "claude-code") {
return join(distDir, "claude-code", ".claude", "skills", id, "SKILL.md");
} else if (provider === "gemini") {
return join(distDir, "gemini", `GEMINI.${id}.md`);
} else if (provider === "codex") {
return join(distDir, "codex", `AGENTS.${id}.md`);
}
} else if (type === "command") {
if (provider === "cursor") {
return join(distDir, "cursor", ".cursor", "commands", `${id}.md`);
} else if (provider === "claude-code") {
return join(distDir, "claude-code", ".claude", "commands", `${id}.md`);
} else if (provider === "gemini") {
return join(distDir, "gemini", ".gemini", "commands", `${id}.toml`);
} else if (provider === "codex") {
return join(distDir, "codex", ".codex", "prompts", `${id}.md`);
}
}
return null;
}
export default function handler(req, res) {
try {
const { type, provider, id } = req.query;
if (type !== "skill" && type !== "command") {
return res.status(400).json({ error: "Invalid type" });
}
const filePath = getFilePath(type, provider, id);
if (!filePath) {
return res.status(400).json({ error: "Invalid provider" });
}
if (!existsSync(filePath)) {
return res.status(404).json({ error: "File not found" });
}
const content = readFileSync(filePath);
const fileName = basename(filePath);
res.setHeader("Content-Type", "application/octet-stream");
res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
res.send(content);
} catch (error) {
console.error("Error downloading file:", error);
res.status(500).json({ error: error.message });
}
}
+23 -7
View File
@@ -1,12 +1,28 @@
import { handleBundleDownload } from "../../../server/lib/api-handlers.js";
import { readFileSync, existsSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
export default async function handler(request) {
const url = new URL(request.url);
const pathParts = url.pathname.split('/').filter(Boolean);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = join(__dirname, "../../..");
// Extract provider from path: /api/download/bundle/[provider]
const provider = pathParts[3]; // after 'api', 'download', 'bundle'
export default function handler(req, res) {
try {
const { provider } = req.query;
const distDir = join(PROJECT_ROOT, "dist");
const zipPath = join(distDir, `${provider}.zip`);
return handleBundleDownload(provider);
if (!existsSync(zipPath)) {
return res.status(404).json({ error: "Bundle not found" });
}
const content = readFileSync(zipPath);
res.setHeader("Content-Type", "application/zip");
res.setHeader("Content-Disposition", `attachment; filename="impeccable-style-${provider}.zip"`);
res.send(content);
} catch (error) {
console.error("Error downloading bundle:", error);
res.status(500).json({ error: error.message });
}
}
+4 -7
View File
@@ -6,19 +6,16 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = join(__dirname, "..");
export default function handler(request) {
export default function handler(req, res) {
try {
const sourceDir = join(PROJECT_ROOT, "source");
const filePath = join(sourceDir, "patterns.md");
console.log("Reading patterns from:", filePath);
const content = readFileSync(filePath, "utf-8");
console.log("File read, length:", content.length);
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
if (!frontmatterMatch) {
return Response.json({ patterns: [], antipatterns: [] });
return res.status(200).json({ patterns: [], antipatterns: [] });
}
const frontmatterText = frontmatterMatch[1];
@@ -69,9 +66,9 @@ export default function handler(request) {
}
}
return Response.json({ patterns, antipatterns });
res.status(200).json({ patterns, antipatterns });
} catch (error) {
console.error("Error in /api/patterns:", error);
return Response.json({ error: error.message, stack: error.stack }, { status: 500 });
res.status(500).json({ error: error.message, stack: error.stack });
}
}
+39 -4
View File
@@ -1,7 +1,42 @@
import { getSkills } from "../server/lib/api-handlers.js";
import { readdirSync, readFileSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
export default async function handler(request) {
const skills = await getSkills();
return Response.json(skills);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = join(__dirname, "..");
export default function handler(req, res) {
try {
const sourceDir = join(PROJECT_ROOT, "source");
const skillsDir = join(sourceDir, "skills");
const files = readdirSync(skillsDir);
const skills = [];
for (const file of files) {
if (file.endsWith(".md")) {
const content = readFileSync(join(skillsDir, file), "utf-8");
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
if (frontmatterMatch) {
const frontmatter = frontmatterMatch[1];
const nameMatch = frontmatter.match(/name:\s*(.+)/);
const descMatch = frontmatter.match(/description:\s*(.+)/);
skills.push({
id: file.replace(".md", ""),
name: nameMatch?.[1]?.trim() || file.replace(".md", ""),
description: descMatch?.[1]?.trim() || "No description available",
});
}
}
}
res.status(200).json(skills);
} catch (error) {
console.error("Error in /api/skills:", error);
res.status(500).json({ error: error.message });
}
}