mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-18 14:27:20 +00:00
- 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
333 lines
8.7 KiB
TypeScript
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);
|
|
}
|
|
}
|