mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
feat(analytics): Implement Analytics Dashboard and Token Management
This commit is contained in:
1 parent
b38f082d6e
commit
f8ddb44e38
822 files changed
+132545
-51
No files matched your search
@@ -0,0 +1,94 @@
|
||||
|
||||
|
||||
export class FacebookApiError extends Error {
|
||||
constructor(
|
||||
public message: string,
|
||||
public status: number,
|
||||
public code: number,
|
||||
public fbTraceId: string
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'FacebookApiError';
|
||||
}
|
||||
}
|
||||
|
||||
interface GraphRequestConfig {
|
||||
params?: Record<string, string | number | boolean>;
|
||||
accessToken?: string;
|
||||
}
|
||||
|
||||
const GRAPH_API_VERSION = 'v19.0';
|
||||
const BASE_URL = `https://graph.facebook.com/${GRAPH_API_VERSION}`;
|
||||
|
||||
export class GraphAPIClient {
|
||||
|
||||
static async get<T>(endpoint: string, config: GraphRequestConfig): Promise<T> {
|
||||
const url = this.buildUrl(endpoint, config);
|
||||
console.log(`[GraphAPI] GET ${endpoint}`);
|
||||
|
||||
// In node-fetch v2 (which is typically used in CJS/TS mixes unless v3 ESM), basic fetch
|
||||
// If project uses v3, imports might differ. Assuming standard fetch is available or polyfilled.
|
||||
// socialflow package.json has "@types/node-fetch": "^2.6.13" but also "node-fetch" isn't explicitly in dependencies?
|
||||
// Wait, package.json has "node-fetch" missing in dependencies list!
|
||||
// But it has "@types/node-fetch".
|
||||
// "canvas" is there. "express" is there.
|
||||
// I need to check if fetch is globally available (Node 18+) or if I need to use `axios` or add `node-fetch`.
|
||||
// Package.json has: "type": "module". Node 20.16.11 is used in parsing.
|
||||
// Node 18+ has native fetch. I should use `global.fetch` or just `fetch`.
|
||||
// Explicit import `import fetch from 'node-fetch'` might fail if not installed.
|
||||
// I will use native fetch.
|
||||
|
||||
// Remove import above if using native.
|
||||
|
||||
const response = await fetch(url.toString());
|
||||
return this.handleResponse<T>(response);
|
||||
}
|
||||
|
||||
static async post<T>(endpoint: string, body: any, config: GraphRequestConfig): Promise<T> {
|
||||
const url = this.buildUrl(endpoint, config);
|
||||
console.log(`[GraphAPI] POST ${endpoint}`);
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
return this.handleResponse<T>(response);
|
||||
}
|
||||
|
||||
private static buildUrl(endpoint: string, config: GraphRequestConfig): URL {
|
||||
const url = new URL(`${BASE_URL}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`);
|
||||
|
||||
if (config.accessToken) {
|
||||
url.searchParams.append('access_token', config.accessToken);
|
||||
}
|
||||
|
||||
if (config.params) {
|
||||
Object.entries(config.params).forEach(([key, value]) => {
|
||||
url.searchParams.append(key, String(value));
|
||||
});
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
private static async handleResponse<T>(response: Response): Promise<T> {
|
||||
const data: any = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
// Parse FB Error structure
|
||||
const error = data.error || {};
|
||||
throw new FacebookApiError(
|
||||
error.message || 'Unknown Facebook API Error',
|
||||
response.status,
|
||||
error.code || 0,
|
||||
error.fbtrace_id || ''
|
||||
);
|
||||
}
|
||||
|
||||
return data as T;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user