@olastudio/social-media-sdk 0.1.0

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