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