@@ -6,15 +6,15 @@ import contrib from 'blessed-contrib'
66
77import { logger } from '@socketsecurity/registry/lib/logger'
88
9+ import { fetchOrgAnalyticsData } from './fetch-org-analytics.ts'
10+ import { fetchRepoAnalyticsData } from './fetch-repo-analytics.ts' // Note: Widgets does not seem to actually work as code :'(
911import constants from '../../constants'
10- import { handleApiCall , handleUnsuccessfulApiResponse } from '../../utils/api'
1112import { AuthError } from '../../utils/errors.ts'
1213import { mdTableStringNumber } from '../../utils/markdown.ts'
13- import { getDefaultToken , setupSdk } from '../../utils/sdk'
14+ import { getDefaultToken } from '../../utils/sdk'
1415
15- import type { Spinner } from '@socketsecurity/registry/lib/spinner'
1616import type { SocketSdkReturnType } from '@socketsecurity/sdk'
17- import type { Widgets } from 'blessed' // Note: Widgets does not seem to actually work as code :'(
17+ import type { Widgets } from 'blessed'
1818
1919interface FormattedData {
2020 top_five_alert_types : Record < string , number >
@@ -32,22 +32,6 @@ interface FormattedData {
3232 total_low_prevented : Record < string , number >
3333}
3434
35- // Note: This maps `new Date(date).getMonth()` to English three letters
36- export const Months = [
37- 'Jan' ,
38- 'Feb' ,
39- 'Mar' ,
40- 'Apr' ,
41- 'May' ,
42- 'Jun' ,
43- 'Jul' ,
44- 'Aug' ,
45- 'Sep' ,
46- 'Oct' ,
47- 'Nov' ,
48- 'Dec'
49- ] as const
50-
5135const METRICS = [
5236 'total_critical_alerts' ,
5337 'total_high_alerts' ,
@@ -63,6 +47,22 @@ const METRICS = [
6347 'total_low_prevented'
6448] as const
6549
50+ // Note: This maps `new Date(date).getMonth()` to English three letters
51+ const Months = [
52+ 'Jan' ,
53+ 'Feb' ,
54+ 'Mar' ,
55+ 'Apr' ,
56+ 'May' ,
57+ 'Jun' ,
58+ 'Jul' ,
59+ 'Aug' ,
60+ 'Sep' ,
61+ 'Oct' ,
62+ 'Nov' ,
63+ 'Dec'
64+ ] as const
65+
6666export async function displayAnalytics ( {
6767 filePath,
6868 outputKind,
@@ -127,17 +127,9 @@ async function outputAnalyticsWithToken({
127127 if ( ! data ) return
128128
129129 if ( outputKind === 'json' ) {
130- let serialized
131- try {
132- serialized = JSON . stringify ( data , null , 2 )
133- } catch ( e ) {
134- // This could be caused by circular references, which is an "us" problem
135- logger . error (
136- 'There was a problem converting the data set to JSON. Please try without --json or with --markdown'
137- )
138- process . exitCode = 1
139- return
140- }
130+ let serialized = renderJson ( data )
131+ if ( ! serialized ) return
132+
141133 if ( filePath && filePath !== '-' ) {
142134 try {
143135 await fs . writeFile ( filePath , serialized , 'utf8' )
@@ -154,7 +146,7 @@ async function outputAnalyticsWithToken({
154146 const fdata = scope === 'org' ? formatDataOrg ( data ) : formatDataRepo ( data )
155147
156148 if ( outputKind === 'markdown' ) {
157- const serialized = renderMarkdown ( fdata )
149+ const serialized = renderMarkdown ( fdata , time , repo )
158150
159151 if ( filePath ) {
160152 try {
@@ -172,9 +164,30 @@ async function outputAnalyticsWithToken({
172164 }
173165}
174166
175- function renderMarkdown ( data : FormattedData ) : string {
167+ function renderJson ( data : unknown ) : string | undefined {
168+ try {
169+ return JSON . stringify ( data , null , 2 )
170+ } catch ( e ) {
171+ // This could be caused by circular references, which is an "us" problem
172+ logger . error (
173+ 'There was a problem converting the data set to JSON. Please try without --json or with --markdown'
174+ )
175+ process . exitCode = 1
176+ return
177+ }
178+ }
179+
180+ function renderMarkdown (
181+ data : FormattedData ,
182+ days : number ,
183+ repoSlug : string
184+ ) : string {
176185 return (
177- '# Socket Alert Analytics\n\nThese are the Socket.dev stats are analytics for the org / [name] repo of the past 7/30/90 days\n\n' +
186+ `# Socket Alert Analytics
187+
188+ These are the Socket.dev stats are analytics for the ${ repoSlug ? `${ repoSlug } repo` : 'org' } of the past ${ days } days
189+
190+ ` +
178191 [
179192 [
180193 'Total critical alerts' ,
@@ -302,59 +315,6 @@ function displayAnalyticsScreen(data: FormattedData): void {
302315 screen . key ( [ 'escape' , 'q' , 'C-c' ] , ( ) => process . exit ( 0 ) )
303316}
304317
305- async function fetchOrgAnalyticsData (
306- time : number ,
307- spinner : Spinner ,
308- apiToken : string
309- ) : Promise < SocketSdkReturnType < 'getOrgAnalytics' > [ 'data' ] | undefined > {
310- const socketSdk = await setupSdk ( apiToken )
311- const result = await handleApiCall (
312- socketSdk . getOrgAnalytics ( time . toString ( ) ) ,
313- 'fetching analytics data'
314- )
315-
316- if ( result . success === false ) {
317- handleUnsuccessfulApiResponse ( 'getOrgAnalytics' , result , spinner )
318- return undefined
319- }
320-
321- spinner . stop ( )
322-
323- if ( ! result . data . length ) {
324- logger . log ( 'No analytics data is available for this organization yet.' )
325- return undefined
326- }
327-
328- return result . data
329- }
330-
331- async function fetchRepoAnalyticsData (
332- repo : string ,
333- time : number ,
334- spinner : Spinner ,
335- apiToken : string
336- ) : Promise < SocketSdkReturnType < 'getRepoAnalytics' > [ 'data' ] | undefined > {
337- const socketSdk = await setupSdk ( apiToken )
338- const result = await handleApiCall (
339- socketSdk . getRepoAnalytics ( repo , time . toString ( ) ) ,
340- 'fetching analytics data'
341- )
342-
343- if ( result . success === false ) {
344- handleUnsuccessfulApiResponse ( 'getRepoAnalytics' , result , spinner )
345- return undefined
346- }
347-
348- spinner . stop ( )
349-
350- if ( ! result . data . length ) {
351- logger . log ( 'No analytics data is available for this organization yet.' )
352- return undefined
353- }
354-
355- return result . data
356- }
357-
358318function formatDataRepo (
359319 data : SocketSdkReturnType < 'getRepoAnalytics' > [ 'data' ]
360320) : FormattedData {
0 commit comments