@dracoonghost/trndup-sdk 1.3.24 → 1.3.26

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.
package/dist/index.d.mts CHANGED
@@ -1401,6 +1401,259 @@ declare namespace Insights {
1401
1401
  /** Days per comparison period (14-90, default: 30) */
1402
1402
  period?: number;
1403
1403
  }
1404
+ interface TopPostData {
1405
+ mediaId: string;
1406
+ caption: string | null;
1407
+ mediaType: 'IMAGE' | 'VIDEO' | 'CAROUSEL_ALBUM' | 'REELS';
1408
+ thumbnailUrl: string | null;
1409
+ permalink: string;
1410
+ postedAt: string;
1411
+ ageInDays: number;
1412
+ }
1413
+ interface TopPostMetrics {
1414
+ reach: number;
1415
+ views: number;
1416
+ likes: number;
1417
+ comments: number;
1418
+ shares: number;
1419
+ saves: number;
1420
+ engagementRate: number;
1421
+ }
1422
+ interface TopPostComparison {
1423
+ vsAccountAverage: {
1424
+ reach: number;
1425
+ engagement: number;
1426
+ description: string;
1427
+ };
1428
+ standoutReasons: string[];
1429
+ }
1430
+ interface BestPerformingPostData {
1431
+ period: {
1432
+ start: string;
1433
+ end: string;
1434
+ days: number;
1435
+ };
1436
+ topPost: TopPostData;
1437
+ metrics: TopPostMetrics;
1438
+ comparison: TopPostComparison;
1439
+ insight: string;
1440
+ runnersUp: Array<{
1441
+ mediaId: string;
1442
+ caption: string | null;
1443
+ reach: number;
1444
+ thumbnailUrl: string | null;
1445
+ }>;
1446
+ }
1447
+ type BestPerformingPostResponse = InsufficientDataResponse | {
1448
+ hasData: true;
1449
+ data: BestPerformingPostData;
1450
+ _meta: InsightMeta;
1451
+ };
1452
+ type PostingConsistencyStatus = 'excellent' | 'good' | 'needs_improvement' | 'poor' | 'inactive';
1453
+ interface MonthlyPostData {
1454
+ month: string;
1455
+ posts: number;
1456
+ avgGap: number | null;
1457
+ }
1458
+ interface PostingConsistencyData {
1459
+ period: {
1460
+ start: string;
1461
+ end: string;
1462
+ days: number;
1463
+ };
1464
+ consistencyScore: number;
1465
+ status: PostingConsistencyStatus;
1466
+ metrics: {
1467
+ totalPosts: number;
1468
+ avgDaysBetweenPosts: number;
1469
+ postVariance: number;
1470
+ daysSinceLastPost: number;
1471
+ lastPostDate: string | null;
1472
+ };
1473
+ pattern: {
1474
+ isRegular: boolean;
1475
+ typicalGap: string;
1476
+ longestStreak: number;
1477
+ currentStreak: number;
1478
+ trend: 'increasing' | 'stable' | 'decreasing';
1479
+ trendDescription: string;
1480
+ };
1481
+ monthlyBreakdown: MonthlyPostData[];
1482
+ recommendation: {
1483
+ suggested: string;
1484
+ current: string;
1485
+ reason: string;
1486
+ };
1487
+ insight: string;
1488
+ recommendations: string[];
1489
+ }
1490
+ type PostingConsistencyResponse = InsufficientDataResponse | {
1491
+ hasData: true;
1492
+ data: PostingConsistencyData;
1493
+ _meta: InsightMeta;
1494
+ };
1495
+ type FollowerQualityLabel = 'excellent' | 'good' | 'fair' | 'needs_attention' | 'concerning';
1496
+ interface FollowerQualityData {
1497
+ period: {
1498
+ start: string;
1499
+ end: string;
1500
+ days: number;
1501
+ };
1502
+ qualityScore: number;
1503
+ scoreLabel: FollowerQualityLabel;
1504
+ metrics: {
1505
+ followsGained: number;
1506
+ unfollows: number;
1507
+ netFollowers: number;
1508
+ retentionRate: number;
1509
+ engagementPerFollower: number;
1510
+ reachPerFollower: number;
1511
+ accountsEngaged: number;
1512
+ };
1513
+ trend: {
1514
+ scoreChange: number;
1515
+ direction: 'improving' | 'stable' | 'declining';
1516
+ description: string;
1517
+ };
1518
+ insight: string;
1519
+ recommendations: string[];
1520
+ }
1521
+ type FollowerQualityResponse = InsufficientDataResponse | {
1522
+ hasData: true;
1523
+ data: FollowerQualityData;
1524
+ _meta: InsightMeta;
1525
+ };
1526
+ type InstagramMomentumStatus = 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping';
1527
+ type InstagramMomentumTrend = 'accelerating' | 'stable' | 'decelerating';
1528
+ interface InstagramMetricChange {
1529
+ current: number;
1530
+ previous: number;
1531
+ change: number;
1532
+ }
1533
+ interface InstagramMomentumData {
1534
+ score: number;
1535
+ rawChange: number;
1536
+ status: InstagramMomentumStatus;
1537
+ trend: InstagramMomentumTrend;
1538
+ previousScore: number | null;
1539
+ period: {
1540
+ current: {
1541
+ start: string;
1542
+ end: string;
1543
+ };
1544
+ previous: {
1545
+ start: string;
1546
+ end: string;
1547
+ };
1548
+ };
1549
+ breakdown: {
1550
+ reach: InstagramMetricChange;
1551
+ engagement: InstagramMetricChange;
1552
+ followers: InstagramMetricChange;
1553
+ profileViews: InstagramMetricChange;
1554
+ };
1555
+ insight: string;
1556
+ topDrivers: string[];
1557
+ }
1558
+ type InstagramMomentumResponse = InsufficientDataResponse | {
1559
+ hasData: true;
1560
+ data: InstagramMomentumData;
1561
+ _meta: InsightMeta;
1562
+ };
1563
+ type EngagementStyle = 'passive' | 'active' | 'viral' | 'valuable';
1564
+ interface EngagementMetricBreakdown {
1565
+ count: number;
1566
+ percent: number;
1567
+ trend: number;
1568
+ }
1569
+ interface EngagementBreakdownData {
1570
+ period: {
1571
+ start: string;
1572
+ end: string;
1573
+ days: number;
1574
+ };
1575
+ totalEngagement: number;
1576
+ breakdown: {
1577
+ likes: EngagementMetricBreakdown;
1578
+ comments: EngagementMetricBreakdown;
1579
+ shares: EngagementMetricBreakdown;
1580
+ saves: EngagementMetricBreakdown;
1581
+ };
1582
+ engagementStyle: EngagementStyle;
1583
+ analysis: {
1584
+ strongestType: string;
1585
+ weakestType: string;
1586
+ opportunity: string;
1587
+ };
1588
+ insight: string;
1589
+ recommendations: string[];
1590
+ }
1591
+ type EngagementBreakdownResponse = InsufficientDataResponse | {
1592
+ hasData: true;
1593
+ data: EngagementBreakdownData;
1594
+ _meta: InsightMeta;
1595
+ };
1596
+ type InstagramHealthLabel = 'excellent' | 'good' | 'fair' | 'needs_attention' | 'poor';
1597
+ interface HealthScoreComponent {
1598
+ score: number;
1599
+ label: string;
1600
+ trend: number;
1601
+ }
1602
+ interface InstagramHealthScoreData {
1603
+ period: {
1604
+ start: string;
1605
+ end: string;
1606
+ days: number;
1607
+ };
1608
+ overall: number;
1609
+ label: InstagramHealthLabel;
1610
+ components: {
1611
+ consistency: HealthScoreComponent;
1612
+ engagement: HealthScoreComponent;
1613
+ growth: HealthScoreComponent;
1614
+ reach: HealthScoreComponent;
1615
+ };
1616
+ metrics: {
1617
+ postsPerWeek: number;
1618
+ avgEngagementRate: number;
1619
+ followerGrowthRate: number;
1620
+ avgReachPerPost: number;
1621
+ };
1622
+ percentageChanges: {
1623
+ overall: number;
1624
+ components: {
1625
+ consistency: number;
1626
+ engagement: number;
1627
+ growth: number;
1628
+ reach: number;
1629
+ };
1630
+ };
1631
+ insight: string;
1632
+ recommendations: string[];
1633
+ }
1634
+ type InstagramHealthScoreResponse = InsufficientDataResponse | {
1635
+ hasData: true;
1636
+ data: InstagramHealthScoreData;
1637
+ _meta: InsightMeta;
1638
+ };
1639
+ interface InstagramAllInsightsData {
1640
+ bestPost: BestPerformingPostResponse;
1641
+ consistency: PostingConsistencyResponse;
1642
+ followerQuality: FollowerQualityResponse;
1643
+ momentum: InstagramMomentumResponse;
1644
+ engagement: EngagementBreakdownResponse;
1645
+ health: InstagramHealthScoreResponse;
1646
+ }
1647
+ interface InstagramAllInsightsResponse {
1648
+ data: InstagramAllInsightsData;
1649
+ meta: {
1650
+ available: string[];
1651
+ };
1652
+ }
1653
+ interface GetInstagramInsightParams {
1654
+ /** Time range (e.g., "30d") */
1655
+ range?: string;
1656
+ }
1404
1657
  }
