completionId: cgen-19a49fcb88134d9f8c20fca743291e9e
cgen-19a49fcb88134d9f8c20fca743291e9e
This commit is contained in:
parent
3710b02a8e
commit
a355f2c9fd
1 changed files with 83 additions and 105 deletions
188
server/index.ts
188
server/index.ts
|
|
@ -353,123 +353,101 @@ export function createServer() {
|
|||
next();
|
||||
});
|
||||
|
||||
// Subdomain Passport Handler - serves the React app with pre-fetched data
|
||||
app.use(async (req, res, next) => {
|
||||
const subdomainInfo = (req as any).subdomainInfo;
|
||||
|
||||
// Only handle root path for subdomains
|
||||
if (!subdomainInfo.domain || req.path !== "/") {
|
||||
return next();
|
||||
}
|
||||
|
||||
// Subdomain Passport Data API - returns JSON for the React component to use
|
||||
app.get("/api/passport/subdomain-data/:username", async (req, res) => {
|
||||
try {
|
||||
let passportData: any = null;
|
||||
const username = String(req.params.username || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
|
||||
// Creator Passport (aethex.me)
|
||||
if (subdomainInfo.isCreatorPassport) {
|
||||
console.log(
|
||||
"[Passport Handler] Fetching creator:",
|
||||
subdomainInfo.subdomain,
|
||||
);
|
||||
const { data: user, error } = await adminSupabase
|
||||
.from("user_profiles")
|
||||
.select(
|
||||
"id, username, full_name, bio, avatar_url, banner_url, location, website_url, github_url, linkedin_url, twitter_url, role, level, total_xp, user_type, experience_level, current_streak, longest_streak, created_at, updated_at",
|
||||
)
|
||||
.eq("username", subdomainInfo.subdomain)
|
||||
.single();
|
||||
|
||||
if (error || !user) {
|
||||
console.log("[Passport Handler] Creator not found");
|
||||
return next(); // Fall through to 404
|
||||
}
|
||||
|
||||
// Fetch achievements
|
||||
const { data: achievements = [] } = await adminSupabase
|
||||
.from("user_achievements")
|
||||
.select(
|
||||
`
|
||||
achievement_id,
|
||||
achievements(
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
category,
|
||||
badge_color
|
||||
)
|
||||
`,
|
||||
)
|
||||
.eq("user_id", user.id);
|
||||
|
||||
passportData = {
|
||||
type: "creator",
|
||||
user,
|
||||
achievements: achievements
|
||||
.map((a: any) => a.achievements)
|
||||
.filter(Boolean),
|
||||
domain: "aethex.me",
|
||||
};
|
||||
if (!username) {
|
||||
return res.status(400).json({ error: "username required" });
|
||||
}
|
||||
|
||||
// Project Passport (aethex.space)
|
||||
if (subdomainInfo.isProjectPassport) {
|
||||
console.log(
|
||||
"[Passport Handler] Fetching project:",
|
||||
subdomainInfo.subdomain,
|
||||
);
|
||||
const { data: project, error } = await adminSupabase
|
||||
.from("projects")
|
||||
.select(
|
||||
"id, slug, name, description, logo_url, banner_url, website_url, github_url, team_size, created_at, updated_at",
|
||||
console.log("[Passport Data API] Fetching creator:", username);
|
||||
|
||||
const { data: user, error } = await adminSupabase
|
||||
.from("user_profiles")
|
||||
.select(
|
||||
"id, username, full_name, bio, avatar_url, banner_url, location, website_url, github_url, linkedin_url, twitter_url, role, level, total_xp, user_type, experience_level, current_streak, longest_streak, created_at, updated_at",
|
||||
)
|
||||
.eq("username", username)
|
||||
.single();
|
||||
|
||||
if (error || !user) {
|
||||
console.log("[Passport Data API] Creator not found:", username);
|
||||
return res.status(404).json({ error: "Creator not found", username });
|
||||
}
|
||||
|
||||
// Fetch achievements
|
||||
const { data: achievements = [] } = await adminSupabase
|
||||
.from("user_achievements")
|
||||
.select(
|
||||
`
|
||||
achievement_id,
|
||||
achievements(
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
category,
|
||||
badge_color
|
||||
)
|
||||
.eq("slug", subdomainInfo.subdomain)
|
||||
.single();
|
||||
`,
|
||||
)
|
||||
.eq("user_id", user.id);
|
||||
|
||||
if (error || !project) {
|
||||
console.log("[Passport Handler] Project not found");
|
||||
return next(); // Fall through to 404
|
||||
}
|
||||
return res.json({
|
||||
type: "creator",
|
||||
user,
|
||||
achievements: achievements
|
||||
.map((a: any) => a.achievements)
|
||||
.filter(Boolean),
|
||||
domain: "aethex.me",
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.error("[Passport Data API] Error:", e?.message);
|
||||
return res.status(500).json({
|
||||
error: e?.message || "Failed to fetch creator passport",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
passportData = {
|
||||
type: "group",
|
||||
group: project,
|
||||
domain: "aethex.space",
|
||||
};
|
||||
app.get("/api/passport/project-data/:projectSlug", async (req, res) => {
|
||||
try {
|
||||
const projectSlug = String(req.params.projectSlug || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
|
||||
if (!projectSlug) {
|
||||
return res.status(400).json({ error: "projectSlug required" });
|
||||
}
|
||||
|
||||
// If we found passport data, inject it into the page
|
||||
if (passportData) {
|
||||
console.log("[Passport Handler] Serving passport with pre-fetched data");
|
||||
// The React app will receive this data via window.__PASSPORT_DATA__
|
||||
const dataJson = JSON.stringify(passportData)
|
||||
.replace(/</g, "\\u003c")
|
||||
.replace(/>/g, "\\u003e");
|
||||
console.log("[Passport Data API] Fetching project:", projectSlug);
|
||||
|
||||
res.set("Content-Type", "text/html; charset=utf-8");
|
||||
res.send(`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>AeThex Passport</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
window.__PASSPORT_DATA__ = ${dataJson};
|
||||
</script>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>`);
|
||||
return;
|
||||
const { data: project, error } = await adminSupabase
|
||||
.from("projects")
|
||||
.select(
|
||||
"id, slug, name, description, logo_url, banner_url, website_url, github_url, team_size, created_at, updated_at",
|
||||
)
|
||||
.eq("slug", projectSlug)
|
||||
.single();
|
||||
|
||||
if (error || !project) {
|
||||
console.log("[Passport Data API] Project not found:", projectSlug);
|
||||
return res.status(404).json({ error: "Project not found", projectSlug });
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error: any) {
|
||||
console.error("[Passport Handler] Error:", error?.message);
|
||||
next();
|
||||
return res.json({
|
||||
type: "group",
|
||||
group: project,
|
||||
domain: "aethex.space",
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.error("[Passport Data API] Error:", e?.message);
|
||||
return res.status(500).json({
|
||||
error: e?.message || "Failed to fetch project passport",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue