11import * as path from 'path' ;
2+ import * as os from 'os' ;
23import { ExtensionInstaller , Extension } from '@ali/ide-extension-installer' ;
34import * as fse from 'fs-extra' ;
45import { from , of } from 'rxjs' ;
5- import { mergeMap , filter } from 'rxjs/operators' ;
6+ import { mergeMap , filter , map } from 'rxjs/operators' ;
7+ import { IExtensionMode } from '@alipay/alex-shared' ;
68import { EXTENSION_DIR , EXTENSION_METADATA_DIR , EXTENSION_FIELD } from './util/constant' ;
79import { getExtension } from './extension/scanner' ;
8- import { IExtensionBasicMetadata , IExtensionDesc , IExtensionIdentity } from './extension/type' ;
10+ import {
11+ IExtensionBasicMetadata ,
12+ IExtensionDesc ,
13+ IExtensionIdentity ,
14+ IExtensionServerOptions ,
15+ } from './extension/type' ;
916import { log , error } from './util/log' ;
1017import checkFramework from './util/check-framework' ;
18+ import { createServer , getHttpUri } from './util/serve-file' ;
1119import { formatExtension } from './util' ;
1220import { createMetadataType } from './extension/metadata-type' ;
1321
1422let extensionInstaller : ExtensionInstaller ;
1523let shouldWriteConfig = false ;
1624
17- export const install = async ( extensionId ?: string [ ] , options ?: { silent : boolean } ) => {
25+ export const install = async (
26+ extensionId ?: string [ ] ,
27+ options ?: { silent : boolean ; mode ?: 'public' | 'internal' }
28+ ) => {
1829 checkFramework ( ) ;
1930
2031 createInstaller ( ) ;
2132
2233 let extensions : IExtensionDesc [ ] = [ ] ;
2334
2435 if ( extensionId ?. length ) {
25- extensions = parseExtensionId ( extensionId ) ;
36+ extensions = parseExtensionId ( extensionId , options ?. mode ) ;
2637 shouldWriteConfig = true ;
2738 await Promise . all ( extensions . map ( ( ext ) => removeExtensionById ( ext ) ) ) ;
2839 } else {
@@ -49,8 +60,12 @@ export const install = async (extensionId?: string[], options?: { silent: boolea
4960 from ( extensions )
5061 . pipe (
5162 mergeMap ( installExtension , 5 ) , // 限制并发数 5
52- mergeMap ( ( extPath ) => ( Array . isArray ( extPath ) ? from ( extPath ) : of ( extPath ) ) ) ,
53- mergeMap ( getExtension , 5 ) ,
63+ mergeMap ( ( [ extPath , mode ] ) =>
64+ Array . isArray ( extPath )
65+ ? from ( extPath . map ( ( p ) => [ p , mode ] as const ) )
66+ : of ( [ extPath , mode ] as const )
67+ ) ,
68+ mergeMap ( ( [ extPath , mode ] ) => getExtension ( extPath , mode ) , 5 ) ,
5469 filter ( ( data ) => ! ! data ) ,
5570 mergeMap ( writeMetadata )
5671 )
@@ -72,6 +87,53 @@ export const install = async (extensionId?: string[], options?: { silent: boolea
7287 ) ;
7388} ;
7489
90+ /**
91+ * 从本地安装扩展
92+ * @param dirs 扩展目录
93+ */
94+ export const installLocalExtensions = async ( dirs : string [ ] , options ?: IExtensionServerOptions ) => {
95+ checkFramework ( ) ;
96+
97+ if ( ! dirs . length ) {
98+ return ;
99+ }
100+
101+ const absoluteDirs = dirs . map ( ( dir ) => path . resolve ( dir ) ) ;
102+
103+ log . start ( '开始安装本地扩展\n' ) ;
104+ const homedir = os . homedir ( ) ;
105+ absoluteDirs . forEach ( ( dir ) => {
106+ let readablePath = dir ;
107+ if ( dir . startsWith ( homedir ) ) {
108+ readablePath = dir . replace ( homedir , '~' ) ;
109+ }
110+ console . log ( ` * ${ readablePath } ` ) ;
111+ } ) ;
112+ console . log ( ) ;
113+
114+ const httpUri = await getHttpUri ( options ) ;
115+
116+ from ( absoluteDirs )
117+ . pipe (
118+ mergeMap ( ( localExtPath ) => getExtension ( localExtPath , 'local' , httpUri ) , 5 ) ,
119+ filter ( ( data ) => ! ! data ) ,
120+ mergeMap ( writeMetadata )
121+ )
122+ . subscribe (
123+ ( ext ) => {
124+ log . info ( `${ formatExtension ( ext ) } 安装完成` ) ;
125+ } ,
126+ ( err ) => {
127+ log . error ( '本地扩展安装失败,请重试' ) ;
128+ console . error ( err ) ;
129+ } ,
130+ ( ) => {
131+ log . success ( '本地扩展安装成功' ) ;
132+ createServer ( absoluteDirs , httpUri ) ;
133+ }
134+ ) ;
135+ } ;
136+
75137async function createInstaller ( ) {
76138 const pkgJSON = fse . readJSONSync ( path . join ( __dirname , '../package.json' ) ) ;
77139 extensionInstaller = new ExtensionInstaller ( {
@@ -141,7 +203,7 @@ function checkExtensionConfig(extensions: Extension[]) {
141203 }
142204}
143205
144- function parseExtensionId ( extensionIds : string [ ] ) {
206+ function parseExtensionId ( extensionIds : string [ ] , mode ?: IExtensionMode ) {
145207 const extensions : IExtensionDesc [ ] = [ ] ;
146208 for ( const extId of extensionIds ) {
147209 const reg = / ^ ( [ a - z A - Z ] [ 0 - 9 a - z A - Z _ - ] * ) \. ( [ a - z A - Z ] [ 0 - 9 a - z A - Z _ - ] * ) (?: @ ( \d + \. \d + \. \d + .* ) ) ? $ / ;
@@ -150,17 +212,18 @@ function parseExtensionId(extensionIds: string[]) {
150212 return error ( `${ extId } 格式不合法,请输入 publisher.name[@version] 的形式` ) ;
151213 }
152214 const [ , publisher , name , version ] = matched ;
153- extensions . push ( { publisher, name, version } ) ;
215+ extensions . push ( { publisher, name, version, mode } ) ;
154216 }
155217 return extensions ;
156218}
157219
158220async function installExtension ( extension : IExtensionDesc ) {
159- return extensionInstaller . install ( {
221+ const extensionPath = await extensionInstaller . install ( {
160222 publisher : extension . publisher ,
161223 name : extension . name ,
162224 version : extension . version ,
163225 } ) ;
226+ return [ extensionPath , extension . mode ] as const ;
164227}
165228
166229async function writeMetadata ( metadata : IExtensionBasicMetadata ) {
0 commit comments