@dracoonghost/trndup-sdk 1.3.12 → 1.3.14
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/README.md +5 -5
- package/dist/index.d.mts +262 -2
- package/dist/index.d.ts +262 -2
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,13 +8,13 @@ Official TypeScript SDK for the TrndUp API with Firebase authentication support.
|
|
|
8
8
|
# In your mobile app
|
|
9
9
|
npm install file:../trndup-service/src/sdk
|
|
10
10
|
# or when published
|
|
11
|
-
npm install @trndup
|
|
11
|
+
npm install @dracoonghost/trndup-sdk
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Quick Start
|
|
15
15
|
|
|
16
16
|
```typescript
|
|
17
|
-
import { TrndUpSDK } from '@trndup
|
|
17
|
+
import { TrndUpSDK } from '@dracoonghost/trndup-sdk';
|
|
18
18
|
import auth from '@react-native-firebase/auth';
|
|
19
19
|
|
|
20
20
|
// Initialize SDK
|
|
@@ -132,7 +132,7 @@ const trending = await sdk.insights.getTrending();
|
|
|
132
132
|
## Error Handling
|
|
133
133
|
|
|
134
134
|
```typescript
|
|
135
|
-
import { TrndUpApiError, TrndUpNetworkError } from '@trndup
|
|
135
|
+
import { TrndUpApiError, TrndUpNetworkError } from '@dracoonghost/trndup-sdk';
|
|
136
136
|
|
|
137
137
|
try {
|
|
138
138
|
await sdk.youtube.getVideos();
|
|
@@ -191,7 +191,7 @@ interface TrndUpClientConfig {
|
|
|
191
191
|
The SDK is fully typed with TypeScript. All request/response types are available:
|
|
192
192
|
|
|
193
193
|
```typescript
|
|
194
|
-
import type { Auth, YouTube, Instagram, Social, Insights } from '@trndup
|
|
194
|
+
import type { Auth, YouTube, Instagram, Social, Insights } from '@dracoonghost/trndup-sdk';
|
|
195
195
|
|
|
196
196
|
// Use types in your code
|
|
197
197
|
const user: Auth.User = await sdk.auth.getCurrentUser();
|
|
@@ -216,7 +216,7 @@ npm run type-check
|
|
|
216
216
|
npm link
|
|
217
217
|
|
|
218
218
|
# In your mobile app
|
|
219
|
-
npm link @trndup
|
|
219
|
+
npm link @dracoonghost/trndup-sdk
|
|
220
220
|
```
|
|
221
221
|
|
|
222
222
|
## License
|
package/dist/index.d.mts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
12
|
* import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
13
|
-
* import { YOUTUBE_SCOPES } from '@trndup
|
|
13
|
+
* import { YOUTUBE_SCOPES } from '@dracoonghost/trndup-sdk';
|
|
14
14
|
*
|
|
15
15
|
* GoogleSignin.configure({
|
|
16
16
|
* webClientId: 'YOUR_WEB_CLIENT_ID',
|
|
@@ -253,6 +253,73 @@ declare namespace YouTube {
|
|
|
253
253
|
interface GetHealthScoreParams {
|
|
254
254
|
range?: string;
|
|
255
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Status of a single sync type
|
|
258
|
+
*/
|
|
259
|
+
interface SyncTypeStatus {
|
|
260
|
+
/** Current sync status */
|
|
261
|
+
status: 'never_synced' | 'pending' | 'in_progress' | 'completed' | 'failed';
|
|
262
|
+
/**
|
|
263
|
+
* When the backend last fetched data from YouTube API.
|
|
264
|
+
* UI should store this value and compare on next call.
|
|
265
|
+
* If lastSyncAt is newer than stored → refetch data from API
|
|
266
|
+
*/
|
|
267
|
+
lastSyncAt: string | null;
|
|
268
|
+
/** Last error message if sync failed */
|
|
269
|
+
lastError: string | null;
|
|
270
|
+
/** Number of consecutive failed attempts */
|
|
271
|
+
failedAttempts: number;
|
|
272
|
+
/** Whether data is older than the refresh interval (backend will auto-sync) */
|
|
273
|
+
isStale: boolean;
|
|
274
|
+
/** When the next automatic sync will run */
|
|
275
|
+
nextSyncAt: string | null;
|
|
276
|
+
/** Human-readable time until next sync (e.g., "6 hours") */
|
|
277
|
+
timeUntilNextSync: string;
|
|
278
|
+
/** Sync interval for this data type (e.g., "12 hours") */
|
|
279
|
+
interval: string;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Response from GET /v1/platforms/youtube/sync/status
|
|
283
|
+
*
|
|
284
|
+
* Use this endpoint to:
|
|
285
|
+
* 1. Check if any sync is stale (anyStale) - backend will auto-sync
|
|
286
|
+
* 2. Check if new data available (compare lastSyncAt with stored value)
|
|
287
|
+
* 3. Show sync status in UI settings/debug screen
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const status = await client.youtube.getUnifiedSyncStatus();
|
|
292
|
+
*
|
|
293
|
+
* // Check if backend has newer data than our cache
|
|
294
|
+
* const storedLastSync = localStorage.get('videosLastSync');
|
|
295
|
+
* if (status.data.syncs.videos.lastSyncAt > storedLastSync) {
|
|
296
|
+
* // Backend synced since our last fetch, refetch videos
|
|
297
|
+
* const videos = await client.youtube.getVideos();
|
|
298
|
+
* localStorage.set('videosLastSync', status.data.syncs.videos.lastSyncAt);
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
interface UnifiedSyncStatusResponse {
|
|
303
|
+
/** Whether YouTube account is connected */
|
|
304
|
+
isConnected: boolean;
|
|
305
|
+
/** YouTube channel ID */
|
|
306
|
+
channelId: string | null;
|
|
307
|
+
/** YouTube channel name */
|
|
308
|
+
channelName: string | null;
|
|
309
|
+
/** Total videos stored in database */
|
|
310
|
+
totalVideos: number;
|
|
311
|
+
/** Sync status for each data type */
|
|
312
|
+
syncs: {
|
|
313
|
+
/** Channel info (subscribers, video count) */
|
|
314
|
+
channelInfo: SyncTypeStatus;
|
|
315
|
+
/** Videos list */
|
|
316
|
+
videos: SyncTypeStatus;
|
|
317
|
+
/** Channel analytics (daily metrics, demographics) */
|
|
318
|
+
channelAnalytics: SyncTypeStatus;
|
|
319
|
+
/** Video analytics (per-video metrics) */
|
|
320
|
+
videoAnalytics: SyncTypeStatus;
|
|
321
|
+
};
|
|
322
|
+
}
|
|
256
323
|
/**
|
|
257
324
|
* Response from GET /v1/platforms/youtube/analytics/channel/sync/status
|
|
258
325
|
*/
|
|
@@ -420,6 +487,109 @@ declare namespace Insights {
|
|
|
420
487
|
youtube?: YouTube.Video[];
|
|
421
488
|
instagram?: Instagram.Post[];
|
|
422
489
|
}
|
|
490
|
+
/** Momentum status labels */
|
|
491
|
+
type MomentumStatusLabel = 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping';
|
|
492
|
+
/** Momentum trend direction */
|
|
493
|
+
type MomentumTrend = 'accelerating' | 'holding' | 'decelerating';
|
|
494
|
+
/**
|
|
495
|
+
* Metric breakdown showing current vs previous period
|
|
496
|
+
*/
|
|
497
|
+
interface MetricComparison {
|
|
498
|
+
/** Current period value */
|
|
499
|
+
current: number;
|
|
500
|
+
/** Previous period value */
|
|
501
|
+
previous: number;
|
|
502
|
+
/** Percentage change (-100 to +100+) */
|
|
503
|
+
change: number;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Momentum Status Response
|
|
507
|
+
*
|
|
508
|
+
* Provides a 0-100 score indicating channel momentum:
|
|
509
|
+
* - 50 = Steady (no change week over week)
|
|
510
|
+
* - 0 = Severe decline (-100% or worse)
|
|
511
|
+
* - 100 = Explosive growth (+100% or better)
|
|
512
|
+
*
|
|
513
|
+
* Status labels:
|
|
514
|
+
* - 80-100: Surging 🚀
|
|
515
|
+
* - 60-79: Rising 📈
|
|
516
|
+
* - 40-59: Steady ➡️
|
|
517
|
+
* - 20-39: Cooling 📉
|
|
518
|
+
* - 0-19: Dropping 🔻
|
|
519
|
+
*/
|
|
520
|
+
interface MomentumStatusResponse {
|
|
521
|
+
/** Normalized score 0-100 (50 = no change) */
|
|
522
|
+
score: number;
|
|
523
|
+
/** Raw weighted average change before normalization */
|
|
524
|
+
rawChange: number;
|
|
525
|
+
/** Human-friendly status label */
|
|
526
|
+
status: MomentumStatusLabel;
|
|
527
|
+
/** Trend direction compared to previous period */
|
|
528
|
+
trend: MomentumTrend;
|
|
529
|
+
/** Previous period's score (null if first calculation) */
|
|
530
|
+
previousScore: number | null;
|
|
531
|
+
/** Time periods being compared */
|
|
532
|
+
period: {
|
|
533
|
+
current: {
|
|
534
|
+
start: string;
|
|
535
|
+
end: string;
|
|
536
|
+
};
|
|
537
|
+
previous: {
|
|
538
|
+
start: string;
|
|
539
|
+
end: string;
|
|
540
|
+
};
|
|
541
|
+
};
|
|
542
|
+
/** Breakdown of individual metrics */
|
|
543
|
+
breakdown: {
|
|
544
|
+
views: MetricComparison;
|
|
545
|
+
engagement: MetricComparison;
|
|
546
|
+
watchTime: MetricComparison;
|
|
547
|
+
subscribers: MetricComparison;
|
|
548
|
+
};
|
|
549
|
+
/** Weights used in calculation */
|
|
550
|
+
weights: {
|
|
551
|
+
views: number;
|
|
552
|
+
engagement: number;
|
|
553
|
+
watchTime: number;
|
|
554
|
+
subscribers: number;
|
|
555
|
+
};
|
|
556
|
+
/** Human-readable insight summary */
|
|
557
|
+
insight: string;
|
|
558
|
+
/** Cache metadata */
|
|
559
|
+
_meta?: {
|
|
560
|
+
fromCache: boolean;
|
|
561
|
+
refreshed?: boolean;
|
|
562
|
+
cacheValidFor: string;
|
|
563
|
+
algorithmVersion: string;
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Single history point for momentum graphing
|
|
568
|
+
*/
|
|
569
|
+
interface MomentumHistoryPoint {
|
|
570
|
+
/** Date (YYYY-MM-DD) */
|
|
571
|
+
date: string;
|
|
572
|
+
/** Momentum score at that time */
|
|
573
|
+
score: number;
|
|
574
|
+
/** Status label at that time */
|
|
575
|
+
status: MomentumStatusLabel;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Momentum history response for graphing
|
|
579
|
+
*/
|
|
580
|
+
interface MomentumHistoryResponse {
|
|
581
|
+
/** Historical data points (oldest first) */
|
|
582
|
+
history: MomentumHistoryPoint[];
|
|
583
|
+
/** Number of points returned */
|
|
584
|
+
count: number;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Parameters for momentum history request
|
|
588
|
+
*/
|
|
589
|
+
interface GetMomentumHistoryParams {
|
|
590
|
+
/** Max number of data points (default: 30, max: 90) */
|
|
591
|
+
limit?: number;
|
|
592
|
+
}
|
|
423
593
|
}
|
|
424
594
|
|
|
425
595
|
/**
|
|
@@ -621,6 +791,29 @@ declare class YouTubeModule {
|
|
|
621
791
|
message: string;
|
|
622
792
|
jobId?: string;
|
|
623
793
|
}>;
|
|
794
|
+
/**
|
|
795
|
+
* Get unified sync status for all YouTube data types.
|
|
796
|
+
*
|
|
797
|
+
* Use this for:
|
|
798
|
+
* - Checking if UI cache needs refresh (compare lastSyncAt)
|
|
799
|
+
* - Showing sync status in settings/debug screens
|
|
800
|
+
* - Detecting if background sync is running
|
|
801
|
+
*
|
|
802
|
+
* GET /v1/platforms/youtube/sync/status
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* ```typescript
|
|
806
|
+
* const status = await client.youtube.getUnifiedSyncStatus();
|
|
807
|
+
*
|
|
808
|
+
* // Check if backend synced since our last fetch
|
|
809
|
+
* const storedLastSync = await AsyncStorage.getItem('videosLastSync');
|
|
810
|
+
* if (status.syncs.videos.lastSyncAt > storedLastSync) {
|
|
811
|
+
* const videos = await client.youtube.getVideos();
|
|
812
|
+
* await AsyncStorage.setItem('videosLastSync', status.syncs.videos.lastSyncAt);
|
|
813
|
+
* }
|
|
814
|
+
* ```
|
|
815
|
+
*/
|
|
816
|
+
getUnifiedSyncStatus(): Promise<YouTube.UnifiedSyncStatusResponse>;
|
|
624
817
|
/**
|
|
625
818
|
* Get channel analytics sync status
|
|
626
819
|
* GET /v1/platforms/youtube/analytics/channel/sync/status
|
|
@@ -745,6 +938,73 @@ declare class InsightsModule {
|
|
|
745
938
|
* GET /v1/insights/trending
|
|
746
939
|
*/
|
|
747
940
|
getTrending(): Promise<Insights.TrendingContent>;
|
|
941
|
+
/**
|
|
942
|
+
* Get YouTube channel momentum status
|
|
943
|
+
*
|
|
944
|
+
* Returns a 0-100 score indicating channel momentum:
|
|
945
|
+
* - 50 = Steady (no change week over week)
|
|
946
|
+
* - 0 = Severe decline
|
|
947
|
+
* - 100 = Explosive growth
|
|
948
|
+
*
|
|
949
|
+
* Results are cached for 12 hours. Use `refreshYouTubeMomentum()` to force recalculation.
|
|
950
|
+
*
|
|
951
|
+
* @example
|
|
952
|
+
* ```typescript
|
|
953
|
+
* const momentum = await client.insights.getYouTubeMomentum();
|
|
954
|
+
*
|
|
955
|
+
* console.log(`Score: ${momentum.score}/100`);
|
|
956
|
+
* console.log(`Status: ${momentum.status}`); // 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping'
|
|
957
|
+
* console.log(`Trend: ${momentum.trend}`); // 'accelerating' | 'holding' | 'decelerating'
|
|
958
|
+
* console.log(momentum.insight); // Human-readable summary
|
|
959
|
+
*
|
|
960
|
+
* // Show breakdown
|
|
961
|
+
* console.log(`Views: ${momentum.breakdown.views.change}%`);
|
|
962
|
+
* console.log(`Engagement: ${momentum.breakdown.engagement.change}%`);
|
|
963
|
+
* ```
|
|
964
|
+
*
|
|
965
|
+
* GET /v1/insights/youtube/momentum
|
|
966
|
+
*/
|
|
967
|
+
getYouTubeMomentum(): Promise<Insights.MomentumStatusResponse>;
|
|
968
|
+
/**
|
|
969
|
+
* Get YouTube momentum history for graphing
|
|
970
|
+
*
|
|
971
|
+
* Returns historical momentum scores, oldest first.
|
|
972
|
+
* Use this to plot momentum trends over time.
|
|
973
|
+
*
|
|
974
|
+
* @param params - Query parameters
|
|
975
|
+
* @param params.limit - Max data points (default: 30, max: 90)
|
|
976
|
+
*
|
|
977
|
+
* @example
|
|
978
|
+
* ```typescript
|
|
979
|
+
* const { history } = await client.insights.getYouTubeMomentumHistory({ limit: 30 });
|
|
980
|
+
*
|
|
981
|
+
* // Plot on a chart
|
|
982
|
+
* const chartData = history.map(point => ({
|
|
983
|
+
* x: new Date(point.date),
|
|
984
|
+
* y: point.score,
|
|
985
|
+
* label: point.status
|
|
986
|
+
* }));
|
|
987
|
+
* ```
|
|
988
|
+
*
|
|
989
|
+
* GET /v1/insights/youtube/momentum/history
|
|
990
|
+
*/
|
|
991
|
+
getYouTubeMomentumHistory(params?: Insights.GetMomentumHistoryParams): Promise<Insights.MomentumHistoryResponse>;
|
|
992
|
+
/**
|
|
993
|
+
* Force refresh YouTube momentum status (bypass cache)
|
|
994
|
+
*
|
|
995
|
+
* Use this after a sync completes to get the latest momentum score.
|
|
996
|
+
* Results are recalculated and cached for 12 hours.
|
|
997
|
+
*
|
|
998
|
+
* @example
|
|
999
|
+
* ```typescript
|
|
1000
|
+
* // After videos sync completes
|
|
1001
|
+
* const freshMomentum = await client.insights.refreshYouTubeMomentum();
|
|
1002
|
+
* console.log('Updated score:', freshMomentum.score);
|
|
1003
|
+
* ```
|
|
1004
|
+
*
|
|
1005
|
+
* POST /v1/insights/youtube/momentum/refresh
|
|
1006
|
+
*/
|
|
1007
|
+
refreshYouTubeMomentum(): Promise<Insights.MomentumStatusResponse>;
|
|
748
1008
|
}
|
|
749
1009
|
|
|
750
1010
|
/**
|
|
@@ -755,7 +1015,7 @@ declare class InsightsModule {
|
|
|
755
1015
|
*
|
|
756
1016
|
* @example
|
|
757
1017
|
* ```typescript
|
|
758
|
-
* import { TrndUpSDK, YOUTUBE_SCOPES } from '@trndup
|
|
1018
|
+
* import { TrndUpSDK, YOUTUBE_SCOPES } from '@dracoonghost/trndup-sdk';
|
|
759
1019
|
* import auth from '@react-native-firebase/auth';
|
|
760
1020
|
* import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
761
1021
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
12
|
* import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
13
|
-
* import { YOUTUBE_SCOPES } from '@trndup
|
|
13
|
+
* import { YOUTUBE_SCOPES } from '@dracoonghost/trndup-sdk';
|
|
14
14
|
*
|
|
15
15
|
* GoogleSignin.configure({
|
|
16
16
|
* webClientId: 'YOUR_WEB_CLIENT_ID',
|
|
@@ -253,6 +253,73 @@ declare namespace YouTube {
|
|
|
253
253
|
interface GetHealthScoreParams {
|
|
254
254
|
range?: string;
|
|
255
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Status of a single sync type
|
|
258
|
+
*/
|
|
259
|
+
interface SyncTypeStatus {
|
|
260
|
+
/** Current sync status */
|
|
261
|
+
status: 'never_synced' | 'pending' | 'in_progress' | 'completed' | 'failed';
|
|
262
|
+
/**
|
|
263
|
+
* When the backend last fetched data from YouTube API.
|
|
264
|
+
* UI should store this value and compare on next call.
|
|
265
|
+
* If lastSyncAt is newer than stored → refetch data from API
|
|
266
|
+
*/
|
|
267
|
+
lastSyncAt: string | null;
|
|
268
|
+
/** Last error message if sync failed */
|
|
269
|
+
lastError: string | null;
|
|
270
|
+
/** Number of consecutive failed attempts */
|
|
271
|
+
failedAttempts: number;
|
|
272
|
+
/** Whether data is older than the refresh interval (backend will auto-sync) */
|
|
273
|
+
isStale: boolean;
|
|
274
|
+
/** When the next automatic sync will run */
|
|
275
|
+
nextSyncAt: string | null;
|
|
276
|
+
/** Human-readable time until next sync (e.g., "6 hours") */
|
|
277
|
+
timeUntilNextSync: string;
|
|
278
|
+
/** Sync interval for this data type (e.g., "12 hours") */
|
|
279
|
+
interval: string;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Response from GET /v1/platforms/youtube/sync/status
|
|
283
|
+
*
|
|
284
|
+
* Use this endpoint to:
|
|
285
|
+
* 1. Check if any sync is stale (anyStale) - backend will auto-sync
|
|
286
|
+
* 2. Check if new data available (compare lastSyncAt with stored value)
|
|
287
|
+
* 3. Show sync status in UI settings/debug screen
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const status = await client.youtube.getUnifiedSyncStatus();
|
|
292
|
+
*
|
|
293
|
+
* // Check if backend has newer data than our cache
|
|
294
|
+
* const storedLastSync = localStorage.get('videosLastSync');
|
|
295
|
+
* if (status.data.syncs.videos.lastSyncAt > storedLastSync) {
|
|
296
|
+
* // Backend synced since our last fetch, refetch videos
|
|
297
|
+
* const videos = await client.youtube.getVideos();
|
|
298
|
+
* localStorage.set('videosLastSync', status.data.syncs.videos.lastSyncAt);
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
interface UnifiedSyncStatusResponse {
|
|
303
|
+
/** Whether YouTube account is connected */
|
|
304
|
+
isConnected: boolean;
|
|
305
|
+
/** YouTube channel ID */
|
|
306
|
+
channelId: string | null;
|
|
307
|
+
/** YouTube channel name */
|
|
308
|
+
channelName: string | null;
|
|
309
|
+
/** Total videos stored in database */
|
|
310
|
+
totalVideos: number;
|
|
311
|
+
/** Sync status for each data type */
|
|
312
|
+
syncs: {
|
|
313
|
+
/** Channel info (subscribers, video count) */
|
|
314
|
+
channelInfo: SyncTypeStatus;
|
|
315
|
+
/** Videos list */
|
|
316
|
+
videos: SyncTypeStatus;
|
|
317
|
+
/** Channel analytics (daily metrics, demographics) */
|
|
318
|
+
channelAnalytics: SyncTypeStatus;
|
|
319
|
+
/** Video analytics (per-video metrics) */
|
|
320
|
+
videoAnalytics: SyncTypeStatus;
|
|
321
|
+
};
|
|
322
|
+
}
|
|
256
323
|
/**
|
|
257
324
|
* Response from GET /v1/platforms/youtube/analytics/channel/sync/status
|
|
258
325
|
*/
|
|
@@ -420,6 +487,109 @@ declare namespace Insights {
|
|
|
420
487
|
youtube?: YouTube.Video[];
|
|
421
488
|
instagram?: Instagram.Post[];
|
|
422
489
|
}
|
|
490
|
+
/** Momentum status labels */
|
|
491
|
+
type MomentumStatusLabel = 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping';
|
|
492
|
+
/** Momentum trend direction */
|
|
493
|
+
type MomentumTrend = 'accelerating' | 'holding' | 'decelerating';
|
|
494
|
+
/**
|
|
495
|
+
* Metric breakdown showing current vs previous period
|
|
496
|
+
*/
|
|
497
|
+
interface MetricComparison {
|
|
498
|
+
/** Current period value */
|
|
499
|
+
current: number;
|
|
500
|
+
/** Previous period value */
|
|
501
|
+
previous: number;
|
|
502
|
+
/** Percentage change (-100 to +100+) */
|
|
503
|
+
change: number;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Momentum Status Response
|
|
507
|
+
*
|
|
508
|
+
* Provides a 0-100 score indicating channel momentum:
|
|
509
|
+
* - 50 = Steady (no change week over week)
|
|
510
|
+
* - 0 = Severe decline (-100% or worse)
|
|
511
|
+
* - 100 = Explosive growth (+100% or better)
|
|
512
|
+
*
|
|
513
|
+
* Status labels:
|
|
514
|
+
* - 80-100: Surging 🚀
|
|
515
|
+
* - 60-79: Rising 📈
|
|
516
|
+
* - 40-59: Steady ➡️
|
|
517
|
+
* - 20-39: Cooling 📉
|
|
518
|
+
* - 0-19: Dropping 🔻
|
|
519
|
+
*/
|
|
520
|
+
interface MomentumStatusResponse {
|
|
521
|
+
/** Normalized score 0-100 (50 = no change) */
|
|
522
|
+
score: number;
|
|
523
|
+
/** Raw weighted average change before normalization */
|
|
524
|
+
rawChange: number;
|
|
525
|
+
/** Human-friendly status label */
|
|
526
|
+
status: MomentumStatusLabel;
|
|
527
|
+
/** Trend direction compared to previous period */
|
|
528
|
+
trend: MomentumTrend;
|
|
529
|
+
/** Previous period's score (null if first calculation) */
|
|
530
|
+
previousScore: number | null;
|
|
531
|
+
/** Time periods being compared */
|
|
532
|
+
period: {
|
|
533
|
+
current: {
|
|
534
|
+
start: string;
|
|
535
|
+
end: string;
|
|
536
|
+
};
|
|
537
|
+
previous: {
|
|
538
|
+
start: string;
|
|
539
|
+
end: string;
|
|
540
|
+
};
|
|
541
|
+
};
|
|
542
|
+
/** Breakdown of individual metrics */
|
|
543
|
+
breakdown: {
|
|
544
|
+
views: MetricComparison;
|
|
545
|
+
engagement: MetricComparison;
|
|
546
|
+
watchTime: MetricComparison;
|
|
547
|
+
subscribers: MetricComparison;
|
|
548
|
+
};
|
|
549
|
+
/** Weights used in calculation */
|
|
550
|
+
weights: {
|
|
551
|
+
views: number;
|
|
552
|
+
engagement: number;
|
|
553
|
+
watchTime: number;
|
|
554
|
+
subscribers: number;
|
|
555
|
+
};
|
|
556
|
+
/** Human-readable insight summary */
|
|
557
|
+
insight: string;
|
|
558
|
+
/** Cache metadata */
|
|
559
|
+
_meta?: {
|
|
560
|
+
fromCache: boolean;
|
|
561
|
+
refreshed?: boolean;
|
|
562
|
+
cacheValidFor: string;
|
|
563
|
+
algorithmVersion: string;
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Single history point for momentum graphing
|
|
568
|
+
*/
|
|
569
|
+
interface MomentumHistoryPoint {
|
|
570
|
+
/** Date (YYYY-MM-DD) */
|
|
571
|
+
date: string;
|
|
572
|
+
/** Momentum score at that time */
|
|
573
|
+
score: number;
|
|
574
|
+
/** Status label at that time */
|
|
575
|
+
status: MomentumStatusLabel;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Momentum history response for graphing
|
|
579
|
+
*/
|
|
580
|
+
interface MomentumHistoryResponse {
|
|
581
|
+
/** Historical data points (oldest first) */
|
|
582
|
+
history: MomentumHistoryPoint[];
|
|
583
|
+
/** Number of points returned */
|
|
584
|
+
count: number;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Parameters for momentum history request
|
|
588
|
+
*/
|
|
589
|
+
interface GetMomentumHistoryParams {
|
|
590
|
+
/** Max number of data points (default: 30, max: 90) */
|
|
591
|
+
limit?: number;
|
|
592
|
+
}
|
|
423
593
|
}
|
|
424
594
|
|
|
425
595
|
/**
|
|
@@ -621,6 +791,29 @@ declare class YouTubeModule {
|
|
|
621
791
|
message: string;
|
|
622
792
|
jobId?: string;
|
|
623
793
|
}>;
|
|
794
|
+
/**
|
|
795
|
+
* Get unified sync status for all YouTube data types.
|
|
796
|
+
*
|
|
797
|
+
* Use this for:
|
|
798
|
+
* - Checking if UI cache needs refresh (compare lastSyncAt)
|
|
799
|
+
* - Showing sync status in settings/debug screens
|
|
800
|
+
* - Detecting if background sync is running
|
|
801
|
+
*
|
|
802
|
+
* GET /v1/platforms/youtube/sync/status
|
|
803
|
+
*
|
|
804
|
+
* @example
|
|
805
|
+
* ```typescript
|
|
806
|
+
* const status = await client.youtube.getUnifiedSyncStatus();
|
|
807
|
+
*
|
|
808
|
+
* // Check if backend synced since our last fetch
|
|
809
|
+
* const storedLastSync = await AsyncStorage.getItem('videosLastSync');
|
|
810
|
+
* if (status.syncs.videos.lastSyncAt > storedLastSync) {
|
|
811
|
+
* const videos = await client.youtube.getVideos();
|
|
812
|
+
* await AsyncStorage.setItem('videosLastSync', status.syncs.videos.lastSyncAt);
|
|
813
|
+
* }
|
|
814
|
+
* ```
|
|
815
|
+
*/
|
|
816
|
+
getUnifiedSyncStatus(): Promise<YouTube.UnifiedSyncStatusResponse>;
|
|
624
817
|
/**
|
|
625
818
|
* Get channel analytics sync status
|
|
626
819
|
* GET /v1/platforms/youtube/analytics/channel/sync/status
|
|
@@ -745,6 +938,73 @@ declare class InsightsModule {
|
|
|
745
938
|
* GET /v1/insights/trending
|
|
746
939
|
*/
|
|
747
940
|
getTrending(): Promise<Insights.TrendingContent>;
|
|
941
|
+
/**
|
|
942
|
+
* Get YouTube channel momentum status
|
|
943
|
+
*
|
|
944
|
+
* Returns a 0-100 score indicating channel momentum:
|
|
945
|
+
* - 50 = Steady (no change week over week)
|
|
946
|
+
* - 0 = Severe decline
|
|
947
|
+
* - 100 = Explosive growth
|
|
948
|
+
*
|
|
949
|
+
* Results are cached for 12 hours. Use `refreshYouTubeMomentum()` to force recalculation.
|
|
950
|
+
*
|
|
951
|
+
* @example
|
|
952
|
+
* ```typescript
|
|
953
|
+
* const momentum = await client.insights.getYouTubeMomentum();
|
|
954
|
+
*
|
|
955
|
+
* console.log(`Score: ${momentum.score}/100`);
|
|
956
|
+
* console.log(`Status: ${momentum.status}`); // 'surging' | 'rising' | 'steady' | 'cooling' | 'dropping'
|
|
957
|
+
* console.log(`Trend: ${momentum.trend}`); // 'accelerating' | 'holding' | 'decelerating'
|
|
958
|
+
* console.log(momentum.insight); // Human-readable summary
|
|
959
|
+
*
|
|
960
|
+
* // Show breakdown
|
|
961
|
+
* console.log(`Views: ${momentum.breakdown.views.change}%`);
|
|
962
|
+
* console.log(`Engagement: ${momentum.breakdown.engagement.change}%`);
|
|
963
|
+
* ```
|
|
964
|
+
*
|
|
965
|
+
* GET /v1/insights/youtube/momentum
|
|
966
|
+
*/
|
|
967
|
+
getYouTubeMomentum(): Promise<Insights.MomentumStatusResponse>;
|
|
968
|
+
/**
|
|
969
|
+
* Get YouTube momentum history for graphing
|
|
970
|
+
*
|
|
971
|
+
* Returns historical momentum scores, oldest first.
|
|
972
|
+
* Use this to plot momentum trends over time.
|
|
973
|
+
*
|
|
974
|
+
* @param params - Query parameters
|
|
975
|
+
* @param params.limit - Max data points (default: 30, max: 90)
|
|
976
|
+
*
|
|
977
|
+
* @example
|
|
978
|
+
* ```typescript
|
|
979
|
+
* const { history } = await client.insights.getYouTubeMomentumHistory({ limit: 30 });
|
|
980
|
+
*
|
|
981
|
+
* // Plot on a chart
|
|
982
|
+
* const chartData = history.map(point => ({
|
|
983
|
+
* x: new Date(point.date),
|
|
984
|
+
* y: point.score,
|
|
985
|
+
* label: point.status
|
|
986
|
+
* }));
|
|
987
|
+
* ```
|
|
988
|
+
*
|
|
989
|
+
* GET /v1/insights/youtube/momentum/history
|
|
990
|
+
*/
|
|
991
|
+
getYouTubeMomentumHistory(params?: Insights.GetMomentumHistoryParams): Promise<Insights.MomentumHistoryResponse>;
|
|
992
|
+
/**
|
|
993
|
+
* Force refresh YouTube momentum status (bypass cache)
|
|
994
|
+
*
|
|
995
|
+
* Use this after a sync completes to get the latest momentum score.
|
|
996
|
+
* Results are recalculated and cached for 12 hours.
|
|
997
|
+
*
|
|
998
|
+
* @example
|
|
999
|
+
* ```typescript
|
|
1000
|
+
* // After videos sync completes
|
|
1001
|
+
* const freshMomentum = await client.insights.refreshYouTubeMomentum();
|
|
1002
|
+
* console.log('Updated score:', freshMomentum.score);
|
|
1003
|
+
* ```
|
|
1004
|
+
*
|
|
1005
|
+
* POST /v1/insights/youtube/momentum/refresh
|
|
1006
|
+
*/
|
|
1007
|
+
refreshYouTubeMomentum(): Promise<Insights.MomentumStatusResponse>;
|
|
748
1008
|
}
|
|
749
1009
|
|
|
750
1010
|
/**
|
|
@@ -755,7 +1015,7 @@ declare class InsightsModule {
|
|
|
755
1015
|
*
|
|
756
1016
|
* @example
|
|
757
1017
|
* ```typescript
|
|
758
|
-
* import { TrndUpSDK, YOUTUBE_SCOPES } from '@trndup
|
|
1018
|
+
* import { TrndUpSDK, YOUTUBE_SCOPES } from '@dracoonghost/trndup-sdk';
|
|
759
1019
|
* import auth from '@react-native-firebase/auth';
|
|
760
1020
|
* import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
761
1021
|
*
|