@@ -32,6 +32,8 @@ const fs = require('fs-extra');
32
32
const fg = require ( 'fast-glob' ) ;
33
33
const path = require ( 'path' ) ;
34
34
const consola = require ( 'consola' ) ;
35
+ const bent = require ( 'bent' ) ;
36
+ const tar = require ( 'tar' ) ;
35
37
const Package = require ( './package.js' ) ;
36
38
const { getPrefix} = require ( './utils/vfs.js' ) ;
37
39
const logger = consola . withTag ( 'Packages' ) ;
@@ -42,10 +44,17 @@ const readOrDefault = filename => fs.existsSync(filename)
42
44
? fs . readJsonSync ( filename )
43
45
: [ ] ;
44
46
47
+ const extract = ( stream , target ) => new Promise ( ( resolve , reject ) => {
48
+ stream . once ( 'end' , ( ) => resolve ( ) ) ;
49
+ stream . once ( 'error' , error => reject ( error ) ) ;
50
+ stream . pipe ( tar . extract ( { C : target } ) ) ;
51
+ } ) ;
52
+
45
53
/**
46
54
* @typedef InstallPackageOptions
55
+ * @param {string } root
47
56
* @param {boolean } system
48
- * @param {object } [auth ]
57
+ * @param {object } [headers ]
49
58
*/
50
59
51
60
/**
@@ -144,9 +153,38 @@ class Packages {
144
153
* Installs a package from given url
145
154
* @param {string } url
146
155
* @param {InstallPackageOptions } options
156
+ * @param {object } user
147
157
*/
148
- async installPackage ( url , options ) {
149
- throw new Error ( 'Not implemented yet' ) ;
158
+ async installPackage ( url , options , user ) {
159
+ const { realpath} = this . core . make ( 'osjs/vfs' ) ;
160
+
161
+ const name = path . basename ( url . split ( '?' ) [ 0 ] )
162
+ . replace ( / \. [ ^ / . ] + $ / , '' ) ;
163
+
164
+ const stream = await bent ( ) ( url , null , {
165
+ headers : options . headers || { }
166
+ } ) ;
167
+
168
+ const userRoot = options . root || 'home:/.packages' ; // FIXME: Client-side
169
+ const target = await realpath ( `${ userRoot } /${ name } ` , user ) ;
170
+ const root = await realpath ( userRoot , user ) ;
171
+ const manifest = await realpath ( `${ userRoot } /metadata.json` , user ) ;
172
+
173
+ if ( await fs . exists ( target ) ) {
174
+ throw new Error ( 'Target already exists' ) ;
175
+ }
176
+
177
+ if ( options . system ) {
178
+ throw new Error ( 'System packages not yet implemented' ) ;
179
+ }
180
+
181
+ await fs . mkdir ( target ) ;
182
+ await extract ( stream , target ) ;
183
+
184
+ const filenames = await fg ( root + '/*/metadata.json' ) ;
185
+ const metadatas = await Promise . all ( filenames . map ( f => fs . readJson ( f ) ) ) ;
186
+
187
+ await fs . writeJson ( manifest , metadatas ) ;
150
188
}
151
189
152
190
/**
0 commit comments