1405
1658
  declare namespace Activity {
1406
1659
  /**
@@ -1566,6 +1819,10 @@ declare class TrndUpClient {
1566
1819
  patch<T = unknown>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1567
1820
  delete<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
1568
1821
  private request;
1822
+ private logRequest;
1823
+ private logResponse;
1824
+ private logError;
1825
+ private truncateObject;
1569
1826
  private buildUrl;
1570
1827
  private buildHeaders;
1571
1828
  private handleResponse;
package/dist/index.d.ts CHANGED
@@ -1401,6 +1401,259 @@ declare namespace Insights {
1401
1401
  /** Days per comparison period (14-90, default: 30) */
1402
1402
  period?: number;
1403
1403
  }
1404
+ interface TopPostData {
1405
+ mediaId: string;
1406
+ caption: string | null;
1407
+ mediaType: 'IMAGE' | 'VIDEO' | 'CAROUSEL_ALBUM' | 'REELS';
1408
+ thumbnailUrl: string | null;
1409
+ permalink: string;
1410
+ postedAt: string;
1411
+ ageInDays: number;
1412
+ }
1413
+ interface TopPostMetrics {
1414
+ reach: number;
1415
+ views: number;
1416
+ likes: number;
1417
+ comments: number;
1418
+ shares: number;
1419
+ saves: number;
1420
+ engagementRate: number;
1421
+ }
1422
+ interface TopPostComparison {
1423
+ vsAccountAverage: {
1424
+ reach: number;
1425
+ engagement: number;
1426
+ description: string;
1427
+ };
1428
+ standoutReasons: string[];
1429
+ }
1430
+ interface BestPerformingPostData {
1431
+ period: {
1432
+ start: string;
1433
+ end: string;
1434
+ days: number;
1435
+ };
1436
+ topPost: TopPostData;
1437
+ metrics: TopPostMetrics;
1438
+ comparison: TopPostComparison;
1439
+ insight: string;
1440
+ runnersUp: Array<{
1441
+ mediaId: string;
1442
+ caption: string | null;
1443
+ reach: number;
1444
+ thumbnailUrl: string | null;
1445
+ }>;
1446
+ }
1447
+ type BestPerformingPostResponse = InsufficientDataResponse | {
1448
+ hasData: true;
1449
+ data: BestPerformingPostData;
1450
+ _meta: InsightMeta;
1451
+ };
1452
+ type PostingConsistencyStatus = 'excellent' | 'good' | 'needs_improvement' | 'poor' | 'inactive';
1453
+ interface MonthlyPostData {
1454
+ month: string;
1455
+ posts: number;
1456
+ avgGap: number | null;
1457
+ }
1458
+ interface PostingConsistencyData {
1459
+ period: {
1460
+ start: string;
1461
+ end: string;
1462
+ days: number;
1463
+ };
1464
+ consistencyScore: number;
1465
+ status: PostingConsistencyStatus;
1466
+ metrics: {
1467
+ totalPosts: number;
1468
+ avgDaysBetweenPosts: number;
1469
+ postVariance: number;
1470
+ daysSinceLastPost: number;
1471
+ lastPostDate: string | null;
1472
+ };
1473
+ pattern: {
1474
+ isRegular: boolean;
1475
+ typicalGap: string;
1476
+ longestStreak: number;
1477
+ currentStreak: number;
1478
+ trend: 'increasing' | 'stable' | 'decreasing';
1479
+ trendDescription: string;
1480
+ };
1481
+ monthlyBreakdown: MonthlyPostData[];
1482
+ recommendation: {
1483
+ suggested: string;
1484
+ current: string;
1485
+ reason: string;
1486
+ };
1487
+ insight: string;
1488
+ recommendations: string[];
1489
+ }
1490
+ type PostingConsistencyResponse = InsufficientDataResponse | {
1491
+ hasData: true;
1492
+ data: PostingConsistencyData;
1493
+ _meta: InsightMeta;
1494
+ };
1495
+ type FollowerQualityLabel = 'excellent' | 'good' | 'fair' | 'needs_attention' | 'concerning';
1496
+ interface FollowerQualityData {
1497
+ period: {
1498
+ start: string;
1499
+ end: string;
1500
+ days: number;
1501
+ };
1502
+ qualityScore: number;
1503
+ scoreLabel: FollowerQualityLabel;
1504
+ metrics: {
1505
+ followsGained: number;
1506
+ unfollows: number;
1507
+ netFollowers: number;
1508
+ retentionRate: number;
1509
+ engagementPerFollower: number;
1510
+ reachPerFollower: number;
1511
+ accountsEngaged: number;
1512
+ };
1513
+ trend: {
1514
+ scoreChange: number;
1515
+ direction: 'improving' | 'stable' | 'declining';
1516
+ description: string;
1517
+ };
1518
+ insight: string;
1519
+ recommendations: string[];
1520
+ }
1521
+ type FollowerQualityResponse = InsufficientDataResponse | {
1522
+ hasData: true;
1523
+ data: FollowerQualityData;
1524
+ _meta: InsightMeta;
1525
+ };
1526
+ type InstagramMomentumStatus = 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping';
1527
+ type InstagramMomentumTrend = 'accelerating' | 'stable' | 'decelerating';
1528
+ interface InstagramMetricChange {
1529
+ current: number;
1530
+ previous: number;
1531
+ change: number;
1532
+ }
1533
+ interface InstagramMomentumData {
1534
+ score: number;
1535
+ rawChange: number;
1536
+ status: InstagramMomentumStatus;
1537
+ trend: InstagramMomentumTrend;
1538
+ previousScore: number | null;
1539
+ period: {
1540
+ current: {
1541
+ start: string;
1542
+ end: string;
1543
+ };
1544
+ previous: {
1545
+ start: string;
1546
+ end: string;
1547
+ };
1548
+ };
1549
+ breakdown: {
1550
+ reach: InstagramMetricChange;
1551
+ engagement: InstagramMetricChange;
1552
+ followers: InstagramMetricChange;
1553
+ profileViews: InstagramMetricChange;
1554
+ };
1555
+ insight: string;
1556
+ topDrivers: string[];
1557
+ }
1558
+ type InstagramMomentumResponse = InsufficientDataResponse | {
1559
+ hasData: true;
1560
+ data: InstagramMomentumData;
1561
+ _meta: InsightMeta;
1562
+ };
1563
+ type EngagementStyle = 'passive' | 'active' | 'viral' | 'valuable';
1564
+ interface EngagementMetricBreakdown {
1565
+ count: number;
1566
+ percent: number;
1567
+ trend: number;
1568
+ }
1569
+ interface EngagementBreakdownData {
1570
+ period: {
1571
+ start: string;
1572
+ end: string;
1573
+ days: number;
1574
+ };
1575
+ totalEngagement: number;
1576
+ breakdown: {
1577
+ likes: EngagementMetricBreakdown;
1578
+ comments: EngagementMetricBreakdown;
1579
+ shares: EngagementMetricBreakdown;
1580
+ saves: EngagementMetricBreakdown;
1581
+ };
1582
+ engagementStyle: EngagementStyle;
1583
+ analysis: {
1584
+ strongestType: string;
1585
+ weakestType: string;
1586
+ opportunity: string;
1587
+ };
1588
+ insight: string;
1589
+ recommendations: string[];
1590
+ }
1591
+ type EngagementBreakdownResponse = InsufficientDataResponse | {
1592
+ hasData: true;
1593
+ data: EngagementBreakdownData;
1594
+ _meta: InsightMeta;
1595
+ };
1596
+ type InstagramHealthLabel = 'excellent' | 'good' | 'fair' | 'needs_attention' | 'poor';
1597
+ interface HealthScoreComponent {
1598
+ score: number;
1599
+ label: string;
1600
+ trend: number;
1601
+ }
1602
+ interface InstagramHealthScoreData {
1603
+ period: {
1604
+ start: string;
1605
+ end: string;
1606
+ days: number;
1607
+ };
1608
+ overall: number;
1609
+ label: InstagramHealthLabel;
1610
+ components: {
1611
+ consistency: HealthScoreComponent;
1612
+ engagement: HealthScoreComponent;
1613
+ growth: HealthScoreComponent;
1614
+ reach: HealthScoreComponent;
1615
+ };
1616
+ metrics: {
1617
+ postsPerWeek: number;
1618
+ avgEngagementRate: number;
1619
+ followerGrowthRate: number;
1620
+ avgReachPerPost: number;
1621
+ };
1622
+ percentageChanges: {
1623
+ overall: number;
1624
+ components: {
1625
+ consistency: number;
1626
+ engagement: number;
1627
+ growth: number;
1628
+ reach: number;
1629
+ };
1630
+ };
1631
+ insight: string;
1632
+ recommendations: string[];
1633
+ }
1634
+ type InstagramHealthScoreResponse = InsufficientDataResponse | {
1635
+ hasData: true;
1636
+ data: InstagramHealthScoreData;
1637
+ _meta: InsightMeta;
1638
+ };
1639
+ interface InstagramAllInsightsData {
1640
+ bestPost: BestPerformingPostResponse;
1641
+ consistency: PostingConsistencyResponse;
1642
+ followerQuality: FollowerQualityResponse;
1643
+ momentum: InstagramMomentumResponse;
1644
+ engagement: EngagementBreakdownResponse;
1645
+ health: InstagramHealthScoreResponse;
1646
+ }
1647
+ interface InstagramAllInsightsResponse {
1648
+ data: InstagramAllInsightsData;
1649
+ meta: {
1650
+ available: string[];
1651
+ };
1652
+ }
1653
+ interface GetInstagramInsightParams {
1654
+ /** Time range (e.g., "30d") */
1655
+ range?: string;
1656
+ }
1404
1657
  }
