@@ -4,45 +4,13 @@ import type { Logger } from '@/logger';
44import type { ILogger } from '@/logger/constants' ;
55import { fs } from '@modern-js/codesmith-utils/fs-extra' ;
66import { semver } from '@modern-js/codesmith-utils/semver' ;
7- import pacote from 'pacote' ;
7+ import axios from 'axios' ;
8+ import tar from 'tar' ;
9+ import { getNpmTarballUrl } from './getNpmTarballUrl' ;
810import { fsExists } from './fsExists' ;
911import { getNpmVersion } from './getNpmVersion' ;
1012import { runInstall } from './packageManager' ;
1113
12- async function isValidCache ( cacheDir : string ) {
13- /* generator cache can use
14- * 1. .codesmith.completed exist
15- * 2. cache time is within the validity period
16- */
17- if ( await fsExists ( `${ cacheDir } /.codesmith.completed` ) ) {
18- const preCacheTimeStr = await fs . readFile (
19- `${ cacheDir } /.codesmith.completed` ,
20- {
21- encoding : 'utf-8' ,
22- } ,
23- ) ;
24- const preCacheTime = preCacheTimeStr
25- ? new Date ( preCacheTimeStr )
26- : new Date ( 0 ) ;
27- if ( Number ( new Date ( ) ) - Number ( preCacheTime ) < CATCHE_VALIDITY_PREIOD ) {
28- return true ;
29- }
30- return false ;
31- }
32- return false ;
33- }
34-
35- async function downloadAndDecompressTargz (
36- packageName : string ,
37- version : string ,
38- targetDir : string ,
39- registryUrl ?: string ,
40- ) : Promise < void > {
41- await pacote . extract ( `${ packageName } @${ version } ` , targetDir , {
42- registry : registryUrl ,
43- } ) ;
44- }
45-
4614const GeneratorVersionMap = new Map < string , string > ( ) ;
4715
4816export async function getGeneratorVersion (
@@ -89,6 +57,76 @@ export async function getGeneratorVersion(
8957 return version ;
9058}
9159
60+ async function isValidCache ( cacheDir : string ) {
61+ /* generator cache can use
62+ * 1. .codesmith.completed exist
63+ * 2. cache time is within the validity period
64+ */
65+ if ( await fsExists ( `${ cacheDir } /.codesmith.completed` ) ) {
66+ const preCacheTimeStr = await fs . readFile (
67+ `${ cacheDir } /.codesmith.completed` ,
68+ {
69+ encoding : 'utf-8' ,
70+ } ,
71+ ) ;
72+ const preCacheTime = preCacheTimeStr
73+ ? new Date ( preCacheTimeStr )
74+ : new Date ( 0 ) ;
75+ if ( Number ( new Date ( ) ) - Number ( preCacheTime ) < CATCHE_VALIDITY_PREIOD ) {
76+ return true ;
77+ }
78+ return false ;
79+ }
80+ return false ;
81+ }
82+
83+ async function downloadAndDecompressTargz (
84+ tarballPkg : string ,
85+ targetDir : string ,
86+ ) {
87+ const response = await axios ( {
88+ method : 'get' ,
89+ url : tarballPkg ,
90+ responseType : 'stream' ,
91+ adapter : 'http' ,
92+ } ) ;
93+ if ( response . status !== 200 ) {
94+ throw new Error (
95+ `download tar package get bad status code: ${ response . status } ` ,
96+ ) ;
97+ }
98+ // create tmp file
99+ const randomId = Math . floor ( Math . random ( ) * 10000 ) ;
100+ const tempTgzFilePath = `${ os . tmpdir ( ) } /temp-${ randomId } .tgz` ;
101+
102+ const dest = fs . createWriteStream ( tempTgzFilePath ) ;
103+
104+ await new Promise < void > ( ( resolve , reject ) => {
105+ response . data . pipe ( dest ) ;
106+ response . data . on ( 'error' , ( err : any ) => {
107+ reject ( err ) ;
108+ } ) ;
109+ dest . on ( 'finish' , ( ) => {
110+ resolve ( ) ;
111+ } ) ;
112+ } ) ;
113+ await new Promise < void > ( ( resolve , reject ) => {
114+ fs . createReadStream ( tempTgzFilePath )
115+ . pipe (
116+ tar . x ( {
117+ strip : 1 ,
118+ C : `${ targetDir } ` ,
119+ } ) ,
120+ )
121+ . on ( 'finish' , ( ) => {
122+ resolve ( ) ;
123+ } )
124+ . on ( 'error' , ( err : any ) => {
125+ reject ( err ) ;
126+ } ) ;
127+ } ) ;
128+ }
129+
92130/**
93131 * download npm package
94132 * @param {string } pkgName
@@ -106,10 +144,21 @@ export async function downloadPackage(
106144 } = { } ,
107145) {
108146 const { registryUrl, install, logger } = options ;
109- const version = await getGeneratorVersion ( pkgName , pkgVersion , {
110- registryUrl,
111- logger,
112- } ) ;
147+ let version : string | undefined ;
148+ if ( ! semver . valid ( pkgVersion ) ) {
149+ // get pkgName version
150+ logger ?. timing ( `🕒 get ${ pkgName } version` ) ;
151+ version = await getNpmVersion ( pkgName , {
152+ registryUrl,
153+ version : pkgVersion ,
154+ } ) ;
155+ logger ?. timing ( `🕒 get ${ pkgName } version` , true ) ;
156+ if ( version === undefined ) {
157+ throw new Error ( `package ${ pkgName } @${ pkgVersion } not found in registry` ) ;
158+ }
159+ } else {
160+ version = pkgVersion ;
161+ }
113162 const targetDir = `${ os . tmpdir ( ) } /csmith-generator/${ pkgName } @${ version } ` ;
114163 logger ?. debug ?.(
115164 `💡 [Download Generator Package]: ${ pkgName } @${ version } to ${ targetDir } ` ,
@@ -120,9 +169,16 @@ export async function downloadPackage(
120169 await fs . remove ( targetDir ) ;
121170 await fs . mkdirp ( targetDir ) ;
122171
172+ logger ?. timing ( `🕒 get ${ pkgName } @${ version } tarball url` ) ;
173+ // get package tarball
174+ const tarballPkg = await getNpmTarballUrl ( pkgName , version , {
175+ registryUrl,
176+ } ) ;
177+ logger ?. timing ( `🕒 get ${ pkgName } @${ version } tarball url` , true ) ;
178+
123179 logger ?. timing ( `🕒 download ${ pkgName } @${ version } tarball` ) ;
124180 // download tarball and compress it to target directory
125- await downloadAndDecompressTargz ( pkgName , version , targetDir , registryUrl ) ;
181+ await downloadAndDecompressTargz ( tarballPkg , targetDir ) ;
126182 logger ?. timing ( `🕒 download ${ pkgName } @${ version } tarball` , true ) ;
127183
128184 if ( install ) {
0 commit comments