@dracoonghost/trndup-sdk 1.3.16 → 1.3.18

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.js CHANGED
@@ -595,6 +595,376 @@ var InsightsModule = class {
595
595
  `/v1/insights/youtube/momentum/history${query}`
596
596
  );
597
597
  }
598
+ // =========================================================================
599
+ // YOUTUBE BEST PERFORMING VIDEO
600
+ // =========================================================================
601
+ /**
602
+ * Get the best performing video in a time period
603
+ *
604
+ * Identifies your top video by views and explains WHY it performed well.
605
+ *
606
+ * @param params - Query parameters
607
+ * @param params.period - Days to analyze (1-90, default: 30)
608
+ *
609
+ * @example
610
+ * ```typescript
611
+ * const result = await client.insights.getYouTubeBestVideo({ period: 30 });
612
+ *
613
+ * if (result.hasData) {
614
+ * console.log(`🏆 ${result.data.topVideo.title}`);
615
+ * console.log(`Views: ${result.data.metrics.views}`);
616
+ * console.log(`${result.data.comparison.vsChannelAverage.description}`);
617
+ * console.log(result.data.insight);
618
+ *
619
+ * // Show how it was calculated
620
+ * console.log(result._meta.howWeCalculatedThis.method);
621
+ * } else {
622
+ * console.log(result.suggestion);
623
+ * }
624
+ * ```
625
+ *
626
+ * GET /v1/insights/youtube/best-video
627
+ */
628
+ async getYouTubeBestVideo(params) {
629
+ const query = params?.period ? `?period=${params.period}` : "";
630
+ return this.client.get(
631
+ `/v1/insights/youtube/best-video${query}`
632
+ );
633
+ }
634
+ // =========================================================================
635
+ // YOUTUBE CONTENT DECAY
636
+ // =========================================================================
637
+ /**
638
+ * Find videos that are losing momentum
639
+ *
640
+ * Compares current period vs previous period to identify declining videos.
641
+ * Provides actionable suggestions for each decaying video.
642
+ *
643
+ * @param params - Query parameters
644
+ * @param params.period - Days per comparison period (3-14, default: 7)
645
+ *
646
+ * @example
647
+ * ```typescript
648
+ * const result = await client.insights.getYouTubeContentDecay({ period: 7 });
649
+ *
650
+ * if (result.hasData) {
651
+ * console.log(result.data.insight);
652
+ * console.log(`${result.data.summary.totalDecaying} videos declining`);
653
+ *
654
+ * for (const video of result.data.decayingVideos) {
655
+ * console.log(`📉 ${video.title}: ${video.decayRate}%`);
656
+ * console.log(` ${video.suggestion}`);
657
+ * }
658
+ * }
659
+ * ```
660
+ *
661
+ * GET /v1/insights/youtube/content-decay
662
+ */
663
+ async getYouTubeContentDecay(params) {
664
+ const query = params?.period ? `?period=${params.period}` : "";
665
+ return this.client.get(
666
+ `/v1/insights/youtube/content-decay${query}`
667
+ );
668
+ }
669
+ // =========================================================================
670
+ // YOUTUBE AUDIENCE ACTIVITY
671
+ // =========================================================================
672
+ /**
673
+ * Get when your audience is most active
674
+ *
675
+ * Unlike generic advice, this is based on YOUR audience's behavior.
676
+ * Analyzes first-day performance by publish day and time to identify
677
+ * when your audience is most engaged.
678
+ *
679
+ * @example
680
+ * ```typescript
681
+ * const result = await client.insights.getYouTubeAudienceActivity();
682
+ *
683
+ * if (result.hasData) {
684
+ * console.log(`📅 Most active day: ${result.data.mostActiveDay.day}`);
685
+ * console.log(`⏰ Peak time: ${result.data.mostActiveTimeSlot.label}`);
686
+ * console.log(result.data.insight);
687
+ *
688
+ * // Show day breakdown
689
+ * for (const day of result.data.dayBreakdown) {
690
+ * console.log(`${day.day}: ${day.avgFirstDayViews} avg views`);
691
+ * }
692
+ * }
693
+ * ```
694
+ *
695
+ * GET /v1/insights/youtube/audience-activity
696
+ */
697
+ async getYouTubeAudienceActivity() {
698
+ return this.client.get(
699
+ "/v1/insights/youtube/audience-activity"
700
+ );
701
+ }
702
+ /**
703
+ * @deprecated Use `getYouTubeAudienceActivity()` instead
704
+ */
705
+ async getYouTubeBestUploadTime() {
706
+ return this.getYouTubeAudienceActivity();
707
+ }
708
+ // =========================================================================
709
+ // YOUTUBE FADING HITS
710
+ // =========================================================================
711
+ /**
712
+ * Find videos that were hits but are now declining
713
+ *
714
+ * Identifies videos that performed above your channel average initially
715
+ * but have since lost momentum. These are revival opportunities.
716
+ *
717
+ * @example
718
+ * ```typescript
719
+ * const result = await client.insights.getYouTubeFadingHits();
720
+ *
721
+ * if (result.hasData) {
722
+ * console.log(result.data.insight);
723
+ * console.log(`${result.data.summary.totalFading} videos could use a boost`);
724
+ *
725
+ * for (const video of result.data.fadingHits) {
726
+ * console.log(`📉 ${video.title}`);
727
+ * console.log(` Peak: ${video.peakPeriod.avgDailyViews} views/day`);
728
+ * console.log(` Now: ${video.currentPeriod.avgDailyViews} views/day`);
729
+ * console.log(` Decline: ${video.decline.percentage}%`);
730
+ * console.log(` Revival potential: ${video.revivalPotential}`);
731
+ * console.log(` ${video.whyRevive}`);
732
+ * for (const suggestion of video.suggestions) {
733
+ * console.log(` 💡 ${suggestion}`);
734
+ * }
735
+ * }
736
+ * }
737
+ * ```
738
+ *
739
+ * GET /v1/insights/youtube/fading-hits
740
+ */
741
+ async getYouTubeFadingHits() {
742
+ return this.client.get(
743
+ "/v1/insights/youtube/fading-hits"
744
+ );
745
+ }
746
+ // =========================================================================
747
+ // YOUTUBE SUBSCRIBER QUALITY
748
+ // =========================================================================
749
+ /**
750
+ * Measure subscriber quality score (0-100)
751
+ *
752
+ * Analyzes whether new subscribers are engaged or just numbers.
753
+ * Helps identify fake growth or low-quality audiences.
754
+ *
755
+ * @param params - Query parameters
756
+ * @param params.period - Days to analyze (7-90, default: 30)
757
+ *
758
+ * @example
759
+ * ```typescript
760
+ * const result = await client.insights.getYouTubeSubscriberQuality({ period: 90 });
761
+ *
762
+ * if (result.hasData) {
763
+ * console.log(`Quality Score: ${result.data.qualityScore}/100 (${result.data.scoreLabel})`);
764
+ * console.log(`Retention: ${result.data.metrics.retentionRate}%`);
765
+ * console.log(result.data.insight);
766
+ *
767
+ * // Show recommendations
768
+ * for (const rec of result.data.recommendations) {
769
+ * console.log(`💡 ${rec}`);
770
+ * }
771
+ * }
772
+ * ```
773
+ *
774
+ * GET /v1/insights/youtube/subscriber-quality
775
+ */
776
+ async getYouTubeSubscriberQuality(params) {
777
+ const query = params?.period ? `?period=${params.period}` : "";
778
+ return this.client.get(
779
+ `/v1/insights/youtube/subscriber-quality${query}`
780
+ );
781
+ }
782
+ // =========================================================================
783
+ // YOUTUBE AUDIENCE FATIGUE
784
+ // =========================================================================
785
+ /**
786
+ * Detect if your audience is getting tired of your content
787
+ *
788
+ * Compares key engagement metrics between recent and previous periods
789
+ * to identify declining audience interest before it becomes critical.
790
+ *
791
+ * @param params - Query parameters
792
+ * @param params.period - Days per comparison period (14-90, default: 30)
793
+ *
794
+ * @example
795
+ * ```typescript
796
+ * const result = await client.insights.getYouTubeAudienceFatigue({ period: 30 });
797
+ *
798
+ * if (result.hasData) {
799
+ * console.log(`Fatigue Index: ${result.data.fatigueIndex}/100`);
800
+ * console.log(`Level: ${result.data.fatigueLevel}`);
801
+ * console.log(result.data.insight);
802
+ *
803
+ * // Check individual signals
804
+ * if (result.data.signals.watchTimePerView.indicatesFatigue) {
805
+ * console.log('⚠️ Watch time is declining');
806
+ * }
807
+ *
808
+ * // Get recommendations
809
+ * for (const rec of result.data.recommendations) {
810
+ * console.log(`💡 ${rec}`);
811
+ * }
812
+ * }
813
+ * ```
814
+ *
815
+ * GET /v1/insights/youtube/audience-fatigue
816
+ */
817
+ async getYouTubeAudienceFatigue(params) {
818
+ const query = params?.period ? `?period=${params.period}` : "";
819
+ return this.client.get(
820
+ `/v1/insights/youtube/audience-fatigue${query}`
821
+ );
822
+ }
823
+ // =========================================================================
824
+ // YOUTUBE OPTIMAL VIDEO LENGTH
825
+ // =========================================================================
826
+ /**
827
+ * Find the ideal video length for YOUR audience
828
+ *
829
+ * Unlike generic "8-12 minutes is best" advice, this is personalized
830
+ * based on how YOUR videos perform at different lengths.
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * const result = await client.insights.getYouTubeOptimalLength();
835
+ *
836
+ * if (result.hasData) {
837
+ * console.log(`Optimal: ${result.data.optimalLength.bucket}`);
838
+ * console.log(`Confidence: ${result.data.optimalLength.confidence}`);
839
+ * console.log(result.data.insight);
840
+ *
841
+ * // Show breakdown by length
842
+ * for (const bucket of result.data.breakdown) {
843
+ * const marker = bucket.isOptimal ? '🏆' : ' ';
844
+ * console.log(`${marker} ${bucket.bucket}: ${bucket.avgRetention}% retention, ${bucket.avgEngagement}% engagement`);
845
+ * }
846
+ *
847
+ * // Recommendations
848
+ * for (const rec of result.data.recommendations) {
849
+ * console.log(`💡 ${rec}`);
850
+ * }
851
+ * }
852
+ * ```
853
+ *
854
+ * GET /v1/insights/youtube/optimal-length
855
+ */
856
+ async getYouTubeOptimalLength() {
857
+ return this.client.get(
858
+ "/v1/insights/youtube/optimal-length"
859
+ );
860
+ }
861
+ // =========================================================================
862
+ // YOUTUBE ALL INSIGHTS
863
+ // =========================================================================
864
+ /**
865
+ * Get all YouTube insights in one call
866
+ *
867
+ * Efficient for dashboard display - fetches all insights in parallel.
868
+ * Each insight has `hasData: boolean` to check availability.
869
+ *
870
+ * @example
871
+ * ```typescript
872
+ * const all = await client.insights.getYouTubeAllInsights();
873
+ *
874
+ * // Check which insights are available
875
+ * console.log('Available:', all._meta.insightsAvailable);
876
+ *
877
+ * // Use each insight
878
+ * if (all.data.bestPerformingVideo.hasData) {
879
+ * console.log(`Best: ${all.data.bestPerformingVideo.data.topVideo.title}`);
880
+ * }
881
+ *
882
+ * if (all.data.audienceFatigue.hasData) {
883
+ * console.log(`Fatigue: ${all.data.audienceFatigue.data.fatigueLevel}`);
884
+ * }
885
+ *
886
+ * if (all.data.optimalLength.hasData) {
887
+ * console.log(`Optimal Length: ${all.data.optimalLength.data.optimalLength.bucket}`);
888
+ * }
889
+ * ```
890
+ *
891
+ * GET /v1/insights/youtube/all
892
+ */
893
+ async getYouTubeAllInsights() {
894
+ return this.client.get("/v1/insights/youtube/all");
895
+ }
896
+ };
897
+
898
+ // modules/activity.ts
899
+ var ActivityModule = class {
900
+ constructor(client) {
901
+ this.client = client;
902
+ }
903
+ /**
904
+ * Get recent activity logs
905
+ *
906
+ * @param params - Optional filters
907
+ * @returns List of activity log entries
908
+ *
909
+ * @example
910
+ * ```typescript
911
+ * // Get all recent logs
912
+ * const { logs } = await client.activity.getLogs();
913
+ *
914
+ * // Get only failed jobs
915
+ * const { logs } = await client.activity.getLogs({ status: 'failed' });
916
+ *
917
+ * // Get video sync jobs only
918
+ * const { logs } = await client.activity.getLogs({ type: 'videos_sync' });
919
+ * ```
920
+ */
921
+ async getLogs(params) {
922
+ const query = new URLSearchParams();
923
+ if (params?.type) query.set("type", params.type);
924
+ if (params?.status) query.set("status", params.status);
925
+ if (params?.limit) query.set("limit", params.limit.toString());
926
+ const queryString = query.toString();
927
+ const url = queryString ? `/v1/activity/logs?${queryString}` : "/v1/activity/logs";
928
+ const response = await this.client.get(url);
929
+ return response.data;
930
+ }
931
+ /**
932
+ * Get activity summary with counts by type
933
+ *
934
+ * @returns Summary with total/completed/failed counts
935
+ *
936
+ * @example
937
+ * ```typescript
938
+ * const summary = await client.activity.getSummary();
939
+ * console.log(`Total: ${summary.totalJobs}, Failed: ${summary.failed}`);
940
+ * ```
941
+ */
942
+ async getSummary() {
943
+ const response = await this.client.get(
944
+ "/v1/activity/summary"
945
+ );
946
+ return response.data;
947
+ }
948
+ /**
949
+ * Get the latest log entry for a specific job type
950
+ *
951
+ * @param jobType - The type of job to get
952
+ * @returns Latest log entry or null if none exists
953
+ *
954
+ * @example
955
+ * ```typescript
956
+ * const latestVideoSync = await client.activity.getLatest('videos_sync');
957
+ * if (latestVideoSync) {
958
+ * console.log(`Last sync: ${latestVideoSync.completedAt}`);
959
+ * }
960
+ * ```
961
+ */
962
+ async getLatest(jobType) {
963
+ const response = await this.client.get(
964
+ `/v1/activity/logs/${jobType}/latest`
965
+ );
966
+ return response.data;
967
+ }
598
968
  };
599
969
 
600
970
  // types.ts
@@ -623,6 +993,7 @@ var TrndUpSDK = class extends TrndUpClient {
623
993
  this.instagram = new InstagramModule(this);
624
994
  this.social = new SocialModule(this);
625
995
  this.insights = new InsightsModule(this);
996
+ this.activity = new ActivityModule(this);
626
997
  }
627
998
  };
628
999
  var SDK_VERSION = "1.0.0";