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