@olastudio/social-media-sdk 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +190 -55
  2. package/dist/adapters/expo.js +23 -2
  3. package/dist/adapters/expo.js.map +1 -1
  4. package/dist/adapters/expo.mjs +22 -1
  5. package/dist/adapters/expo.mjs.map +1 -1
  6. package/dist/adapters/index.js +0 -2
  7. package/dist/adapters/index.mjs +1 -1
  8. package/dist/core/index.js +318 -87
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/index.mjs +301 -3
  11. package/dist/core/index.mjs.map +1 -1
  12. package/dist/index.js +2225 -170
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +2186 -7
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/providers/facebook/index.js +1071 -26
  17. package/dist/providers/facebook/index.js.map +1 -1
  18. package/dist/providers/facebook/index.mjs +1067 -3
  19. package/dist/providers/facebook/index.mjs.map +1 -1
  20. package/dist/providers/instagram/index.js +866 -22
  21. package/dist/providers/instagram/index.js.map +1 -1
  22. package/dist/providers/instagram/index.mjs +863 -3
  23. package/dist/providers/instagram/index.mjs.map +1 -1
  24. package/dist/providers/tiktok/index.js +395 -41
  25. package/dist/providers/tiktok/index.js.map +1 -1
  26. package/dist/providers/tiktok/index.mjs +389 -1
  27. package/dist/providers/tiktok/index.mjs.map +1 -1
  28. package/package.json +3 -4
  29. package/dist/chunk-36RADUUO.mjs +0 -31
  30. package/dist/chunk-36RADUUO.mjs.map +0 -1
  31. package/dist/chunk-7QAMNVQU.js +0 -666
  32. package/dist/chunk-7QAMNVQU.js.map +0 -1
  33. package/dist/chunk-B6NUTR54.js +0 -4
  34. package/dist/chunk-B6NUTR54.js.map +0 -1
  35. package/dist/chunk-BX3RO5PW.js +0 -4
  36. package/dist/chunk-BX3RO5PW.js.map +0 -1
  37. package/dist/chunk-CGNGZNVG.mjs +0 -391
  38. package/dist/chunk-CGNGZNVG.mjs.map +0 -1
  39. package/dist/chunk-ER5A6TIL.js +0 -296
  40. package/dist/chunk-ER5A6TIL.js.map +0 -1
  41. package/dist/chunk-GF3OEIKI.mjs +0 -3
  42. package/dist/chunk-GF3OEIKI.mjs.map +0 -1
  43. package/dist/chunk-H5GAC4UG.mjs +0 -277
  44. package/dist/chunk-H5GAC4UG.mjs.map +0 -1
  45. package/dist/chunk-HPLIHYLQ.js +0 -35
  46. package/dist/chunk-HPLIHYLQ.js.map +0 -1
  47. package/dist/chunk-MV6HJQQO.mjs +0 -3
  48. package/dist/chunk-MV6HJQQO.mjs.map +0 -1
  49. package/dist/chunk-ONR2OJOB.mjs +0 -848
  50. package/dist/chunk-ONR2OJOB.mjs.map +0 -1
  51. package/dist/chunk-PJ4KYVHH.js +0 -854
  52. package/dist/chunk-PJ4KYVHH.js.map +0 -1
  53. package/dist/chunk-QRGJXASL.js +0 -402
  54. package/dist/chunk-QRGJXASL.js.map +0 -1
  55. package/dist/chunk-QZHJXRRW.mjs +0 -661
  56. package/dist/chunk-QZHJXRRW.mjs.map +0 -1
