11cb0ef41Sopenharmony_ci// npm edit <pkg> 21cb0ef41Sopenharmony_ci// open the package folder in the $EDITOR 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst { resolve } = require('path') 51cb0ef41Sopenharmony_ciconst fs = require('graceful-fs') 61cb0ef41Sopenharmony_ciconst cp = require('child_process') 71cb0ef41Sopenharmony_ciconst completion = require('../utils/completion/installed-shallow.js') 81cb0ef41Sopenharmony_ciconst BaseCommand = require('../base-command.js') 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst splitPackageNames = (path) => { 111cb0ef41Sopenharmony_ci return path.split('/') 121cb0ef41Sopenharmony_ci // combine scoped parts 131cb0ef41Sopenharmony_ci .reduce((parts, part) => { 141cb0ef41Sopenharmony_ci if (parts.length === 0) { 151cb0ef41Sopenharmony_ci return [part] 161cb0ef41Sopenharmony_ci } 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci const lastPart = parts[parts.length - 1] 191cb0ef41Sopenharmony_ci // check if previous part is the first part of a scoped package 201cb0ef41Sopenharmony_ci if (lastPart[0] === '@' && !lastPart.includes('/')) { 211cb0ef41Sopenharmony_ci parts[parts.length - 1] += '/' + part 221cb0ef41Sopenharmony_ci } else { 231cb0ef41Sopenharmony_ci parts.push(part) 241cb0ef41Sopenharmony_ci } 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci return parts 271cb0ef41Sopenharmony_ci }, []) 281cb0ef41Sopenharmony_ci .join('/node_modules/') 291cb0ef41Sopenharmony_ci .replace(/(\/node_modules)+/, '/node_modules') 301cb0ef41Sopenharmony_ci} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ciclass Edit extends BaseCommand { 331cb0ef41Sopenharmony_ci static description = 'Edit an installed package' 341cb0ef41Sopenharmony_ci static name = 'edit' 351cb0ef41Sopenharmony_ci static usage = ['<pkg>[/<subpkg>...]'] 361cb0ef41Sopenharmony_ci static params = ['editor'] 371cb0ef41Sopenharmony_ci static ignoreImplicitWorkspace = false 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // TODO 401cb0ef41Sopenharmony_ci /* istanbul ignore next */ 411cb0ef41Sopenharmony_ci static async completion (opts, npm) { 421cb0ef41Sopenharmony_ci return completion(npm, opts) 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci async exec (args) { 461cb0ef41Sopenharmony_ci if (args.length !== 1) { 471cb0ef41Sopenharmony_ci throw this.usageError() 481cb0ef41Sopenharmony_ci } 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci const path = splitPackageNames(args[0]) 511cb0ef41Sopenharmony_ci const dir = resolve(this.npm.dir, path) 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // graceful-fs does not promisify 541cb0ef41Sopenharmony_ci await new Promise((res, rej) => { 551cb0ef41Sopenharmony_ci fs.lstat(dir, (err) => { 561cb0ef41Sopenharmony_ci if (err) { 571cb0ef41Sopenharmony_ci return rej(err) 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/) 601cb0ef41Sopenharmony_ci const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' }) 611cb0ef41Sopenharmony_ci editor.on('exit', async (code) => { 621cb0ef41Sopenharmony_ci if (code) { 631cb0ef41Sopenharmony_ci return rej(new Error(`editor process exited with code: ${code}`)) 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci try { 661cb0ef41Sopenharmony_ci await this.npm.exec('rebuild', [dir]) 671cb0ef41Sopenharmony_ci } catch (execErr) { 681cb0ef41Sopenharmony_ci rej(execErr) 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci res() 711cb0ef41Sopenharmony_ci }) 721cb0ef41Sopenharmony_ci }) 731cb0ef41Sopenharmony_ci }) 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_cimodule.exports = Edit 77