-
-
Notifications
You must be signed in to change notification settings - Fork 636
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
node ace add
command (#4296)
* feat: add Add command * refactor: pass unknown args to configure command * fix: test on windows
- Loading branch information
1 parent
d83e970
commit e7c668c
Showing
2 changed files
with
485 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* @adonisjs/core | ||
* | ||
* (c) AdonisJS | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
import { detectPackageManager, installPackage } from '@antfu/install-pkg' | ||
|
||
import { CommandOptions } from '../types/ace.js' | ||
import { args, BaseCommand, flags } from '../modules/ace/main.js' | ||
|
||
/** | ||
* The install command is used to `npm install` and `node ace configure` a new package | ||
* in one go. | ||
*/ | ||
export default class Add extends BaseCommand { | ||
static commandName = 'install' | ||
static description = 'Install and configure a package' | ||
static options: CommandOptions = { | ||
allowUnknownFlags: true, | ||
} | ||
|
||
@args.string({ description: 'Package name' }) | ||
declare name: string | ||
|
||
@flags.boolean({ description: 'Display logs in verbose mode' }) | ||
declare verbose?: boolean | ||
|
||
@flags.string({ description: 'Select the package manager you want to use' }) | ||
declare packageManager?: 'npm' | 'pnpm' | 'yarn' | ||
|
||
@flags.boolean({ description: 'Should we install the package as a dev dependency', alias: 'D' }) | ||
declare dev?: boolean | ||
|
||
@flags.boolean({ description: 'Forcefully overwrite existing files' }) | ||
declare force?: boolean | ||
|
||
/** | ||
* Detect the package manager to use | ||
*/ | ||
async #getPackageManager() { | ||
const pkgManager = | ||
this.packageManager || (await detectPackageManager(this.app.makePath())) || 'npm' | ||
|
||
if (['npm', 'pnpm', 'yarn'].includes(pkgManager)) { | ||
return pkgManager as 'npm' | 'pnpm' | 'yarn' | ||
} | ||
|
||
throw new Error('Invalid package manager. Must be one of npm, pnpm or yarn') | ||
} | ||
|
||
/** | ||
* Configure the package by delegating the work to the `node ace configure` command | ||
*/ | ||
async #configurePackage() { | ||
/** | ||
* Sending unknown flags to the configure command | ||
*/ | ||
const flagValueArray = this.parsed.unknownFlags | ||
.filter((flag) => !!this.parsed.flags[flag]) | ||
.map((flag) => `--${flag}=${this.parsed.flags[flag]}`) | ||
|
||
const configureArgs = [ | ||
this.name, | ||
this.force ? '--force' : undefined, | ||
this.verbose ? '--verbose' : undefined, | ||
...flagValueArray, | ||
].filter(Boolean) as string[] | ||
|
||
return await this.kernel.exec('configure', configureArgs) | ||
} | ||
|
||
/** | ||
* Install the package using the selected package manager | ||
*/ | ||
async #installPackage(npmPackageName: string) { | ||
const colors = this.colors | ||
const spinner = this.logger | ||
.await(`installing ${colors.green(this.name)} using ${colors.grey(this.packageManager!)}`) | ||
.start() | ||
|
||
spinner.start() | ||
|
||
try { | ||
await installPackage(npmPackageName, { | ||
dev: this.dev, | ||
silent: this.verbose === true ? false : true, | ||
cwd: this.app.makePath(), | ||
packageManager: this.packageManager, | ||
}) | ||
|
||
spinner.update('package installed successfully') | ||
spinner.stop() | ||
|
||
return true | ||
} catch (error) { | ||
spinner.update('unable to install the package') | ||
spinner.stop() | ||
|
||
this.logger.fatal(error) | ||
this.exitCode = 1 | ||
return false | ||
} | ||
} | ||
|
||
/** | ||
* Run method is invoked by ace automatically | ||
*/ | ||
async run() { | ||
const colors = this.colors | ||
this.packageManager = await this.#getPackageManager() | ||
|
||
/** | ||
* Handle special packages to configure | ||
*/ | ||
let npmPackageName = this.name | ||
if (this.name === 'vinejs') { | ||
npmPackageName = '@vinejs/vine' | ||
} else if (this.name === 'edge') { | ||
npmPackageName = 'edge.js' | ||
} | ||
|
||
/** | ||
* Prompt the user to confirm the installation | ||
*/ | ||
const cmd = colors.grey(`${this.packageManager} add ${this.dev ? '-D ' : ''}${this.name}`) | ||
this.logger.info(`Installing the package using the following command : ${cmd}`) | ||
|
||
const shouldInstall = await this.prompt.confirm('Continue ?', { name: 'install' }) | ||
if (!shouldInstall) { | ||
this.logger.info('Installation cancelled') | ||
return | ||
} | ||
|
||
/** | ||
* Install package | ||
*/ | ||
const pkgWasInstalled = await this.#installPackage(npmPackageName) | ||
if (!pkgWasInstalled) { | ||
return | ||
} | ||
|
||
/** | ||
* Configure package | ||
*/ | ||
const { exitCode } = await this.#configurePackage() | ||
this.exitCode = exitCode | ||
if (exitCode === 0) { | ||
this.logger.success(`Installed and configured ${colors.green(this.name)}`) | ||
} else { | ||
this.logger.fatal(`Unable to configure ${colors.green(this.name)}`) | ||
} | ||
} | ||
} |
Oops, something went wrong.