@@ -1,5 +1,1069 @@
1
- export { FacebookAPI, FacebookAuth, FacebookProvider, FacebookScopesBusiness, FacebookScopesUser } from '../../chunk-ONR2OJOB.mjs';
2
- import '../../chunk-H5GAC4UG.mjs';
3
- import '../../chunk-36RADUUO.mjs';
1
+ // core/constants.ts
2
+ var FACEBOOK_GRAPH_API_VERSION = "v24.0";
3
+ var FACEBOOK_GRAPH_API_BASE_URL = `https://graph.facebook.com/${FACEBOOK_GRAPH_API_VERSION}`;
4
+ var FACEBOOK_OAUTH_AUTHORIZATION_URL = `https://www.facebook.com/${FACEBOOK_GRAPH_API_VERSION}/dialog/oauth`;
5
+
6
+ // core/errors/BaseError.ts
7
+ var BaseError = class extends Error {
8
+ constructor(message, code, details) {
9
+ super(message);
10
+ this.name = this.constructor.name;
11
+ this.code = code;
12
+ this.details = details;
13
+ Error.captureStackTrace(this, this.constructor);
14
+ }
15
+ };
16
+
17
+ // core/errors/AuthError.ts
18
+ var AuthError = class extends BaseError {
19
+ constructor(message, code, details) {
20
+ super(message, code, details);
21
+ this.name = "AuthError";
22
+ }
23
+ };
24
+
25
+ // core/errors/APIError.ts
26
+ var APIError = class extends BaseError {
27
+ constructor(message, statusCode, code, details) {
28
+ super(message, code, details);
29
+ this.name = "APIError";
30
+ this.statusCode = statusCode;
31
+ }
32
+ };
33
+
34
+ // core/http/HttpClient.ts
35
+ var HttpClient = class {
36
+ constructor(config) {
37
+ this.config = {
38
+ timeout: 3e4,
39
+ // 30 seconds default
40
+ headers: {
41
+ "Content-Type": "application/json"
42
+ },
43
+ ...config
44
+ };
45
+ }
46
+ /**
47
+ * Generic request
48
+ */
49
+ async request(endpoint, options = {}) {
50
+ const url = this.buildURL(endpoint, options.params);
51
+ const method = options.method || "GET";
52
+ const headers = {
53
+ ...this.config.headers,
54
+ ...options.headers
55
+ };
56
+ if (this.config.accessToken) {
57
+ headers["Authorization"] = `Bearer ${this.config.accessToken}`;
58
+ }
59
+ const config = {
60
+ method,
61
+ headers,
62
+ signal: this.createAbortSignal(options.timeout || this.config.timeout)
63
+ };
64
+ if (options.body && method !== "GET") {
65
+ if (headers["Content-Type"] === "application/json") {
66
+ config.body = JSON.stringify(options.body);
67
+ } else if (headers["Content-Type"] === "application/x-www-form-urlencoded") {
68
+ config.body = this.encodeFormBody(options.body);
69
+ } else {
70
+ config.body = options.body;
71
+ }
72
+ }
73
+ try {
74
+ const response = await fetch(url, config);
75
+ return await this.handleResponse(response);
76
+ } catch (error) {
77
+ if (error instanceof APIError) {
78
+ throw error;
79
+ }
80
+ throw new APIError(
81
+ `Network error: ${error instanceof Error ? error.message : "Unknown error"}`,
82
+ 0,
83
+ "NETWORK_ERROR",
84
+ error
85
+ );
86
+ }
87
+ }
88
+ /**
89
+ * GET request
90
+ */
91
+ async get(endpoint, params) {
92
+ return this.request(endpoint, { method: "GET", params });
93
+ }
94
+ /**
95
+ * POST request
96
+ */
97
+ async post(endpoint, body) {
98
+ return this.request(endpoint, { method: "POST", body });
99
+ }
100
+ /**
101
+ * PUT request
102
+ */
103
+ async put(endpoint, body) {
104
+ return this.request(endpoint, { method: "PUT", body });
105
+ }
106
+ /**
107
+ * DELETE request
108
+ */
109
+ async delete(endpoint) {
110
+ return this.request(endpoint, { method: "DELETE" });
111
+ }
112
+ /**
113
+ * Build URL with query params
114
+ */
115
+ buildURL(endpoint, params) {
116
+ const url = endpoint.startsWith("http") ? endpoint : `${this.config.baseURL}${endpoint}`;
117
+ if (!params || Object.keys(params).length === 0) {
118
+ return url;
119
+ }
120
+ const queryString = Object.entries(params).filter(([_, value]) => value !== void 0 && value !== null).map(
121
+ ([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
122
+ ).join("&");
123
+ return queryString ? `${url}?${queryString}` : url;
124
+ }
125
+ /**
126
+ * Encode body as form-urlencoded
127
+ */
128
+ encodeFormBody(body) {
129
+ return Object.entries(body).filter(([_, value]) => value !== void 0 && value !== null).map(
130
+ ([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
131
+ ).join("&");
132
+ }
133
+ /**
134
+ * Create AbortSignal for timeout
135
+ */
136
+ createAbortSignal(timeout) {
137
+ if (!timeout) return void 0;
138
+ const controller = new AbortController();
139
+ setTimeout(() => controller.abort(), timeout);
140
+ return controller.signal;
141
+ }
142
+ /**
143
+ * Handle HTTP response
144
+ */
145
+ async handleResponse(response) {
146
+ let data;
147
+ const contentType = response.headers.get("content-type");
148
+ if (contentType?.includes("application/json")) {
149
+ data = await response.json();
150
+ } else {
151
+ data = await response.text();
152
+ }
153
+ if (!response.ok) {
154
+ const errorMessage = data?.error?.message || data?.message || "API request failed";
155
+ const errorCode = data?.error?.code || data?.code || response.status;
156
+ throw new APIError(errorMessage, response.status, errorCode, data);
157
+ }
158
+ return data;
159
+ }
160
+ /**
161
+ * Update access token
162
+ */
163
+ setAccessToken(token) {
164
+ this.config.accessToken = token;
165
+ }
166
+ /**
167
+ * Get current configuration
168
+ */
169
+ getConfig() {
170
+ return { ...this.config };
171
+ }
172
+ };
173
+
174
+ // core/insights.constants.ts
175
+ var POST_METRICS = [
176
+ "post_engaged_users",
177
+ "post_negative_feedback",
178
+ "post_engaged_fan",
179
+ "post_clicks",
180
+ "post_clicks_unique",
181
+ "post_reactions_by_type_total"
182
+ ];
183
+ var VIDEO_METRICS = [
184
+ "total_video_views",
185
+ "total_video_views_unique",
186
+ "total_video_views_autoplayed",
187
+ "total_video_views_clicked_to_play",
188
+ "total_video_views_organic",
189
+ "total_video_views_organic_unique",
190
+ "total_video_views_paid",
191
+ "total_video_views_paid_unique",
192
+ "total_video_avg_time_watched",
193
+ "total_video_view_total_time",
194
+ "total_video_complete_views",
195
+ "total_video_complete_views_unique",
196
+ "total_video_complete_views_organic",
197
+ "total_video_complete_views_organic_unique",
198
+ "total_video_complete_views_paid",
199
+ "total_video_complete_views_paid_unique"
200
+ ];
201
+ var REELS_METRICS = [
202
+ "blue_reels_play_count",
203
+ "post_video_avg_time_watched",
204
+ "post_video_views",
205
+ "post_video_social_actions"
206
+ ];
207
+ var PHOTO_METRICS = [
208
+ "photo_views",
209
+ "photo_reach",
210
+ "engaged_users"
211
+ ];
212
+ var METRIC_PRESETS = {
213
+ // Facebook Page quick overview
214
+ PAGE_OVERVIEW: ["page_views_total", "page_post_engagements", "page_video_views"],
215
+ // Facebook Video performance
216
+ VIDEO_PERFORMANCE: ["total_video_views", "total_video_avg_time_watched", "total_video_complete_views"],
217
+ // Facebook Reels performance
218
+ REELS_PERFORMANCE: ["blue_reels_play_count", "post_video_avg_time_watched", "post_video_social_actions"],
219
+ // Instagram account overview
220
+ INSTAGRAM_OVERVIEW: ["views", "reach", "accounts_engaged", "total_interactions"],
221
+ // Instagram content engagement
222
+ INSTAGRAM_ENGAGEMENT: ["likes", "comments", "shares", "saves"]
223
+ };
224
+
225
+ // providers/facebook/api/FacebookAPI.ts
226
+ var FacebookAPI = class {
227
+ constructor(config, accessToken) {
228
+ this.config = config;
229
+ this.accessToken = accessToken;
230
+ this.httpClient = new HttpClient({
231
+ baseURL: FACEBOOK_GRAPH_API_BASE_URL,
232
+ accessToken: this.accessToken
233
+ });
234
+ }
235
+ /**
236
+ * Generic request
237
+ */
238
+ async request(endpoint, options = {}) {
239
+ if (this.accessToken && !options.params?.access_token) {
240
+ options.params = {
241
+ ...options.params,
242
+ access_token: this.accessToken
243
+ };
244
+ }
245
+ return this.httpClient.request(endpoint, options);
246
+ }
247
+ /**
248
+ * GET request
249
+ */
250
+ async get(endpoint, params) {
251
+ return this.request(endpoint, { method: "GET", params });
252
+ }
253
+ /**
254
+ * POST request
255
+ */
256
+ async post(endpoint, body) {
257
+ return this.request(endpoint, { method: "POST", body });
258
+ }
259
+ /**
260
+ * PUT request
261
+ */
262
+ async put(endpoint, body) {
263
+ return this.request(endpoint, { method: "PUT", body });
264
+ }
265
+ /**
266
+ * DELETE request
267
+ */
268
+ async delete(endpoint) {
269
+ return this.request(endpoint, { method: "DELETE" });
270
+ }
271
+ /**
272
+ * Update access token
273
+ */
274
+ setAccessToken(token) {
275
+ this.accessToken = token;
276
+ this.httpClient.setAccessToken(token);
277
+ }
278
+ /**
279
+ * Get current access token
280
+ */
281
+ getAccessToken() {
282
+ return this.accessToken;
283
+ }
284
+ // ============= Facebook-specific methods =============
285
+ /**
286
+ * Get user's pages
287
+ */
288
+ async getPages(userAccessToken) {
289
+ try {
290
+ const token = userAccessToken || this.accessToken;
291
+ if (!token) {
292
+ throw new APIError("Access token is required", 401, "NO_TOKEN");
293
+ }
294
+ const response = await this.get("/me/accounts", {
295
+ fields: "id,name,access_token,picture",
296
+ access_token: token
297
+ });
298
+ return response.data;
299
+ } catch (error) {
300
+ throw new APIError(
301
+ `Failed to fetch Facebook pages: ${error instanceof Error ? error.message : "Unknown error"}`,
302
+ void 0,
303
+ "PAGES_FETCH_ERROR",
304
+ error
305
+ );
306
+ }
307
+ }
308
+ /**
309
+ * Publish post to Facebook page
310
+ */
311
+ async publishPost(params) {
312
+ const { pageId, pageAccessToken, message, imageUrl, scheduledPublishTime } = params;
313
+ try {
314
+ let endpoint = `/${pageId}/`;
315
+ const body = {
316
+ access_token: pageAccessToken
317
+ };
318
+ if (scheduledPublishTime) {
319
+ body.published = false;
320
+ body.scheduled_publish_time = scheduledPublishTime;
321
+ }
322
+ if (imageUrl) {
323
+ endpoint += "photos";
324
+ body.url = imageUrl;
325
+ if (message) body.caption = message;
326
+ } else if (message) {
327
+ endpoint += "feed";
328
+ body.message = message;
329
+ } else {
330
+ throw new APIError(
331
+ "Either message or imageUrl must be provided",
332
+ 400,
333
+ "INVALID_PARAMS"
334
+ );
335
+ }
336
+ const response = await this.request(endpoint, {
337
+ method: "POST",
338
+ headers: {
339
+ "Content-Type": "application/x-www-form-urlencoded"
340
+ },
341
+ body
342
+ });
343
+ return response;
344
+ } catch (error) {
345
+ throw new APIError(
346
+ `Failed to publish post: ${error instanceof Error ? error.message : "Unknown error"}`,
347
+ void 0,
348
+ "POST_PUBLISH_ERROR",
349
+ error
350
+ );
351
+ }
352
+ }
353
+ /**
354
+ * Delete Facebook post
355
+ */
356
+ async deletePost(postId, pageAccessToken) {
357
+ try {
358
+ const response = await this.delete(
359
+ `/${postId}?access_token=${pageAccessToken}`
360
+ );
361
+ return response.success === true;
362
+ } catch (error) {
363
+ throw new APIError(
364
+ `Failed to delete post: ${error instanceof Error ? error.message : "Unknown error"}`,
365
+ void 0,
366
+ "POST_DELETE_ERROR",
367
+ error
368
+ );
369
+ }
370
+ }
371
+ /**
372
+ * Get page information
373
+ */
374
+ async getPage(pageId, fields) {
375
+ try {
376
+ const fieldsParam = fields?.join(",") || "id,name,access_token,picture";
377
+ return await this.get(`/${pageId}`, {
378
+ fields: fieldsParam
379
+ });
380
+ } catch (error) {
381
+ throw new APIError(
382
+ `Failed to fetch page info: ${error instanceof Error ? error.message : "Unknown error"}`,
383
+ void 0,
384
+ "PAGE_FETCH_ERROR",
385
+ error
386
+ );
387
+ }
388
+ }
389
+ /**
390
+ * Debug/validate a Facebook access token
391
+ * Uses Facebook's debug_token endpoint
392
+ *
393
+ * @param inputToken - The token to validate
394
+ * @param appAccessToken - App token (app_id|app_secret)
395
+ * @returns Token debug information
396
+ */
397
+ async debugToken(inputToken, appAccessToken) {
398
+ try {
399
+ return await this.get("/debug_token", {
400
+ input_token: inputToken,
401
+ access_token: appAccessToken
402
+ });
403
+ } catch (error) {
404
+ throw new APIError(
405
+ `Failed to debug token: ${error instanceof Error ? error.message : "Unknown error"}`,
406
+ void 0,
407
+ "TOKEN_DEBUG_ERROR",
408
+ error
409
+ );
410
+ }
411
+ }
412
+ /**
413
+ * Get page insights/analytics
414
+ * @param pageId - Facebook Page ID
415
+ * @param options - Insights options
416
+ * @returns Page insights data
417
+ */
418
+ async getPageInsights(pageId, options) {
419
+ try {
420
+ const params = {
421
+ metric: options.metric.join(","),
422
+ period: options.period || "day"
423
+ };
424
+ if (options.since) params.since = options.since;
425
+ if (options.until) params.until = options.until;
426
+ const response = await this.get(`/${pageId}/insights`, params);
427
+ return response;
428
+ } catch (error) {
429
+ throw new APIError(
430
+ `Failed to fetch page insights: ${error instanceof Error ? error.message : "Unknown error"}`,
431
+ void 0,
432
+ "INSIGHTS_FETCH_ERROR",
433
+ error
434
+ );
435
+ }
436
+ }
437
+ /**
438
+ * Get page fans count (total followers)
439
+ * @param pageId - Facebook Page ID
440
+ * @returns Page with fan count
441
+ */
442
+ async getPageFansCount(pageId) {
443
+ try {
444
+ return await this.get(`/${pageId}`, {
445
+ fields: "id,fan_count"
446
+ });
447
+ } catch (error) {
448
+ throw new APIError(
449
+ `Failed to fetch page fans count: ${error instanceof Error ? error.message : "Unknown error"}`,
450
+ void 0,
451
+ "FANS_COUNT_ERROR",
452
+ error
453
+ );
454
+ }
455
+ }
456
+ /**
457
+ * Get page overview with key metrics
458
+ * @param pageId - Facebook Page ID
459
+ * @returns Page overview data
460
+ */
461
+ async getPageOverview(pageId) {
462
+ try {
463
+ const response = await this.get(`/${pageId}`, {
464
+ fields: "id,name,followers_count,fan_count"
465
+ });
466
+ return {
467
+ id: response.id,
468
+ name: response.name,
469
+ followers_count: response.followers_count || response.fan_count || 0,
470
+ fan_count: response.fan_count
471
+ };
472
+ } catch (error) {
473
+ throw new APIError(
474
+ `Failed to fetch page overview: ${error instanceof Error ? error.message : "Unknown error"}`,
475
+ void 0,
476
+ "PAGE_OVERVIEW_ERROR",
477
+ error
478
+ );
479
+ }
480
+ }
481
+ // ============= Video Insights Methods =============
482
+ /**
483
+ * Get video insights
484
+ * @param videoId - Facebook Video ID
485
+ * @param metrics - Specific metrics to fetch (defaults to common metrics)
486
+ * @returns Video insights data
487
+ */
488
+ async getVideoInsights(videoId, metrics) {
489
+ try {
490
+ const metricsToFetch = metrics || METRIC_PRESETS.VIDEO_PERFORMANCE;
491
+ const response = await this.get(
492
+ `/${videoId}/video_insights`,
493
+ {
494
+ metric: metricsToFetch.join(",")
495
+ }
496
+ );
497
+ return response;
498
+ } catch (error) {
499
+ throw new APIError(
500
+ `Failed to fetch video insights: ${error instanceof Error ? error.message : "Unknown error"}`,
501
+ void 0,
502
+ "VIDEO_INSIGHTS_ERROR",
503
+ error
504
+ );
505
+ }
506
+ }
507
+ /**
508
+ * Get video insights with parsed values
509
+ * @param videoId - Facebook Video ID
510
+ * @returns Parsed video insights
511
+ */
512
+ async getVideoInsightsParsed(videoId) {
513
+ try {
514
+ const response = await this.getVideoInsights(videoId, [...VIDEO_METRICS.slice(0, 8)]);
515
+ const insights = { id: videoId };
516
+ for (const item of response.data) {
517
+ const value = item.values?.[0]?.value ?? item.total_value?.value;
518
+ if (typeof value !== "number") continue;
519
+ switch (item.name) {
520
+ case "total_video_views":
521
+ insights.total_views = value;
522
+ break;
523
+ case "total_video_views_unique":
524
+ insights.unique_views = value;
525
+ break;
526
+ case "total_video_avg_time_watched":
527
+ insights.avg_time_watched = value;
528
+ break;
529
+ case "total_video_complete_views":
530
+ insights.complete_views = value;
531
+ break;
532
+ case "total_video_views_organic":
533
+ insights.organic_views = value;
534
+ break;
535
+ case "total_video_views_paid":
536
+ insights.paid_views = value;
537
+ break;
538
+ case "total_video_view_total_time":
539
+ insights.total_time_watched = value;
540
+ break;
541
+ }
542
+ }
543
+ return insights;
544
+ } catch (error) {
545
+ throw new APIError(
546
+ `Failed to fetch parsed video insights: ${error instanceof Error ? error.message : "Unknown error"}`,
547
+ void 0,
548
+ "VIDEO_INSIGHTS_PARSED_ERROR",
549
+ error
550
+ );
551
+ }
552
+ }
553
+ /**
554
+ * Get page videos with basic info
555
+ * @param pageId - Facebook Page ID
556
+ * @param limit - Number of videos to fetch
557
+ * @returns List of videos
558
+ */
559
+ async getPageVideos(pageId, limit = 25) {
560
+ try {
561
+ return await this.get(`/${pageId}/videos`, {
562
+ fields: "id,title,description,created_time,length",
563
+ limit
564
+ });
565
+ } catch (error) {
566
+ throw new APIError(
567
+ `Failed to fetch page videos: ${error instanceof Error ? error.message : "Unknown error"}`,
568
+ void 0,
569
+ "PAGE_VIDEOS_ERROR",
570
+ error
571
+ );
572
+ }
573
+ }
574
+ // ============= Reels Insights Methods =============
575
+ /**
576
+ * Get reels insights
577
+ * @param reelId - Facebook Reel ID
578
+ * @param metrics - Specific metrics to fetch
579
+ * @returns Reels insights data
580
+ */
581
+ async getReelsInsights(reelId, metrics) {
582
+ try {
583
+ const metricsToFetch = metrics || METRIC_PRESETS.REELS_PERFORMANCE;
584
+ const response = await this.get(
585
+ `/${reelId}/video_insights`,
586
+ {
587
+ metric: metricsToFetch.join(",")
588
+ }
589
+ );
590
+ return response;
591
+ } catch (error) {
592
+ throw new APIError(
593
+ `Failed to fetch reels insights: ${error instanceof Error ? error.message : "Unknown error"}`,
594
+ void 0,
595
+ "REELS_INSIGHTS_ERROR",
596
+ error
597
+ );
598
+ }
599
+ }
600
+ /**
601
+ * Get reels insights with parsed values
602
+ * @param reelId - Facebook Reel ID
603
+ * @returns Parsed reels insights
604
+ */
605
+ async getReelsInsightsParsed(reelId) {
606
+ try {
607
+ const response = await this.getReelsInsights(reelId, [...REELS_METRICS]);
608
+ const insights = { id: reelId };
609
+ for (const item of response.data) {
610
+ const value = item.values?.[0]?.value ?? item.total_value?.value;
611
+ if (typeof value !== "number") continue;
612
+ switch (item.name) {
613
+ case "blue_reels_play_count":
614
+ insights.plays = value;
615
+ break;
616
+ case "post_video_avg_time_watched":
617
+ insights.avg_time_watched = value;
618
+ break;
619
+ case "post_video_views":
620
+ insights.total_plays = value;
621
+ break;
622
+ }
623
+ }
624
+ try {
625
+ const postResponse = await this.get(`/${reelId}`, {
626
+ fields: "reactions.summary(true),comments.summary(true),shares"
627
+ });
628
+ insights.likes = postResponse.reactions?.summary?.total_count;
629
+ insights.comments = postResponse.comments?.summary?.total_count;
630
+ insights.shares = postResponse.shares?.count;
631
+ } catch {
632
+ }
633
+ return insights;
634
+ } catch (error) {
635
+ throw new APIError(
636
+ `Failed to fetch parsed reels insights: ${error instanceof Error ? error.message : "Unknown error"}`,
637
+ void 0,
638
+ "REELS_INSIGHTS_PARSED_ERROR",
639
+ error
640
+ );
641
+ }
642
+ }
643
+ /**
644
+ * Get page reels
645
+ * @param pageId - Facebook Page ID
646
+ * @param limit - Number of reels to fetch
647
+ * @returns List of reels
648
+ */
649
+ async getPageReels(pageId, limit = 25) {
650
+ try {
651
+ return await this.get(`/${pageId}/video_reels`, {
652
+ fields: "id,description,created_time",
653
+ limit
654
+ });
655
+ } catch (error) {
656
+ throw new APIError(
657
+ `Failed to fetch page reels: ${error instanceof Error ? error.message : "Unknown error"}`,
658
+ void 0,
659
+ "PAGE_REELS_ERROR",
660
+ error
661
+ );
662
+ }
663
+ }
664
+ // ============= Post Insights Methods =============
665
+ /**
666
+ * Get post insights
667
+ * @param postId - Facebook Post ID
668
+ * @param metrics - Specific metrics to fetch
669
+ * @returns Post insights data
670
+ */
671
+ async getPostInsights(postId, metrics) {
672
+ try {
673
+ const metricsToFetch = metrics || [...POST_METRICS];
674
+ const response = await this.get(
675
+ `/${postId}/insights`,
676
+ {
677
+ metric: metricsToFetch.join(",")
678
+ }
679
+ );
680
+ return response;
681
+ } catch (error) {
682
+ throw new APIError(
683
+ `Failed to fetch post insights: ${error instanceof Error ? error.message : "Unknown error"}`,
684
+ void 0,
685
+ "POST_INSIGHTS_ERROR",
686
+ error
687
+ );
688
+ }
689
+ }
690
+ /**
691
+ * Get post insights with parsed values
692
+ * @param postId - Facebook Post ID
693
+ * @returns Parsed post insights
694
+ */
695
+ async getPostInsightsParsed(postId) {
696
+ try {
697
+ const response = await this.getPostInsights(postId);
698
+ const insights = { id: postId };
699
+ for (const item of response.data) {
700
+ const value = item.values?.[0]?.value ?? item.total_value?.value;
701
+ switch (item.name) {
702
+ case "post_engaged_users":
703
+ if (typeof value === "number") insights.engaged_users = value;
704
+ break;
705
+ case "post_clicks":
706
+ if (typeof value === "number") insights.clicks = value;
707
+ break;
708
+ case "post_negative_feedback":
709
+ if (typeof value === "number") insights.negative_feedback = value;
710
+ break;
711
+ case "post_reactions_by_type_total":
712
+ if (typeof value === "object") insights.reactions_by_type = value;
713
+ break;
714
+ }
715
+ }
716
+ return insights;
717
+ } catch (error) {
718
+ throw new APIError(
719
+ `Failed to fetch parsed post insights: ${error instanceof Error ? error.message : "Unknown error"}`,
720
+ void 0,
721
+ "POST_INSIGHTS_PARSED_ERROR",
722
+ error
723
+ );
724
+ }
725
+ }
726
+ /**
727
+ * Get page posts/feed
728
+ * @param pageId - Facebook Page ID
729
+ * @param limit - Number of posts to fetch
730
+ * @returns List of posts
731
+ */
732
+ async getPagePosts(pageId, limit = 25) {
733
+ try {
734
+ return await this.get(`/${pageId}/feed`, {
735
+ fields: "id,message,created_time,type",
736
+ limit
737
+ });
738
+ } catch (error) {
739
+ throw new APIError(
740
+ `Failed to fetch page posts: ${error instanceof Error ? error.message : "Unknown error"}`,
741
+ void 0,
742
+ "PAGE_POSTS_ERROR",
743
+ error
744
+ );
745
+ }
746
+ }
747
+ // ============= Photo Insights Methods =============
748
+ /**
749
+ * Get photo insights
750
+ * @param photoId - Facebook Photo ID
751
+ * @param metrics - Specific metrics to fetch
752
+ * @returns Photo insights data
753
+ */
754
+ async getPhotoInsights(photoId, metrics) {
755
+ try {
756
+ const metricsToFetch = metrics || [...PHOTO_METRICS];
757
+ const response = await this.get(
758
+ `/${photoId}/insights`,
759
+ {
760
+ metric: metricsToFetch.join(",")
761
+ }
762
+ );
763
+ return response;
764
+ } catch (error) {
765
+ throw new APIError(
766
+ `Failed to fetch photo insights: ${error instanceof Error ? error.message : "Unknown error"}`,
767
+ void 0,
768
+ "PHOTO_INSIGHTS_ERROR",
769
+ error
770
+ );
771
+ }
772
+ }
773
+ /**
774
+ * Get photo insights with parsed values
775
+ * @param photoId - Facebook Photo ID
776
+ * @returns Parsed photo insights
777
+ */
778
+ async getPhotoInsightsParsed(photoId) {
779
+ try {
780
+ const response = await this.getPhotoInsights(photoId);
781
+ const insights = { id: photoId };
782
+ for (const item of response.data) {
783
+ const value = item.values?.[0]?.value ?? item.total_value?.value;
784
+ if (typeof value !== "number") continue;
785
+ switch (item.name) {
786
+ case "photo_views":
787
+ insights.views = value;
788
+ break;
789
+ case "photo_reach":
790
+ insights.reach = value;
791
+ break;
792
+ case "engaged_users":
793
+ insights.engaged_users = value;
794
+ break;
795
+ }
796
+ }
797
+ return insights;
798
+ } catch (error) {
799
+ throw new APIError(
800
+ `Failed to fetch parsed photo insights: ${error instanceof Error ? error.message : "Unknown error"}`,
801
+ void 0,
802
+ "PHOTO_INSIGHTS_PARSED_ERROR",
803
+ error
804
+ );
805
+ }
806
+ }
807
+ /**
808
+ * Get page photos
809
+ * @param pageId - Facebook Page ID
810
+ * @param limit - Number of photos to fetch
811
+ * @returns List of photos
812
+ */
813
+ async getPagePhotos(pageId, limit = 25) {
814
+ try {
815
+ return await this.get(`/${pageId}/photos`, {
816
+ fields: "id,name,created_time",
817
+ type: "uploaded",
818
+ limit
819
+ });
820
+ } catch (error) {
821
+ throw new APIError(
822
+ `Failed to fetch page photos: ${error instanceof Error ? error.message : "Unknown error"}`,
823
+ void 0,
824
+ "PAGE_PHOTOS_ERROR",
825
+ error
826
+ );
827
+ }
828
+ }
829
+ // ============= Batch/Helper Methods =============
830
+ /**
831
+ * Get quick insights summary for a page
832
+ * Combines key metrics in a single call
833
+ * @param pageId - Facebook Page ID
834
+ * @param period - Period for time-based metrics
835
+ * @returns Summary of page insights
836
+ */
837
+ async getPageInsightsSummary(pageId, period = "days_28") {
838
+ try {
839
+ const overview = await this.getPageOverview(pageId);
840
+ const insightsResponse = await this.getPageInsights(pageId, {
841
+ metric: [...METRIC_PRESETS.PAGE_OVERVIEW],
842
+ period
843
+ });
844
+ const engagement = {};
845
+ for (const item of insightsResponse.data) {
846
+ const values = item.values || [];
847
+ const total = values.reduce((sum, v) => sum + (typeof v.value === "number" ? v.value : 0), 0);
848
+ switch (item.name) {
849
+ case "page_views_total":
850
+ engagement.views = total;
851
+ break;
852
+ case "page_post_engagements":
853
+ engagement.post_engagements = total;
854
+ break;
855
+ case "page_video_views":
856
+ engagement.video_views = total;
857
+ break;
858
+ }
859
+ }
860
+ return { overview, engagement };
861
+ } catch (error) {
862
+ throw new APIError(
863
+ `Failed to fetch page insights summary: ${error instanceof Error ? error.message : "Unknown error"}`,
864
+ void 0,
865
+ "PAGE_SUMMARY_ERROR",
866
+ error
867
+ );
868
+ }
869
+ }
870
+ /**
871
+ * Get current API version (read-only)
872
+ */
873
+ getApiVersion() {
874
+ return FACEBOOK_GRAPH_API_VERSION;
875
+ }
876
+ };
877
+
878
+ // providers/facebook/auth/FacebookAuth.ts
879
+ var FacebookAuth = class {
880
+ constructor(config) {
881
+ this.config = config;
882
+ this.httpClient = new HttpClient({
883
+ baseURL: FACEBOOK_GRAPH_API_BASE_URL
884
+ });
885
+ }
886
+ /**
887
+ * Exchange Facebook token for session
888
+ * In Expo + Supabase, this is handled in the app
889
+ * This function only validates and gets profile info
890
+ */
891
+ async exchangeToken(facebookToken) {
892
+ try {
893
+ const profile = await this.getProfile(facebookToken);
894
+ return {
895
+ accessToken: facebookToken,
896
+ user: profile
897
+ };
898
+ } catch (error) {
899
+ throw new AuthError(
900
+ `Failed to exchange Facebook token: ${error instanceof Error ? error.message : "Unknown error"}`,
901
+ "TOKEN_EXCHANGE_ERROR",
902
+ error
903
+ );
904
+ }
905
+ }
906
+ /**
907
+ * Get Facebook user profile
908
+ */
909
+ async getProfile(accessToken) {
910
+ try {
911
+ const profile = await this.httpClient.get("/me", {
912
+ fields: "id,name,email,picture",
913
+ access_token: accessToken
914
+ });
915
+ return {
916
+ id: profile.id,
917
+ name: profile.name,
918
+ email: profile.email,
919
+ picture: profile.picture?.data?.url
920
+ };
921
+ } catch (error) {
922
+ throw new AuthError(
923
+ `Failed to fetch Facebook profile: ${error instanceof Error ? error.message : "Unknown error"}`,
924
+ "PROFILE_FETCH_ERROR",
925
+ error
926
+ );
927
+ }
928
+ }
929
+ /**
930
+ * Exchange short-lived token for long-lived token
931
+ */
932
+ async exchangeForLongLivedToken(params) {
933
+ try {
934
+ const response = await this.httpClient.get(
935
+ "/oauth/access_token",
936
+ {
937
+ grant_type: "fb_exchange_token",
938
+ client_id: params.appId,
939
+ client_secret: params.appSecret,
940
+ fb_exchange_token: params.shortLivedToken
941
+ }
942
+ );
943
+ return response.access_token;
944
+ } catch (error) {
945
+ throw new AuthError(
946
+ `Failed to exchange for long-lived token: ${error instanceof Error ? error.message : "Unknown error"}`,
947
+ "LONG_LIVED_TOKEN_ERROR",
948
+ error
949
+ );
950
+ }
951
+ }
952
+ /**
953
+ * Get OAuth configuration for Facebook
954
+ */
955
+ getOAuthConfig(scopes, redirectUri) {
956
+ return {
957
+ authorizationEndpoint: FACEBOOK_OAUTH_AUTHORIZATION_URL,
958
+ tokenEndpoint: `${FACEBOOK_GRAPH_API_BASE_URL}/oauth/access_token`,
959
+ clientId: this.config.appId,
960
+ clientSecret: this.config.appSecret,
961
+ redirectUri,
962
+ scopes,
963
+ responseType: "token",
964
+ extraParams: {
965
+ display: "popup"
966
+ }
967
+ };
968
+ }
969
+ /**
970
+ * Get authorization URL
971
+ */
972
+ getAuthorizationUrl(scopes, redirectUri, state) {
973
+ const params = new URLSearchParams({
974
+ client_id: this.config.appId,
975
+ redirect_uri: redirectUri,
976
+ scope: scopes.join(","),
977
+ response_type: "token",
978
+ display: "popup",
979
+ ...state && { state }
980
+ });
981
+ return `${FACEBOOK_OAUTH_AUTHORIZATION_URL}?${params.toString()}`;
982
+ }
983
+ /**
984
+ * Get current API version (read-only)
985
+ */
986
+ getApiVersion() {
987
+ return FACEBOOK_GRAPH_API_VERSION;
988
+ }
989
+ };
990
+
991
+ // providers/facebook/FacebookProvider.ts
992
+ var FacebookProvider = class {
993
+ constructor(config) {
994
+ this.name = "facebook";
995
+ this.config = config;
996
+ this.auth = new FacebookAuth(config);
997
+ this.api = new FacebookAPI(config);
998
+ }
999
+ /**
1000
+ * Create new API instance with access token
1001
+ */
1002
+ createAPIClient(accessToken) {
1003
+ return new FacebookAPI(this.config, accessToken);
1004
+ }
1005
+ /**
1006
+ * Update access token of existing API client
1007
+ */
1008
+ setAccessToken(accessToken) {
1009
+ this.api.setAccessToken(accessToken);
1010
+ }
1011
+ /**
1012
+ * Get current access token
1013
+ */
1014
+ getAccessToken() {
1015
+ return this.api.getAccessToken();
1016
+ }
1017
+ };
1018
+
1019
+ // providers/facebook/types/index.ts
1020
+ var FacebookScopesBusiness = /* @__PURE__ */ ((FacebookScopesBusiness2) => {
1021
+ FacebookScopesBusiness2["PUBLIC_PROFILE"] = "public_profile";
1022
+ FacebookScopesBusiness2["EMAIL"] = "email";
1023
+ FacebookScopesBusiness2["PAGES_SHOW_LIST"] = "pages_show_list";
1024
+ FacebookScopesBusiness2["PAGES_READ_ENGAGEMENT"] = "pages_read_engagement";
1025
+ FacebookScopesBusiness2["PAGES_MANAGE_POSTS"] = "pages_manage_posts";
1026
+ FacebookScopesBusiness2["ADS_MANAGEMENT"] = "ads_management";
1027
+ FacebookScopesBusiness2["ADS_READ"] = "ads_read";
1028
+ FacebookScopesBusiness2["BUSINESS_MANAGEMENT"] = "business_management";
1029
+ FacebookScopesBusiness2["CATALOG_MANAGEMENT"] = "catalog_management";
1030
+ FacebookScopesBusiness2["COMMERCE_ACCOUNT_MANAGE_ORDERS"] = "commerce_account_manage_orders";
1031
+ FacebookScopesBusiness2["COMMERCE_ACCOUNT_READ_ORDERS"] = "commerce_account_read_orders";
1032
+ FacebookScopesBusiness2["COMMERCE_ACCOUNT_READ_REPORTS"] = "commerce_account_read_reports";
1033
+ FacebookScopesBusiness2["COMMERCE_ACCOUNT_READ_SETTINGS"] = "commerce_account_read_settings";
1034
+ FacebookScopesBusiness2["COMMERCE_MANAGE_ACCOUNTS"] = "commerce_manage_accounts";
1035
+ FacebookScopesBusiness2["INSTAGRAM_BASIC"] = "instagram_basic";
1036
+ FacebookScopesBusiness2["INSTAGRAM_CONTENT_PUBLISH"] = "instagram_content_publish";
1037
+ FacebookScopesBusiness2["INSTAGRAM_MANAGE_COMMENTS"] = "instagram_manage_comments";
1038
+ FacebookScopesBusiness2["INSTAGRAM_MANAGE_INSIGHTS"] = "instagram_manage_insights";
1039
+ FacebookScopesBusiness2["INSTAGRAM_MANAGE_MESSAGES"] = "instagram_manage_messages";
1040
+ FacebookScopesBusiness2["INSTAGRAM_SHOPPING_TAG_PRODUCTS"] = "instagram_shopping_tag_products";
1041
+ FacebookScopesBusiness2["LEADS_RETRIEVAL"] = "leads_retrieval";
1042
+ FacebookScopesBusiness2["MANAGE_APP_SOLUTIONS"] = "manage_app_solutions";
1043
+ FacebookScopesBusiness2["MANAGE_FUNDRAISERS"] = "manage_fundraisers";
1044
+ FacebookScopesBusiness2["PAGES_MANAGE_CTA"] = "pages_manage_cta";
1045
+ FacebookScopesBusiness2["PAGE_EVENTS"] = "page_events";
1046
+ FacebookScopesBusiness2["PAGES_MANAGE_ADS"] = "pages_manage_ads";
1047
+ FacebookScopesBusiness2["PAGES_MANAGE_ENGAGEMENT"] = "pages_manage_engagement";
1048
+ FacebookScopesBusiness2["PAGES_MANAGE_INSTANT_ARTICLES"] = "pages_manage_instant_articles";
1049
+ FacebookScopesBusiness2["PAGES_MANAGE_METADATA"] = "pages_manage_metadata";
1050
+ FacebookScopesBusiness2["PAGES_MESSAGING"] = "pages_messaging";
1051
+ FacebookScopesBusiness2["PAGES_READ_USER_CONTENT"] = "pages_read_user_content";
1052
+ FacebookScopesBusiness2["PRIVATE_COMPUTATION_ACCESS"] = "private_computation_access";
1053
+ FacebookScopesBusiness2["PUBLISH_VIDEO"] = "publish_video";
1054
+ FacebookScopesBusiness2["READ_INSIGHTS"] = "read_insights";
1055
+ FacebookScopesBusiness2["READ_AUDIENCE_NETWORK_INSIGHTS"] = "read_audience_network_insights";
1056
+ FacebookScopesBusiness2["WHATSAPP_BUSINESS_MANAGEMENT"] = "whatsapp_business_management";
1057
+ FacebookScopesBusiness2["WHATSAPP_BUSINESS_MESSAGING"] = "whatsapp_business_messaging";
1058
+ return FacebookScopesBusiness2;
1059
+ })(FacebookScopesBusiness || {});
1060
+ var FacebookScopesUser = /* @__PURE__ */ ((FacebookScopesUser2) => {
1061
+ FacebookScopesUser2["PUBLIC_PROFILE"] = "public_profile";
1062
+ FacebookScopesUser2["EMAIL"] = "email";
1063
+ FacebookScopesUser2["USER_FRIENDS"] = "user_friends";
1064
+ return FacebookScopesUser2;
1065
+ })(FacebookScopesUser || {});
1066
+
1067
+ export { FacebookAPI, FacebookAuth, FacebookProvider, FacebookScopesBusiness, FacebookScopesUser };
4
1068
  //# sourceMappingURL=index.mjs.map
5
1069
  //# sourceMappingURL=index.mjs.map