@@ -65,127 +65,7 @@ export async function outputAuditLog(
6565 return
6666 }
6767
68- const filteredLogs = result . data . results
69- const formattedOutput = filteredLogs . map ( logs => [
70- logs . event_id ?? '' ,
71- msAtHome ( logs . created_at ?? '' ) ,
72- logs . type ?? '' ,
73- logs . user_email ?? '' ,
74- logs . ip_address ?? '' ,
75- logs . user_agent ?? '' ,
76- ] )
77- const headers = [
78- 'event id' ,
79- ' created at' ,
80- ' event type' ,
81- ' user email' ,
82- ' ip address' ,
83- ' user agent' ,
84- ]
85-
86- // Note: this temporarily takes over the terminal (just like `man` does).
87- const ScreenWidget = require ( 'blessed/lib/widgets/screen.js' )
88- // Lazily access constants.blessedOptions.
89- const screen : Widgets . Screen = new ScreenWidget ( {
90- ...constants . blessedOptions ,
91- } )
92- // Register these keys first so you can always exit, even when it gets stuck
93- // If we don't do this and the code crashes, the user must hard-kill the
94- // node process just to exit it. That's very bad UX.
95- // eslint-disable-next-line n/no-process-exit
96- screen . key ( [ 'escape' , 'q' , 'C-c' ] , ( ) => process . exit ( 0 ) )
97-
98- const TableWidget = require ( 'blessed-contrib/lib/widget/table.js' )
99- const tipsBoxHeight = 1 // 1 row for tips box
100- const detailsBoxHeight = 20 // bottom N rows for details box. 20 gives 4 lines for condensed payload before it scrolls out of view
101-
102- const maxWidths = [ 10 , 10 , 10 , 10 , 10 , 10 ]
103- formattedOutput . forEach ( row => {
104- row . forEach ( ( str , i ) => {
105- maxWidths [ i ] = Math . max ( str . length , maxWidths [ i ] ?? str . length )
106- } )
107- } )
108-
109- const table : any = new TableWidget ( {
110- keys : 'true' ,
111- fg : 'white' ,
112- selectedFg : 'white' ,
113- selectedBg : 'magenta' ,
114- interactive : 'true' ,
115- label : `Audit Logs for ${ orgSlug } ` ,
116- width : '100%' ,
117- top : 0 ,
118- bottom : detailsBoxHeight + tipsBoxHeight ,
119- border : {
120- type : 'line' ,
121- fg : 'cyan' ,
122- } ,
123- columnWidth : maxWidths , //[10, 30, 40, 25, 15, 200],
124- // Note: spacing works as long as you don't reserve more than total width
125- columnSpacing : 4 ,
126- truncate : '_' ,
127- } )
128-
129- const BoxWidget = require ( 'blessed/lib/widgets/box.js' )
130- const tipsBox : Widgets . BoxElement = new BoxWidget ( {
131- bottom : detailsBoxHeight , // sits just above the details box
132- height : tipsBoxHeight ,
133- width : '100%' ,
134- style : {
135- fg : 'yellow' ,
136- bg : 'black' ,
137- } ,
138- tags : true ,
139- content : '↑/↓: Move Enter: Select q/ESC: Quit' ,
140- } )
141- const detailsBox : Widgets . BoxElement = new BoxWidget ( {
142- bottom : 0 ,
143- height : detailsBoxHeight ,
144- width : '100%' ,
145- border : {
146- type : 'line' ,
147- fg : 'cyan' ,
148- } ,
149- label : 'Details' ,
150- content : formatResult ( filteredLogs [ 0 ] , true ) ,
151- style : {
152- fg : 'white' ,
153- } ,
154- } )
155-
156- table . setData ( {
157- headers : headers ,
158- data : formattedOutput ,
159- } )
160-
161- // allow control the table with the keyboard
162- table . focus ( )
163-
164- // Stacking order: table (top), tipsBox (middle), detailsBox (bottom)
165- screen . append ( table )
166- screen . append ( tipsBox )
167- screen . append ( detailsBox )
168-
169- // Update details box when selection changes
170- table . rows . on ( 'select item' , ( ) => {
171- const selectedIndex = table . rows . selected
172- if ( selectedIndex !== undefined && selectedIndex >= 0 ) {
173- const selectedRow = filteredLogs [ selectedIndex ]
174- detailsBox . setContent ( formatResult ( selectedRow ) )
175- screen . render ( )
176- }
177- } )
178-
179- screen . render ( )
180-
181- screen . key ( [ 'return' ] , ( ) => {
182- const selectedIndex = table . rows . selected
183- screen . destroy ( )
184- const selectedRow = formattedOutput [ selectedIndex ]
185- ? formatResult ( filteredLogs [ selectedIndex ] , true )
186- : '(none)'
187- logger . log ( `Last selection:\n${ selectedRow . trim ( ) } ` )
188- } )
68+ await outputWithBlessed ( result . data , orgSlug )
18969}
19070
19171function formatResult (
@@ -308,3 +188,130 @@ ${table}
308188 return ''
309189 }
310190}
191+
192+ async function outputWithBlessed (
193+ data : SocketSdkReturnType < 'getAuditLogEvents' > [ 'data' ] ,
194+ orgSlug : string ,
195+ ) {
196+ const filteredLogs = data . results
197+ const formattedOutput = filteredLogs . map ( logs => [
198+ logs . event_id ?? '' ,
199+ msAtHome ( logs . created_at ?? '' ) ,
200+ logs . type ?? '' ,
201+ logs . user_email ?? '' ,
202+ logs . ip_address ?? '' ,
203+ logs . user_agent ?? '' ,
204+ ] )
205+ const headers = [
206+ ' Event id' ,
207+ ' Created at' ,
208+ ' Event type' ,
209+ ' User email' ,
210+ ' IP address' ,
211+ ' User agent' ,
212+ ]
213+
214+ // Note: this temporarily takes over the terminal (just like `man` does).
215+ const ScreenWidget = require ( 'blessed/lib/widgets/screen.js' )
216+ // Lazily access constants.blessedOptions.
217+ const screen : Widgets . Screen = new ScreenWidget ( {
218+ ...constants . blessedOptions ,
219+ } )
220+ // Register these keys first so you can always exit, even when it gets stuck
221+ // If we don't do this and the code crashes, the user must hard-kill the
222+ // node process just to exit it. That's very bad UX.
223+ // eslint-disable-next-line n/no-process-exit
224+ screen . key ( [ 'escape' , 'q' , 'C-c' ] , ( ) => process . exit ( 0 ) )
225+
226+ const TableWidget = require ( 'blessed-contrib/lib/widget/table.js' )
227+ const tipsBoxHeight = 1 // 1 row for tips box
228+ const detailsBoxHeight = 20 // bottom N rows for details box. 20 gives 4 lines for condensed payload before it scrolls out of view
229+
230+ const maxWidths = headers . map ( s => s . length + 1 )
231+ formattedOutput . forEach ( row => {
232+ row . forEach ( ( str , i ) => {
233+ maxWidths [ i ] = Math . max ( str . length , maxWidths [ i ] ?? str . length )
234+ } )
235+ } )
236+
237+ const table : any = new TableWidget ( {
238+ keys : 'true' ,
239+ fg : 'white' ,
240+ selectedFg : 'white' ,
241+ selectedBg : 'magenta' ,
242+ interactive : 'true' ,
243+ label : `Audit Logs for ${ orgSlug } ` ,
244+ width : '100%' ,
245+ top : 0 ,
246+ bottom : detailsBoxHeight + tipsBoxHeight ,
247+ border : {
248+ type : 'line' ,
249+ fg : 'cyan' ,
250+ } ,
251+ columnWidth : maxWidths , //[10, 30, 40, 25, 15, 200],
252+ // Note: spacing works as long as you don't reserve more than total width
253+ columnSpacing : 4 ,
254+ truncate : '_' ,
255+ } )
256+
257+ const BoxWidget = require ( 'blessed/lib/widgets/box.js' )
258+ const tipsBox : Widgets . BoxElement = new BoxWidget ( {
259+ bottom : detailsBoxHeight , // sits just above the details box
260+ height : tipsBoxHeight ,
261+ width : '100%' ,
262+ style : {
263+ fg : 'yellow' ,
264+ bg : 'black' ,
265+ } ,
266+ tags : true ,
267+ content : `↑/↓: Move Enter: Select q/ESC: Quit` ,
268+ } )
269+ const detailsBox : Widgets . BoxElement = new BoxWidget ( {
270+ bottom : 0 ,
271+ height : detailsBoxHeight ,
272+ width : '100%' ,
273+ border : {
274+ type : 'line' ,
275+ fg : 'cyan' ,
276+ } ,
277+ label : 'Details' ,
278+ content : formatResult ( filteredLogs [ 0 ] , true ) ,
279+ style : {
280+ fg : 'white' ,
281+ } ,
282+ } )
283+
284+ table . setData ( {
285+ headers : headers ,
286+ data : formattedOutput ,
287+ } )
288+
289+ // allow control the table with the keyboard
290+ table . focus ( )
291+
292+ // Stacking order: table (top), tipsBox (middle), detailsBox (bottom)
293+ screen . append ( table )
294+ screen . append ( tipsBox )
295+ screen . append ( detailsBox )
296+
297+ // Update details box when selection changes
298+ table . rows . on ( 'select item' , ( ) => {
299+ const selectedIndex = table . rows . selected
300+ if ( selectedIndex !== undefined && selectedIndex >= 0 ) {
301+ const selectedRow = filteredLogs [ selectedIndex ]
302+ detailsBox . setContent ( formatResult ( selectedRow ) )
303+ screen . render ( )
304+ }
305+ } )
306+
307+ screen . render ( )
308+
309+ screen . key ( [ 'return' ] , ( ) => {
310+ const selectedIndex = table . rows . selected
311+ screen . destroy ( )
312+ const selectedRow = formattedOutput [ selectedIndex ]
313+ ? formatResult ( filteredLogs [ selectedIndex ] , true )
314+ : '(none)'
315+ logger . log ( `Last selection:\n${ selectedRow . trim ( ) } ` )
316+ } )
317+ }
0 commit comments