File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -20,6 +20,7 @@ import { updateCommand } from './commands/update';
2020import { webhooksCommand } from './commands/webhooks/index' ;
2121import { whoamiCommand } from './commands/whoami' ;
2222import { setupCliExitHandler } from './lib/cli-exit' ;
23+ import { printBannerPlain } from './lib/logo' ;
2324import { errorMessage , outputError } from './lib/output' ;
2425import { trackCommand } from './lib/telemetry' ;
2526import { checkForUpdates } from './lib/update-check' ;
@@ -116,6 +117,9 @@ ${pc.gray('Examples:')}
116117` ,
117118 )
118119 . action ( ( ) => {
120+ if ( process . stdout . isTTY ) {
121+ printBannerPlain ( ) ;
122+ }
119123 const opts = program . opts ( ) ;
120124 if ( opts . apiKey ) {
121125 outputError (
Original file line number Diff line number Diff line change 1+ const LOGO_LINES = [
2+ ' ██████╗ ███████╗███████╗███████╗███╗ ██╗██████╗ ' ,
3+ ' ██╔══██╗██╔════╝██╔════╝██╔════╝████╗ ██║██╔══██╗' ,
4+ ' ██████╔╝█████╗ ███████╗█████╗ ██╔██╗ ██║██║ ██║' ,
5+ ' ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██║╚██╗██║██║ ██║' ,
6+ ' ██║ ██║███████╗███████║███████╗██║ ╚████║██████╔╝' ,
7+ ' ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═══╝╚═════╝ ' ,
8+ ] ;
9+
10+ export function printBannerPlain ( ) : void {
11+ process . stdout . write ( '\n' ) ;
12+ for ( const line of LOGO_LINES ) {
13+ process . stdout . write ( `${ line } \n` ) ;
14+ }
15+ process . stdout . write ( '\n' ) ;
16+ }
Original file line number Diff line number Diff line change 1+ import {
2+ afterEach ,
3+ describe ,
4+ expect ,
5+ type MockInstance ,
6+ test ,
7+ vi ,
8+ } from 'vitest' ;
9+ import { printBannerPlain } from '../../src/lib/logo' ;
10+
11+ describe ( 'printBannerPlain' , ( ) => {
12+ let writeSpy : MockInstance ;
13+
14+ afterEach ( ( ) => {
15+ writeSpy ?. mockRestore ( ) ;
16+ } ) ;
17+
18+ test ( 'writes ASCII logo to stdout' , ( ) => {
19+ const chunks : string [ ] = [ ] ;
20+ writeSpy = vi
21+ . spyOn ( process . stdout , 'write' )
22+ . mockImplementation ( ( chunk : unknown ) => {
23+ chunks . push (
24+ typeof chunk === 'string'
25+ ? chunk
26+ : new TextDecoder ( ) . decode ( chunk as Uint8Array ) ,
27+ ) ;
28+ return true ;
29+ } ) ;
30+
31+ printBannerPlain ( ) ;
32+
33+ const out = chunks . join ( '' ) ;
34+ expect ( out ) . toContain ( '██████╗' ) ;
35+ expect ( out ) . toContain ( '█' ) ;
36+ } ) ;
37+ } ) ;
Original file line number Diff line number Diff line change 1+ import { type ExecFileSyncOptions , execFileSync } from 'node:child_process' ;
2+ import { resolve } from 'node:path' ;
3+ import { describe , expect , test } from 'vitest' ;
4+
5+ const CLI = resolve ( import . meta. dirname , '../src/cli.ts' ) ;
6+
7+ const noUpdateEnv = {
8+ ...process . env ,
9+ RESEND_NO_UPDATE_NOTIFIER : '1' ,
10+ NO_COLOR : '1' ,
11+ } ;
12+
13+ describe ( 'no-args welcome' , ( ) => {
14+ test ( 'exits 0 and shows help when invoked with no arguments' , ( ) => {
15+ const execOptions : ExecFileSyncOptions = {
16+ encoding : 'utf-8' ,
17+ timeout : 10_000 ,
18+ env : noUpdateEnv ,
19+ ...( process . platform === 'win32' ? { shell : true } : { } ) ,
20+ } ;
21+ const stdout = execFileSync ( 'npx' , [ 'tsx' , CLI ] , execOptions ) as string ;
22+ expect ( stdout ) . toContain ( 'Usage: resend' ) ;
23+ } ) ;
24+
25+ test ( 'skips banner when stdout is not a TTY' , ( ) => {
26+ const execOptions : ExecFileSyncOptions = {
27+ encoding : 'utf-8' ,
28+ timeout : 10_000 ,
29+ env : noUpdateEnv ,
30+ ...( process . platform === 'win32' ? { shell : true } : { } ) ,
31+ } ;
32+ const stdout = execFileSync ( 'npx' , [ 'tsx' , CLI ] , execOptions ) as string ;
33+ expect ( stdout ) . not . toContain ( '██████╗' ) ;
34+ } ) ;
35+ } ) ;
You can’t perform that action at this time.
0 commit comments