AeThex-OS/temp-forge-extract/aethex-forge-main/api/integrations/fourthwall.ts
MrPiglr b3c308b2c8 Add functional marketplace modules, bottom nav bar, root terminal, arcade games
- ModuleManager: Central tracking for installed marketplace modules
- DataAnalyzerWidget: Real-time CPU/RAM/Battery/Storage widget (unlocked by Data Analyzer module)
- BottomNavBar: Navigation bar for Projects/Chat/Marketplace/Settings
- RootShell: Real root command execution utility
- TerminalActivity: Full root shell with neofetch, sysinfo, real Linux commands
- Terminal Pro module: Adds aliases (ll, la, h), command history
- ArcadeActivity + SnakeGame: Pixel Arcade module unlocks retro games
- fade_in/fade_out animations for smooth transitions
2026-02-18 22:03:50 -07:00

333 lines
8.7 KiB
TypeScript

export const config = {
runtime: "nodejs",
};
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.VITE_SUPABASE_URL;
const supabaseServiceRole = process.env.SUPABASE_SERVICE_ROLE;
if (!supabaseUrl || !supabaseServiceRole) {
throw new Error("Missing Supabase configuration");
}
const supabase = createClient(supabaseUrl, supabaseServiceRole);
const FOURTHWALL_API_EMAIL = process.env.FOURTHWALL_API_EMAIL;
const FOURTHWALL_API_PASSWORD = process.env.FOURTHWALL_API_PASSWORD;
const FOURTHWALL_STOREFRONT_TOKEN = process.env.FOURTHWALL_STOREFRONT_TOKEN;
const FOURTHWALL_API_BASE = "https://api.fourthwall.com";
interface FourthwallAuthResponse {
token: string;
expires_in: number;
}
interface FourthwallProduct {
id: string;
name: string;
description: string;
price: number;
currency: string;
image_url?: string;
category: string;
}
// Get Fourthwall auth token
async function getFourthwallToken(): Promise<string> {
try {
const response = await fetch(`${FOURTHWALL_API_BASE}/auth/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: FOURTHWALL_API_EMAIL,
password: FOURTHWALL_API_PASSWORD,
}),
});
if (!response.ok) {
throw new Error(`Fourthwall auth failed: ${response.statusText}`);
}
const data = (await response.json()) as FourthwallAuthResponse;
return data.token;
} catch (error) {
console.error("[Fourthwall] Auth error:", error);
throw error;
}
}
export default async function handler(req: any, res: any) {
const action = req.query.action || "";
try {
switch (action) {
case "products":
return await handleGetProducts(req, res);
case "sync-products":
return await handleSyncProducts(req, res);
case "store-settings":
return await handleGetStoreSettings(req, res);
case "webhook":
return await handleWebhook(req, res);
default:
return res.status(400).json({ error: "Invalid action" });
}
} catch (error: any) {
console.error("[Fourthwall API] Error:", error);
return res.status(500).json({
error: error.message || "Internal server error",
});
}
}
// Get products from Fourthwall storefront
async function handleGetProducts(req: any, res: any) {
try {
const token = await getFourthwallToken();
const response = await fetch(
`${FOURTHWALL_API_BASE}/storefront/products?storefront_token=${FOURTHWALL_STOREFRONT_TOKEN}`,
{
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
},
);
if (!response.ok) {
throw new Error(`Failed to fetch products: ${response.statusText}`);
}
const data = (await response.json()) as { products?: unknown };
return res.status(200).json({
success: true,
products: data.products || [],
});
} catch (error: any) {
console.error("[Fourthwall] Get products error:", error);
return res.status(500).json({
error: error.message || "Failed to fetch products",
});
}
}
// Sync Fourthwall products to AeThex database
async function handleSyncProducts(req: any, res: any) {
try {
const token = await getFourthwallToken();
const response = await fetch(
`${FOURTHWALL_API_BASE}/storefront/products?storefront_token=${FOURTHWALL_STOREFRONT_TOKEN}`,
{
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
},
);
if (!response.ok) {
throw new Error(`Failed to fetch products: ${response.statusText}`);
}
const data = (await response.json()) as { products?: FourthwallProduct[] };
const products: FourthwallProduct[] = data.products || [];
// Sync products to Supabase
const syncResults = [];
for (const product of products) {
const { error } = await supabase.from("fourthwall_products").upsert(
{
fourthwall_id: product.id,
name: product.name,
description: product.description,
price: product.price,
currency: product.currency,
image_url: product.image_url,
category: product.category,
synced_at: new Date().toISOString(),
},
{
onConflict: "fourthwall_id",
},
);
syncResults.push({
product_id: product.id,
product_name: product.name,
success: !error,
error: error?.message,
});
}
return res.status(200).json({
success: true,
message: `Synced ${products.length} products`,
results: syncResults,
});
} catch (error: any) {
console.error("[Fourthwall] Sync products error:", error);
return res.status(500).json({
error: error.message || "Failed to sync products",
});
}
}
// Get store settings
async function handleGetStoreSettings(req: any, res: any) {
try {
const token = await getFourthwallToken();
const response = await fetch(`${FOURTHWALL_API_BASE}/store/settings`, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`Failed to fetch store settings: ${response.statusText}`);
}
const data = await response.json();
return res.status(200).json({
success: true,
settings: data,
});
} catch (error: any) {
console.error("[Fourthwall] Get settings error:", error);
return res.status(500).json({
error: error.message || "Failed to fetch store settings",
});
}
}
// Handle Fourthwall webhooks (order events, etc)
async function handleWebhook(req: any, res: any) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
try {
const { event_type, data } = req.body;
if (!event_type) {
return res.status(400).json({ error: "Missing event_type" });
}
// Log webhook event
const { error } = await supabase.from("fourthwall_webhook_logs").insert({
event_type,
payload: data,
received_at: new Date().toISOString(),
});
if (error) {
console.error("[Fourthwall] Webhook log error:", error);
}
// Handle specific events
switch (event_type) {
case "order.created":
await handleOrderCreated(data);
break;
case "order.paid":
await handleOrderPaid(data);
break;
case "product.updated":
await handleProductUpdated(data);
break;
}
return res.status(200).json({
success: true,
message: "Webhook processed",
});
} catch (error: any) {
console.error("[Fourthwall] Webhook error:", error);
return res.status(500).json({
error: error.message || "Failed to process webhook",
});
}
}
// Handle Fourthwall order created event
async function handleOrderCreated(data: any) {
try {
const { order_id, customer_email, items, total_amount } = data;
// Store order in database for later processing
const { error } = await supabase.from("fourthwall_orders").insert({
fourthwall_order_id: order_id,
customer_email,
items: items || [],
total_amount,
status: "pending",
created_at: new Date().toISOString(),
});
if (error) {
console.error("[Fourthwall] Failed to store order:", error);
}
console.log(`[Fourthwall] Order created: ${order_id}`);
} catch (error) {
console.error("[Fourthwall] Order creation error:", error);
}
}
// Handle Fourthwall order paid event
async function handleOrderPaid(data: any) {
try {
const { order_id } = data;
// Update order status
const { error } = await supabase
.from("fourthwall_orders")
.update({
status: "paid",
paid_at: new Date().toISOString(),
})
.eq("fourthwall_order_id", order_id);
if (error) {
console.error("[Fourthwall] Failed to update order:", error);
}
console.log(`[Fourthwall] Order paid: ${order_id}`);
} catch (error) {
console.error("[Fourthwall] Order payment error:", error);
}
}
// Handle Fourthwall product updated event
async function handleProductUpdated(data: any) {
try {
const { product_id, ...updates } = data;
// Update product in database
const { error } = await supabase
.from("fourthwall_products")
.update({
...updates,
synced_at: new Date().toISOString(),
})
.eq("fourthwall_id", product_id);
if (error) {
console.error("[Fourthwall] Failed to update product:", error);
}
console.log(`[Fourthwall] Product updated: ${product_id}`);
} catch (error) {
console.error("[Fourthwall] Product update error:", error);
}
}