@@ -7,7 +7,7 @@ import * as Console from 'effect/Console';
77import * as Data from 'effect/Data' ;
88import * as Effect from 'effect/Effect' ;
99import * as Layer from 'effect/Layer' ;
10- import open , { type AppName } from 'open' ;
10+ import open , { type AppName , apps } from 'open' ;
1111
1212import * as Server from '../Server.js' ;
1313
@@ -22,7 +22,15 @@ export const typesync = Command.make('typesync', {
2222 Options . withDescription ( 'If true, opens the Typesync studio in your browser' ) ,
2323 Options . withDefault ( true ) ,
2424 ) ,
25- browser : Options . choice ( 'browser' , [ 'chrome' , 'firefox' , 'edge' , 'browser' , 'browserPrivate' ] ) . pipe (
25+ browser : Options . choice ( 'browser' , [
26+ 'chrome' ,
27+ 'firefox' ,
28+ 'edge' ,
29+ 'safari' ,
30+ 'arc' ,
31+ 'browser' ,
32+ 'browserPrivate' ,
33+ ] ) . pipe (
2634 Options . withAlias ( 'b' ) ,
2735 Options . withDescription ( 'Broweser to open the Typesync studio app in. Default is your default selected browser' ) ,
2836 Options . withDefault ( 'browser' ) ,
@@ -60,19 +68,46 @@ export const typesync = Command.make('typesync', {
6068 ) ,
6169) ;
6270
63- const openBrowser = ( port : number , browser : AppName ) =>
71+ const openBrowser = ( port : number , browser : AppName | 'arc' | 'safari' | 'browser' | 'browserPrivate' ) =>
6472 Effect . async < void , OpenBrowserError > ( ( resume ) => {
65- open ( `http://localhost:${ port } ` , {
66- app : { name : browser } ,
67- } ) . then ( ( subprocess ) => {
68- // wait for child process to start before succeeding
69- subprocess . on ( 'spawn' , ( ) => {
70- resume ( Effect . void ) ;
71- } ) ;
72- subprocess . on ( 'error' , ( err ) => {
73- resume ( Effect . fail ( new OpenBrowserError ( { cause : err } ) ) ) ;
73+ const url = `http://localhost:${ port } ` ;
74+
75+ const launch = ( appOpts ?: { name : string | readonly string [ ] } ) =>
76+ open ( url , appOpts ? { app : appOpts } : undefined ) . then ( ( subprocess ) => {
77+ subprocess . on ( 'spawn' , ( ) => resume ( Effect . void ) ) ;
78+ subprocess . on ( 'error' , ( err ) => resume ( Effect . fail ( new OpenBrowserError ( { cause : err } ) ) ) ) ;
7479 } ) ;
75- } ) ;
80+
81+ const mapBrowserName = ( b : typeof browser ) : string | readonly string [ ] | undefined => {
82+ switch ( b ) {
83+ case 'chrome' :
84+ return apps . chrome ; // cross-platform alias from open
85+ case 'firefox' :
86+ return apps . firefox ;
87+ case 'edge' :
88+ return apps . edge ;
89+ case 'safari' :
90+ return 'Safari' ;
91+ case 'arc' :
92+ return 'Arc' ;
93+ default :
94+ return undefined ;
95+ }
96+ } ;
97+
98+ switch ( browser ) {
99+ case 'browser' :
100+ launch ( ) ;
101+ break ;
102+ case 'browserPrivate' :
103+ launch ( { name : apps . browserPrivate } ) ;
104+ break ;
105+ default : {
106+ const mapped = mapBrowserName ( browser ) ;
107+ mapped ? launch ( { name : mapped } ) . catch ( ( ) => launch ( ) ) : launch ( ) ;
108+ break ;
109+ }
110+ }
76111 } ) ;
77112
78113export class OpenBrowserError extends Data . TaggedError ( '/typesync/errors/OpenBrowserError' ) < {
0 commit comments