/* ============================================================ GLASSGRID — API LAYER All data operations go through this layer. Zero UI modification. Returns structured data objects. Uses Schema for validation. ============================================================ */ 'use strict'; import { validate, applyDefaults } from '../data/schema.js'; const BASE_URL = '/api'; // Replace with your backend URL async function request(method, endpoint, body = null, headers = {}) { const token = localStorage.getItem('gg_auth_token'); const opts = { method, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...headers, }, ...(body ? { body: JSON.stringify(body) } : {}), }; const res = await fetch(`${BASE_URL}${endpoint}`, opts); if (!res.ok) { const err = await res.json().catch(() => ({ message: `HTTP ${res.status}` })); throw new Error(err.message || `Request failed: ${res.status}`); } return res.json(); } export const api = { // ── Auth ────────────────────────────── async login(identifier, password) { const data = await request('POST', '/auth/login', { identifier, password }); if (data.token) localStorage.setItem('gg_auth_token', data.token); return data; }, async logout() { localStorage.removeItem('gg_auth_token'); await request('POST', '/auth/logout').catch(() => {}); }, async register(username, email, password) { return request('POST', '/auth/register', { username, email, password }); }, async getCurrentUser() { return request('GET', '/auth/me'); }, // ── Posts ───────────────────────────── async getFeed(cursor = null, limit = 20) { const q = new URLSearchParams({ limit }); if (cursor) q.set('cursor', cursor); return request('GET', `/posts/feed?${q}`); }, async getExplorePosts(cursor = null, limit = 30) { const q = new URLSearchParams({ limit }); if (cursor) q.set('cursor', cursor); return request('GET', `/posts/explore?${q}`); }, async getPost(postId) { return request('GET', `/posts/${postId}`); }, async createPost(formData) { const token = localStorage.getItem('gg_auth_token'); const res = await fetch(`${BASE_URL}/posts`, { method: 'POST', headers: { ...(token ? { Authorization: `Bearer ${token}` } : {}) }, body: formData, // multipart/form-data for image upload }); if (!res.ok) throw new Error(`Upload failed: ${res.status}`); return res.json(); }, async deletePost(postId) { return request('DELETE', `/posts/${postId}`); }, // ── Likes ───────────────────────────── async likePost(postId) { return request('POST', `/posts/${postId}/like`); }, async unlikePost(postId) { return request('DELETE', `/posts/${postId}/like`); }, async likeComment(commentId) { return request('POST', `/comments/${commentId}/like`); }, // ── Comments ────────────────────────── async getComments(postId, cursor = null) { const q = new URLSearchParams({ limit: 20 }); if (cursor) q.set('cursor', cursor); return request('GET', `/posts/${postId}/comments?${q}`); }, async addComment(postId, text, parentId = null) { return request('POST', `/posts/${postId}/comments`, { text, parentId }); }, async deleteComment(commentId) { return request('DELETE', `/comments/${commentId}`); }, // ── Users ───────────────────────────── async getUser(username) { return request('GET', `/users/${username}`); }, async getUserPosts(userId, cursor = null) { const q = new URLSearchParams({ limit: 21 }); if (cursor) q.set('cursor', cursor); return request('GET', `/users/${userId}/posts?${q}`); }, async followUser(userId) { return request('POST', `/users/${userId}/follow`); }, async unfollowUser(userId) { return request('DELETE', `/users/${userId}/follow`); }, async updateProfile(data) { return request('PATCH', '/users/me', data); }, // ── Stories ─────────────────────────── async getStories() { return request('GET', '/stories'); }, async viewStory(storyId) { return request('POST', `/stories/${storyId}/view`); }, // ── Config (Admin) ──────────────────── async getConfig() { return request('GET', '/admin/config'); }, async updateConfig(config) { return request('PATCH', '/admin/config', config); }, async updateFeatureFlag(featureKey, enabled) { return request('PATCH', `/admin/features/${featureKey}`, { enabled }); }, // ── Moderation (Admin) ──────────────── async getModerationQueue() { return request('GET', '/admin/moderation'); }, async approvePost(postId) { return request('POST', `/admin/posts/${postId}/approve`); }, async removePost(postId, reason) { return request('DELETE', `/admin/posts/${postId}`, { reason }); }, async banUser(userId, reason) { return request('POST', `/admin/users/${userId}/ban`, { reason }); }, async unbanUser(userId) { return request('DELETE', `/admin/users/${userId}/ban`); }, };