1405
1658
  declare namespace Activity {
1406
1659
  /**
@@ -1566,6 +1819,10 @@ declare class TrndUpClient {
1566
1819
  patch<T = unknown>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1567
1820
  delete<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
1568
1821
  private request;
1822
+ private logRequest;
1823
+ private logResponse;
1824
+ private logError;
1825
+ private truncateObject;
1569
1826
  private buildUrl;
1570
1827
  private buildHeaders;
1571
1828
  private handleResponse;
package/dist/index.js CHANGED
@@ -83,19 +83,27 @@ var TrndUpClient = class {
83
83
  () => controller.abort(),
84
84
  timeout ?? this.config.timeout
85
85
  );
86
+ const startTime = Date.now();
86
87
  try {
87
88
  if (this.config.debug) {
88
- console.log(`[TrndUp SDK] ${method} ${url}`, { body, headers: requestHeaders });
89
+ this.logRequest(method, url, body);
89
90
  }
90
91
  const response = await fetch(url, {
91
92
  ...init,
92
93
  signal: signal ?? controller.signal
93
94
  });
94
95
  clearTimeout(timeoutId);
95
- return await this.handleResponse(response, path);
96
+ const result = await this.handleResponse(response, path);
97
+ if (this.config.debug) {
98
+ this.logResponse(method, path, response.status, result, startTime);
99
+ }
100
+ return result;
96
101
  } catch (error) {
97
102
  clearTimeout(timeoutId);
98
103
  if (error instanceof TrndUpApiError) {
104
+ if (this.config.debug) {
105
+ this.logError(method, path, error, startTime);
106
+ }
99
107
  throw error;
100
108
  }
101
109
  const networkError = new TrndUpNetworkError(
@@ -103,11 +111,56 @@ var TrndUpClient = class {
103
111
  path
104
112
  );
105
113
  if (this.config.debug) {
106
- console.error("[TrndUp SDK] Network error:", networkError);
114
+ this.logError(method, path, networkError, startTime);
107
115
  }
108
116
  throw networkError;
109
117
  }
110
118
  }
119
+ // =============================================================================
120
+ // LOGGING HELPERS
121
+ // =============================================================================
122
+ logRequest(method, url, body) {
123
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 12);
124
+ const bodyPreview = body ? this.truncateObject(body, 200) : void 0;
125
+ console.log(
126
+ `\x1B[36m[${timestamp}]\x1B[0m \x1B[33m\u2192 ${method}\x1B[0m ${url}` + (bodyPreview ? `
127
+ \x1B[90mbody:\x1B[0m ${bodyPreview}` : "")
128
+ );
129
+ }
130
+ logResponse(method, path, status, data, startTime) {
131
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 12);
132
+ const duration = Date.now() - startTime;
133
+ const statusColor = status >= 200 && status < 300 ? "\x1B[32m" : "\x1B[31m";
134
+ const dataPreview = this.truncateObject(data, 300);
135
+ console.log(
136
+ `\x1B[36m[${timestamp}]\x1B[0m ${statusColor}\u2190 ${status}\x1B[0m ${method} ${path} \x1B[90m(${duration}ms)\x1B[0m
137
+ \x1B[90mdata:\x1B[0m ${dataPreview}`
138
+ );
139
+ }
140
+ logError(method, path, error, startTime) {
141
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 12);
142
+ const duration = Date.now() - startTime;
143
+ if (error instanceof TrndUpApiError) {
144
+ console.log(
145
+ `\x1B[36m[${timestamp}]\x1B[0m \x1B[31m\u2715 ${error.status}\x1B[0m ${method} ${path} \x1B[90m(${duration}ms)\x1B[0m
146
+ \x1B[31merror:\x1B[0m ${error.code || "UNKNOWN"} - ${error.message}`
147
+ );
148
+ } else {
149
+ console.log(
150
+ `\x1B[36m[${timestamp}]\x1B[0m \x1B[31m\u2715 NETWORK\x1B[0m ${method} ${path} \x1B[90m(${duration}ms)\x1B[0m
151
+ \x1B[31merror:\x1B[0m ${error.message}`
152
+ );
153
+ }
154
+ }
155
+ truncateObject(obj, maxLength) {
156
+ try {
157
+ const str = JSON.stringify(obj);
158
+ if (str.length <= maxLength) return str;
159
+ return str.slice(0, maxLength) + "...";
160
+ } catch {
161
+ return "[Unable to serialize]";
162
+ }
163
+ }
111
164
  buildUrl(path, params) {
112
165
  const url = new URL(`${this.config.baseUrl}${path}`);
113
166
  if (params) {
@@ -164,9 +217,6 @@ var TrndUpClient = class {
164
217
  if (apiError.isAuthError() && this.config.onAuthFailure) {
165
218
  await this.config.onAuthFailure();
166
219
  }
167
- if (this.config.debug) {
168
- console.error("[TrndUp SDK] API error:", apiError);
169
- }
170
220
  throw apiError;
171
221
  }
172
222
  if (isJson) {