@olastudio/social-media-sdk 0.1.0 → 0.1.1

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 +6 -6
  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 +1 -1
  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,865 @@
1
- export { InstagramAPI, InstagramAuth, InstagramProvider, InstagramScopes } from '../../chunk-QZHJXRRW.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
+ // providers/instagram/auth/InstagramAuth.ts
175
+ var InstagramAuth = class {
176
+ constructor(config) {
177
+ this.config = config;
178
+ this.httpClient = new HttpClient({
179
+ baseURL: FACEBOOK_GRAPH_API_BASE_URL
180
+ });
181
+ }
182
+ /**
183
+ * Exchange Instagram/Facebook token for session
184
+ */
185
+ async exchangeToken(instagramToken) {
186
+ try {
187
+ const profile = await this.getProfile(instagramToken);
188
+ return {
189
+ accessToken: instagramToken,
190
+ user: profile
191
+ };
192
+ } catch (error) {
193
+ throw new AuthError(
194
+ `Failed to exchange Instagram token: ${error instanceof Error ? error.message : "Unknown error"}`,
195
+ "TOKEN_EXCHANGE_ERROR",
196
+ error
197
+ );
198
+ }
199
+ }
200
+ /**
201
+ * Get Instagram user profile
202
+ * First gets Facebook profile, then Instagram Business profile
203
+ */
204
+ async getProfile(accessToken) {
205
+ try {
206
+ const response = await this.httpClient.get("/me/accounts", {
207
+ fields: "instagram_business_account",
208
+ access_token: accessToken
209
+ });
210
+ if (!response.data || response.data.length === 0) {
211
+ throw new AuthError(
212
+ "No Instagram business account found",
213
+ "NO_INSTAGRAM_ACCOUNT"
214
+ );
215
+ }
216
+ const instagramAccountId = response.data[0]?.instagram_business_account?.id;
217
+ if (!instagramAccountId) {
218
+ throw new AuthError(
219
+ "No Instagram business account ID found",
220
+ "NO_INSTAGRAM_ACCOUNT_ID"
221
+ );
222
+ }
223
+ const profile = await this.httpClient.get(
224
+ `/${instagramAccountId}`,
225
+ {
226
+ fields: "id,username,name,account_type,profile_picture_url",
227
+ access_token: accessToken
228
+ }
229
+ );
230
+ return {
231
+ id: profile.id,
232
+ name: profile.name || profile.username,
233
+ username: profile.username,
234
+ picture: profile.profile_picture_url
235
+ };
236
+ } catch (error) {
237
+ throw new AuthError(
238
+ `Failed to fetch Instagram profile: ${error instanceof Error ? error.message : "Unknown error"}`,
239
+ "PROFILE_FETCH_ERROR",
240
+ error
241
+ );
242
+ }
243
+ }
244
+ /**
245
+ * Get OAuth configuration for Instagram
246
+ * Instagram uses the same OAuth flow as Facebook
247
+ */
248
+ getOAuthConfig(scopes, redirectUri) {
249
+ return {
250
+ authorizationEndpoint: FACEBOOK_OAUTH_AUTHORIZATION_URL,
251
+ tokenEndpoint: `${FACEBOOK_GRAPH_API_BASE_URL}/oauth/access_token`,
252
+ clientId: this.config.appId,
253
+ clientSecret: this.config.appSecret,
254
+ redirectUri,
255
+ scopes,
256
+ responseType: "token",
257
+ extraParams: {
258
+ display: "popup"
259
+ }
260
+ };
261
+ }
262
+ /**
263
+ * Get authorization URL
264
+ */
265
+ getAuthorizationUrl(scopes, redirectUri, state) {
266
+ const params = new URLSearchParams({
267
+ client_id: this.config.appId,
268
+ redirect_uri: redirectUri,
269
+ scope: scopes.join(","),
270
+ response_type: "token",
271
+ display: "popup",
272
+ ...state && { state }
273
+ });
274
+ return `${FACEBOOK_OAUTH_AUTHORIZATION_URL}?${params.toString()}`;
275
+ }
276
+ /**
277
+ * Get current API version (read-only)
278
+ */
279
+ getApiVersion() {
280
+ return FACEBOOK_GRAPH_API_VERSION;
281
+ }
282
+ };
283
+
284
+ // core/insights.constants.ts
285
+ var INSTAGRAM_MEDIA_METRICS_COMMON = [
286
+ "views",
287
+ "reach",
288
+ "likes",
289
+ "comments",
290
+ "shares",
291
+ "saved",
292
+ "total_interactions"
293
+ ];
294
+ var INSTAGRAM_REELS_METRICS = [
295
+ "plays",
296
+ "reach",
297
+ "likes",
298
+ "comments",
299
+ "shares",
300
+ "saved",
301
+ "total_interactions"
302
+ ];
303
+ var INSTAGRAM_STORIES_METRICS = [
304
+ "exits",
305
+ "replies",
306
+ "taps_forward",
307
+ "taps_back",
308
+ "views",
309
+ "reach"
310
+ ];
311
+ var METRIC_PRESETS = {
312
+ // Instagram account overview
313
+ INSTAGRAM_OVERVIEW: ["views", "reach", "accounts_engaged", "total_interactions"],
314
+ // Instagram content engagement
315
+ INSTAGRAM_ENGAGEMENT: ["likes", "comments", "shares", "saves"]
316
+ };
317
+
318
+ // providers/instagram/api/InstagramAPI.ts
319
+ var InstagramAPI = class {
320
+ constructor(config, accessToken) {
321
+ this.config = config;
322
+ this.accessToken = accessToken;
323
+ this.httpClient = new HttpClient({
324
+ baseURL: FACEBOOK_GRAPH_API_BASE_URL,
325
+ accessToken: this.accessToken
326
+ });
327
+ }
328
+ /**
329
+ * Generic request
330
+ */
331
+ async request(endpoint, options = {}) {
332
+ if (this.accessToken && !options.params?.access_token) {
333
+ options.params = {
334
+ ...options.params,
335
+ access_token: this.accessToken
336
+ };
337
+ }
338
+ return this.httpClient.request(endpoint, options);
339
+ }
340
+ /**
341
+ * GET request
342
+ */
343
+ async get(endpoint, params) {
344
+ return this.request(endpoint, { method: "GET", params });
345
+ }
346
+ /**
347
+ * POST request
348
+ */
349
+ async post(endpoint, body) {
350
+ return this.request(endpoint, { method: "POST", body });
351
+ }
352
+ /**
353
+ * PUT request
354
+ */
355
+ async put(endpoint, body) {
356
+ return this.request(endpoint, { method: "PUT", body });
357
+ }
358
+ /**
359
+ * DELETE request
360
+ */
361
+ async delete(endpoint) {
362
+ return this.request(endpoint, { method: "DELETE" });
363
+ }
364
+ /**
365
+ * Update access token
366
+ */
367
+ setAccessToken(token) {
368
+ this.accessToken = token;
369
+ this.httpClient.setAccessToken(token);
370
+ }
371
+ /**
372
+ * Get current access token
373
+ */
374
+ getAccessToken() {
375
+ return this.accessToken;
376
+ }
377
+ // ============= Instagram-specific methods =============
378
+ /**
379
+ * Get user's Instagram Business account (single account from first page)
380
+ */
381
+ async getAccount(pageAccessToken) {
382
+ try {
383
+ const token = pageAccessToken || this.accessToken;
384
+ if (!token) {
385
+ throw new APIError("Access token is required", 401, "NO_TOKEN");
386
+ }
387
+ const response = await this.get("/me/accounts", {
388
+ fields: "instagram_business_account",
389
+ access_token: token
390
+ });
391
+ if (!response.data || response.data.length === 0) {
392
+ throw new APIError(
393
+ "No Instagram business account found",
394
+ 404,
395
+ "NO_INSTAGRAM_ACCOUNT"
396
+ );
397
+ }
398
+ const instagramAccountId = response.data[0]?.instagram_business_account?.id;
399
+ if (!instagramAccountId) {
400
+ throw new APIError(
401
+ "No Instagram business account ID found",
402
+ 404,
403
+ "NO_INSTAGRAM_ACCOUNT_ID"
404
+ );
405
+ }
406
+ const account = await this.get(
407
+ `/${instagramAccountId}`,
408
+ {
409
+ fields: "id,username,name,profile_picture_url,followers_count,follows_count,media_count",
410
+ access_token: token
411
+ }
412
+ );
413
+ return account;
414
+ } catch (error) {
415
+ throw new APIError(
416
+ `Failed to fetch Instagram account: ${error instanceof Error ? error.message : "Unknown error"}`,
417
+ void 0,
418
+ "ACCOUNT_FETCH_ERROR",
419
+ error
420
+ );
421
+ }
422
+ }
423
+ /**
424
+ * Get all Instagram Business accounts linked to user's Facebook pages
425
+ * Returns all Instagram accounts from all connected Facebook pages
426
+ */
427
+ async getInstagramAccounts(userAccessToken) {
428
+ try {
429
+ const token = userAccessToken || this.accessToken;
430
+ if (!token) {
431
+ throw new APIError("Access token is required", 401, "NO_TOKEN");
432
+ }
433
+ const response = await this.get("/me/accounts", {
434
+ fields: "id,name,instagram_business_account{id,username,name,profile_picture_url,followers_count,follows_count,media_count}",
435
+ access_token: token
436
+ });
437
+ if (!response.data || response.data.length === 0) {
438
+ console.log(" \u2139\uFE0F No Facebook pages found");
439
+ return [];
440
+ }
441
+ const instagramAccounts = [];
442
+ for (const page of response.data) {
443
+ if (page.instagram_business_account) {
444
+ instagramAccounts.push({
445
+ id: page.instagram_business_account.id,
446
+ username: page.instagram_business_account.username,
447
+ name: page.instagram_business_account.name,
448
+ profile_picture_url: page.instagram_business_account.profile_picture_url,
449
+ followers_count: page.instagram_business_account.followers_count,
450
+ follows_count: page.instagram_business_account.follows_count,
451
+ media_count: page.instagram_business_account.media_count
452
+ });
453
+ }
454
+ }
455
+ console.log(` \u2705 Found ${instagramAccounts.length} Instagram account(s)`);
456
+ return instagramAccounts;
457
+ } catch (error) {
458
+ throw new APIError(
459
+ `Failed to fetch Instagram accounts: ${error instanceof Error ? error.message : "Unknown error"}`,
460
+ void 0,
461
+ "ACCOUNTS_FETCH_ERROR",
462
+ error
463
+ );
464
+ }
465
+ }
466
+ /**
467
+ * Get Instagram media
468
+ */
469
+ async getMedia(instagramAccountId, limit = 25) {
470
+ try {
471
+ const response = await this.get(
472
+ `/${instagramAccountId}/media`,
473
+ {
474
+ fields: "id,media_type,media_url,thumbnail_url,permalink,caption,timestamp,like_count,comments_count",
475
+ limit
476
+ }
477
+ );
478
+ return response.data;
479
+ } catch (error) {
480
+ throw new APIError(
481
+ `Failed to fetch Instagram media: ${error instanceof Error ? error.message : "Unknown error"}`,
482
+ void 0,
483
+ "MEDIA_FETCH_ERROR",
484
+ error
485
+ );
486
+ }
487
+ }
488
+ /**
489
+ * Publish photo to Instagram (2-step process)
490
+ */
491
+ async publishPhoto(params) {
492
+ const { instagramAccountId, imageUrl, caption } = params;
493
+ if (!imageUrl) {
494
+ throw new APIError(
495
+ "Image URL is required for photo posts",
496
+ 400,
497
+ "INVALID_PARAMS"
498
+ );
499
+ }
500
+ try {
501
+ const containerResponse = await this.post(
502
+ `/${instagramAccountId}/media`,
503
+ {
504
+ image_url: imageUrl,
505
+ caption: caption || ""
506
+ }
507
+ );
508
+ const publishResponse = await this.post(
509
+ `/${instagramAccountId}/media_publish`,
510
+ {
511
+ creation_id: containerResponse.id
512
+ }
513
+ );
514
+ return publishResponse;
515
+ } catch (error) {
516
+ throw new APIError(
517
+ `Failed to publish photo: ${error instanceof Error ? error.message : "Unknown error"}`,
518
+ void 0,
519
+ "PHOTO_PUBLISH_ERROR",
520
+ error
521
+ );
522
+ }
523
+ }
524
+ /**
525
+ * Publish video to Instagram (2-step process)
526
+ */
527
+ async publishVideo(params) {
528
+ const { instagramAccountId, videoUrl, caption } = params;
529
+ if (!videoUrl) {
530
+ throw new APIError(
531
+ "Video URL is required for video posts",
532
+ 400,
533
+ "INVALID_PARAMS"
534
+ );
535
+ }
536
+ try {
537
+ const containerResponse = await this.post(
538
+ `/${instagramAccountId}/media`,
539
+ {
540
+ media_type: "VIDEO",
541
+ video_url: videoUrl,
542
+ caption: caption || ""
543
+ }
544
+ );
545
+ const publishResponse = await this.post(
546
+ `/${instagramAccountId}/media_publish`,
547
+ {
548
+ creation_id: containerResponse.id
549
+ }
550
+ );
551
+ return publishResponse;
552
+ } catch (error) {
553
+ throw new APIError(
554
+ `Failed to publish video: ${error instanceof Error ? error.message : "Unknown error"}`,
555
+ void 0,
556
+ "VIDEO_PUBLISH_ERROR",
557
+ error
558
+ );
559
+ }
560
+ }
561
+ /**
562
+ * Delete Instagram media
563
+ */
564
+ async deleteMedia(mediaId) {
565
+ try {
566
+ const response = await this.delete(
567
+ `/${mediaId}`
568
+ );
569
+ return response.success === true;
570
+ } catch (error) {
571
+ throw new APIError(
572
+ `Failed to delete media: ${error instanceof Error ? error.message : "Unknown error"}`,
573
+ void 0,
574
+ "MEDIA_DELETE_ERROR",
575
+ error
576
+ );
577
+ }
578
+ }
579
+ /**
580
+ * Get Instagram account insights
581
+ */
582
+ async getAccountInsights(instagramAccountId, params) {
583
+ try {
584
+ const { metric, period, metric_type, since, until } = params;
585
+ const response = await this.get(
586
+ `/${instagramAccountId}/insights`,
587
+ {
588
+ metric: metric.join(","),
589
+ period: period || "day",
590
+ metric_type: metric_type || "total_value",
591
+ ...since && { since },
592
+ ...until && { until }
593
+ }
594
+ );
595
+ return response;
596
+ } catch (error) {
597
+ throw new APIError(
598
+ `Failed to fetch insights: ${error instanceof Error ? error.message : "Unknown error"}`,
599
+ void 0,
600
+ "INSIGHTS_FETCH_ERROR",
601
+ error
602
+ );
603
+ }
604
+ }
605
+ /**
606
+ * Get specific media insights
607
+ */
608
+ async getMediaInsights(mediaId, metrics) {
609
+ try {
610
+ const response = await this.get(
611
+ `/${mediaId}/insights`,
612
+ {
613
+ metric: metrics.join(",")
614
+ }
615
+ );
616
+ return response;
617
+ } catch (error) {
618
+ throw new APIError(
619
+ `Failed to fetch media insights: ${error instanceof Error ? error.message : "Unknown error"}`,
620
+ void 0,
621
+ "MEDIA_INSIGHTS_ERROR",
622
+ error
623
+ );
624
+ }
625
+ }
626
+ // ============= Enhanced Insights Methods =============
627
+ /**
628
+ * Get account insights with default metrics
629
+ * Uses updated metrics (views instead of impressions)
630
+ * @param instagramAccountId - Instagram Account ID
631
+ * @param period - Period for metrics
632
+ * @returns Account insights
633
+ */
634
+ async getAccountInsightsOverview(instagramAccountId, period = "days_28") {
635
+ return this.getAccountInsights(instagramAccountId, {
636
+ metric: [...METRIC_PRESETS.INSTAGRAM_OVERVIEW],
637
+ period,
638
+ metric_type: "total_value"
639
+ });
640
+ }
641
+ /**
642
+ * Get account summary with parsed values
643
+ * @param instagramAccountId - Instagram Account ID
644
+ * @param period - Period for metrics
645
+ * @returns Parsed account summary
646
+ */
647
+ async getAccountSummary(instagramAccountId, period = "days_28") {
648
+ try {
649
+ const account = await this.get(`/${instagramAccountId}`, {
650
+ fields: "id,username,followers_count"
651
+ });
652
+ const insights = await this.getAccountInsightsOverview(instagramAccountId, period);
653
+ const summary = {
654
+ id: account.id,
655
+ username: account.username,
656
+ followers_count: account.followers_count || 0
657
+ };
658
+ for (const item of insights.data) {
659
+ const value = item.total_value?.value ?? item.values?.[0]?.value;
660
+ if (typeof value !== "number") continue;
661
+ switch (item.name) {
662
+ case "views":
663
+ summary.views = value;
664
+ break;
665
+ case "reach":
666
+ summary.reach = value;
667
+ break;
668
+ case "accounts_engaged":
669
+ summary.accounts_engaged = value;
670
+ break;
671
+ case "total_interactions":
672
+ summary.total_interactions = value;
673
+ break;
674
+ }
675
+ }
676
+ return summary;
677
+ } catch (error) {
678
+ throw new APIError(
679
+ `Failed to fetch account summary: ${error instanceof Error ? error.message : "Unknown error"}`,
680
+ void 0,
681
+ "ACCOUNT_SUMMARY_ERROR",
682
+ error
683
+ );
684
+ }
685
+ }
686
+ /**
687
+ * Get media insights based on media type
688
+ * Automatically selects appropriate metrics
689
+ * @param mediaId - Media ID
690
+ * @param mediaType - Type of media
691
+ * @returns Media insights
692
+ */
693
+ async getMediaInsightsByType(mediaId, mediaType) {
694
+ let metrics;
695
+ switch (mediaType) {
696
+ case "REELS":
697
+ metrics = INSTAGRAM_REELS_METRICS;
698
+ break;
699
+ case "VIDEO":
700
+ metrics = [...INSTAGRAM_MEDIA_METRICS_COMMON, "plays"];
701
+ break;
702
+ default:
703
+ metrics = INSTAGRAM_MEDIA_METRICS_COMMON;
704
+ }
705
+ return this.getMediaInsights(mediaId, [...metrics]);
706
+ }
707
+ /**
708
+ * Get media insights with parsed values
709
+ * @param mediaId - Media ID
710
+ * @param mediaType - Type of media
711
+ * @returns Parsed media insights
712
+ */
713
+ async getMediaInsightsParsed(mediaId, mediaType = "IMAGE") {
714
+ try {
715
+ const response = await this.getMediaInsightsByType(mediaId, mediaType);
716
+ const insights = {
717
+ id: mediaId,
718
+ media_type: mediaType
719
+ };
720
+ for (const item of response.data) {
721
+ const value = item.total_value?.value ?? item.values?.[0]?.value;
722
+ if (typeof value !== "number") continue;
723
+ switch (item.name) {
724
+ case "views":
725
+ insights.views = value;
726
+ break;
727
+ case "reach":
728
+ insights.reach = value;
729
+ break;
730
+ case "likes":
731
+ insights.likes = value;
732
+ break;
733
+ case "comments":
734
+ insights.comments = value;
735
+ break;
736
+ case "shares":
737
+ insights.shares = value;
738
+ break;
739
+ case "saved":
740
+ insights.saves = value;
741
+ break;
742
+ case "plays":
743
+ insights.plays = value;
744
+ break;
745
+ case "total_interactions":
746
+ insights.total_interactions = value;
747
+ break;
748
+ }
749
+ }
750
+ return insights;
751
+ } catch (error) {
752
+ throw new APIError(
753
+ `Failed to fetch parsed media insights: ${error instanceof Error ? error.message : "Unknown error"}`,
754
+ void 0,
755
+ "MEDIA_INSIGHTS_PARSED_ERROR",
756
+ error
757
+ );
758
+ }
759
+ }
760
+ /**
761
+ * Get story insights
762
+ * @param storyId - Story media ID
763
+ * @returns Story insights
764
+ */
765
+ async getStoryInsights(storyId) {
766
+ return this.getMediaInsights(storyId, [...INSTAGRAM_STORIES_METRICS]);
767
+ }
768
+ /**
769
+ * Get reels insights
770
+ * @param reelId - Reel media ID
771
+ * @returns Reel insights
772
+ */
773
+ async getReelInsights(reelId) {
774
+ return this.getMediaInsights(reelId, [...INSTAGRAM_REELS_METRICS]);
775
+ }
776
+ /**
777
+ * Get engagement metrics for account
778
+ * @param instagramAccountId - Instagram Account ID
779
+ * @param period - Period for metrics
780
+ * @returns Engagement insights
781
+ */
782
+ async getEngagementInsights(instagramAccountId, period = "days_28") {
783
+ return this.getAccountInsights(instagramAccountId, {
784
+ metric: [...METRIC_PRESETS.INSTAGRAM_ENGAGEMENT],
785
+ period,
786
+ metric_type: "total_value"
787
+ });
788
+ }
789
+ /**
790
+ * Get demographics insights for account
791
+ * @param instagramAccountId - Instagram Account ID
792
+ * @param breakdown - Demographic breakdown type
793
+ * @returns Demographics insights
794
+ */
795
+ async getDemographicsInsights(instagramAccountId, breakdown = "country") {
796
+ try {
797
+ const response = await this.get(
798
+ `/${instagramAccountId}/insights`,
799
+ {
800
+ metric: "follower_demographics",
801
+ period: "lifetime",
802
+ metric_type: "total_value",
803
+ breakdown
804
+ }
805
+ );
806
+ return response;
807
+ } catch (error) {
808
+ throw new APIError(
809
+ `Failed to fetch demographics insights: ${error instanceof Error ? error.message : "Unknown error"}`,
810
+ void 0,
811
+ "DEMOGRAPHICS_ERROR",
812
+ error
813
+ );
814
+ }
815
+ }
816
+ /**
817
+ * Get current API version (read-only)
818
+ */
819
+ getApiVersion() {
820
+ return FACEBOOK_GRAPH_API_VERSION;
821
+ }
822
+ };
823
+
824
+ // providers/instagram/InstagramProvider.ts
825
+ var InstagramProvider = class {
826
+ constructor(config) {
827
+ this.name = "instagram";
828
+ this.config = config;
829
+ this.auth = new InstagramAuth(config);
830
+ this.api = new InstagramAPI(config);
831
+ }
832
+ /**
833
+ * Create new API instance with access token
834
+ */
835
+ createAPIClient(accessToken) {
836
+ return new InstagramAPI(this.config, accessToken);
837
+ }
838
+ /**
839
+ * Update access token of existing API client
840
+ */
841
+ setAccessToken(accessToken) {
842
+ this.api.setAccessToken(accessToken);
843
+ }
844
+ /**
845
+ * Get current access token
846
+ */
847
+ getAccessToken() {
848
+ return this.api.getAccessToken();
849
+ }
850
+ };
851
+
852
+ // providers/instagram/types/index.ts
853
+ var InstagramScopes = /* @__PURE__ */ ((InstagramScopes2) => {
854
+ InstagramScopes2["BASIC"] = "instagram_basic";
855
+ InstagramScopes2["CONTENT_PUBLISH"] = "instagram_content_publish";
856
+ InstagramScopes2["MANAGE_COMMENTS"] = "instagram_manage_comments";
857
+ InstagramScopes2["MANAGE_INSIGHTS"] = "instagram_manage_insights";
858
+ InstagramScopes2["MANAGE_MESSAGES"] = "instagram_manage_messages";
859
+ InstagramScopes2["SHOPPING_TAG_PRODUCTS"] = "instagram_shopping_tag_products";
860
+ return InstagramScopes2;
861
+ })(InstagramScopes || {});
862
+
863
+ export { InstagramAPI, InstagramAuth, InstagramProvider, InstagramScopes };
4
864
  //# sourceMappingURL=index.mjs.map
5
865
  //# sourceMappingURL=index.mjs.map