11<?php
22
3- namespace Sensiolabs \TypeScriptBundle ;
3+ namespace Sensiolabs \TypeScriptBundle \ Tools ;
44
5+ use Symfony \Component \Console \Output \OutputInterface ;
56use Symfony \Component \Console \Style \SymfonyStyle ;
67use Symfony \Component \HttpClient \HttpClient ;
7- use Symfony \Component \Process \Process ;
88use Symfony \Contracts \HttpClient \HttpClientInterface ;
99
10- class TypeScriptBinary
10+ class TypescriptBinaryFactory
1111{
1212 private const VERSION = 'v1.3.92 ' ;
1313 private const SWC_RELEASE_URL_PATTERN = 'https://github.com/swc-project/swc/releases/download/%s/%s ' ;
1414
1515 public function __construct (
1616 private readonly string $ binaryDownloadDir ,
17- private readonly ?string $ binaryPath ,
18- private ?SymfonyStyle $ output = null ,
1917 private ?HttpClientInterface $ httpClient = null ,
20- private ?string $ binaryName = null ,
18+ private ?OutputInterface $ output = null ,
2119 ) {
2220 $ this ->httpClient = $ httpClient ?? HttpClient::create ();
2321 }
2422
25- /**
26- * @param array<string> $args
27- */
28- public function createProcess (array $ args ): Process
23+ public function getBinaryFromPath ($ pathToExecutable ): TypeScriptBinary
2924 {
30- if (null === $ this ->binaryPath ) {
31- $ binary = $ this ->getDefaultBinaryPath ();
32- if (!is_file ($ binary )) {
33- $ this ->downloadBinary ();
34- }
35- } else {
36- $ binary = $ this ->binaryPath ;
37- }
38-
39- array_unshift ($ args , $ binary );
40-
41- return new Process ($ args );
25+ return new TypeScriptBinary ($ pathToExecutable );
4226 }
4327
44- public function downloadBinary ( ): void
28+ public function getBinaryFromServerSpecs ( $ os , $ machine , $ kernel ): TypeScriptBinary
4529 {
46- $ targetPath = $ this ->getDefaultBinaryPath ();
47- if (file_exists ($ targetPath )) {
48- return ;
49- }
50-
51- if (!is_dir ($ this ->binaryDownloadDir )) {
52- mkdir ($ this ->binaryDownloadDir , 0777 , true );
30+ $ binaryName = self ::getBinaryNameFromServerSpecs ($ os , $ machine , $ kernel );
31+ if (!file_exists ($ this ->binaryDownloadDir .'/ ' .$ binaryName )) {
32+ $ this ->downloadAndExtract ($ binaryName );
5333 }
5434
55- $ url = sprintf (self ::SWC_RELEASE_URL_PATTERN , self ::VERSION , $ this ->getBinaryName ());
56- $ this ->output ?->note(sprintf ('Downloading TypeScript binary to %s... ' , $ targetPath ));
57-
58- $ response = $ this ->httpClient ->request ('GET ' , $ url , [
59- 'on_progress ' => function (int $ dlNow , int $ dlSize , array $ info ) use (&$ progressBar ): void {
60- if (0 === $ dlSize ) {
61- return ;
62- }
63-
64- if (!$ progressBar ) {
65- $ progressBar = $ this ->output ?->createProgressBar($ dlSize );
66- }
35+ return $ this ->getBinaryFromPath ($ this ->binaryDownloadDir .'/ ' .$ binaryName );
36+ }
6737
68- $ progressBar ?->setProgress($ dlNow );
69- },
70- ]);
71- $ fileHandler = fopen ($ targetPath , 'w ' );
72- foreach ($ this ->httpClient ->stream ($ response ) as $ chunk ) {
73- fwrite ($ fileHandler , $ chunk ->getContent ());
74- }
38+ public function setOutput (?SymfonyStyle $ output ): self
39+ {
40+ $ this ->output = $ output ;
7541
76- fclose ($ fileHandler );
77- chmod ($ targetPath , 7770 );
78- $ progressBar ?->finish();
79- $ this ->output ?->writeln('' );
42+ return $ this ;
8043 }
8144
82- private function getBinaryName ( ): string
45+ public function setHttpClient ( HttpClientInterface $ client ): self
8346 {
84- if (null !== $ this ->binaryName ) {
85- return $ this ->binaryName ;
86- }
87- $ os = strtolower (\PHP_OS );
88- $ machine = strtolower (php_uname ('m ' ));
47+ $ this ->httpClient = $ client ;
8948
49+ return $ this ;
50+ }
51+
52+ public static function getBinaryNameFromServerSpecs (
53+ $ os ,
54+ $ machine ,
55+ $ kernel ,
56+ ) {
57+ list ($ os , $ machine , $ kernel ) = [strtolower ($ os ), strtolower ($ machine ), strtolower ($ kernel )];
9058 if (str_contains ($ os , 'darwin ' )) {
9159 if ('arm64 ' === $ machine ) {
92- return $ this -> binaryName = 'swc-darwin-arm64 ' ;
60+ return 'swc-darwin-arm64 ' ;
9361 }
9462
9563 if ('x86_64 ' === $ machine ) {
96- return $ this -> binaryName = 'swc-darwin-x64 ' ;
64+ return 'swc-darwin-x64 ' ;
9765 }
9866
9967 throw new \Exception (sprintf ('No matching machine found for Darwin platform (Machine: %s). ' , $ machine ));
10068 }
10169
10270 if (str_contains ($ os , 'linux ' )) {
103- $ kernel = strtolower (php_uname ('r ' ));
10471 $ kernelVersion = str_contains ($ kernel , 'musl ' ) ? 'musl ' : 'gnu ' ;
10572 if ('arm64 ' === $ machine || 'aarch64 ' === $ machine ) {
106- return $ this -> binaryName = 'swc-linux-arm64- ' .$ kernelVersion ;
73+ return 'swc-linux-arm64- ' .$ kernelVersion ;
10774 }
10875 if ('x86_64 ' === $ machine ) {
109- return $ this -> binaryName = 'swc-linux-x64- ' .$ kernelVersion ;
76+ return 'swc-linux-x64- ' .$ kernelVersion ;
11077 }
11178
11279 throw new \Exception (sprintf ('No matching machine found for Linux platform (Machine: %s). ' , $ machine ));
11380 }
11481
11582 if (str_contains ($ os , 'win ' )) {
11683 if ('x86_64 ' === $ machine ) {
117- return $ this -> binaryName = 'swc-win32-x64-msvc ' ;
84+ return 'swc-win32-x64-msvc ' ;
11885 }
11986 if ('amd64 ' === $ machine ) {
120- return $ this -> binaryName = 'swc-win32-arm64-msvc ' ;
87+ return 'swc-win32-arm64-msvc ' ;
12188 }
12289 if ('i586 ' === $ machine ) {
123- return $ this -> binaryName = 'swc-win32-ia32-msvc ' ;
90+ return 'swc-win32-ia32-msvc ' ;
12491 }
12592
12693 throw new \Exception (sprintf ('No matching machine found for Windows platform (Machine: %s). ' , $ machine ));
@@ -129,8 +96,45 @@ private function getBinaryName(): string
12996 throw new \Exception (sprintf ('Unknown platform or architecture (OS: %s, Machine: %s). ' , $ os , $ machine ));
13097 }
13198
132- private function getDefaultBinaryPath ( ): string
99+ private function downloadAndExtract ( $ binaryName ): void
133100 {
134- return $ this ->binaryDownloadDir .'/ ' .$ this ->getBinaryName ();
101+ if (!is_dir ($ this ->binaryDownloadDir )) {
102+ mkdir ($ this ->binaryDownloadDir , 0777 , true );
103+ }
104+ $ targetPath = $ this ->binaryDownloadDir .'/ ' .$ binaryName ;
105+ if (file_exists ($ targetPath )) {
106+ return ;
107+ }
108+ $ url = sprintf (self ::SWC_RELEASE_URL_PATTERN , self ::VERSION , $ binaryName );
109+
110+ if ($ this ->output ?->isVerbose()) {
111+ $ this ->output ?->note(sprintf ('Downloading SWC binary from "%s" to "%s"... ' , $ url , $ targetPath ));
112+ } else {
113+ $ this ->output ?->note('Downloading SWC binary ... ' );
114+ }
115+
116+ $ response = $ this ->httpClient ->request ('GET ' , $ url , [
117+ 'on_progress ' => function (int $ dlNow , int $ dlSize , array $ info ) use (&$ progressBar ): void {
118+ if (0 === $ dlSize ) {
119+ return ;
120+ }
121+
122+ if (!$ progressBar ) {
123+ $ progressBar = $ this ->output ?->createProgressBar($ dlSize );
124+ }
125+
126+ $ progressBar ?->setProgress($ dlNow );
127+ },
128+ ]);
129+ $ fileHandler = fopen ($ targetPath , 'w ' );
130+ foreach ($ this ->httpClient ->stream ($ response ) as $ chunk ) {
131+ fwrite ($ fileHandler , $ chunk ->getContent ());
132+ }
133+
134+ fclose ($ fileHandler );
135+ $ progressBar ?->finish();
136+ $ this ->output ?->writeln('' );
137+
138+ chmod ($ this ->binaryDownloadDir .'/ ' .$ binaryName , 7770 );
135139 }
136140}
0 commit comments