Skip to content

Commit de8fcee

Browse files
committed
feat: Nevermore-cli command to install packages from npm
1 parent 53bfde9 commit de8fcee

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* Install Nevermore packages from npm
3+
*/
4+
5+
import { Argv, CommandModule } from "yargs";
6+
import { OutputHelper } from "@quenty/cli-output-helpers";
7+
import { NevermoreGlobalArgs } from "../args/global-args";
8+
import {
9+
runCommandAsync,
10+
} from "../utils/nevermore-cli-utils";
11+
12+
export interface InstallPackageArgs extends NevermoreGlobalArgs {
13+
packages: string[];
14+
}
15+
16+
/**
17+
* Install a Nevermore package from npm
18+
*/
19+
export class InstallPackageCommand<T> implements CommandModule<T, InstallPackageArgs> {
20+
public command = "install [packages..]";
21+
public aliases = ["i"];
22+
public describe = "Install Nevermore packages from npm";
23+
24+
private static _validatePackageName(name: string): void {
25+
if (!name) {
26+
throw new Error("Package name is required!");
27+
}
28+
}
29+
30+
private static async _getPackages(): Promise<string[]> {
31+
try {
32+
const response = await fetch(
33+
"https://registry.npmjs.org/-/v1/search?text=@quenty/&size=1000"
34+
);
35+
const data = await response.json();
36+
return data.objects
37+
.map((obj: any) => obj.package.name)
38+
.filter((name: string) => name.startsWith("@quenty/"))
39+
.map((name: string) => name.replace("@quenty/", ""))
40+
.sort();
41+
} catch {
42+
return [];
43+
}
44+
}
45+
46+
public builder(args: Argv<T>) {
47+
args.positional("packages", {
48+
type: "string",
49+
array: true,
50+
describe: "Name of the package(s) to install",
51+
completion: async (current: string) => {
52+
const packages = await InstallPackageCommand._getPackages();
53+
return packages.filter(name => !current || name.startsWith(current));
54+
}
55+
});
56+
return args as Argv<InstallPackageArgs>;
57+
}
58+
59+
public async handler(args: InstallPackageArgs) {
60+
const srcRoot = process.cwd();
61+
62+
if (!args.packages?.length) {
63+
throw new Error("No packages specified!");
64+
}
65+
66+
args.packages.forEach(packageName => InstallPackageCommand._validatePackageName(packageName));
67+
68+
const availablePackages = await InstallPackageCommand._getPackages();
69+
const invalidPackages = args.packages.filter(
70+
packageName => !availablePackages.includes(packageName)
71+
);
72+
73+
if (invalidPackages.length > 0) {
74+
throw new Error(`Invalid packages: ${invalidPackages.join(", ")}`);
75+
}
76+
77+
const prefixedPackages = args.packages.map(packageName => `@quenty/${packageName}`);
78+
79+
OutputHelper.info(`Installing packages: ${args.packages.join(", ")}`);
80+
81+
await runCommandAsync(args, "npm", ["install", ...prefixedPackages], {
82+
cwd: srcRoot,
83+
});
84+
}
85+
}

tools/nevermore-cli/src/nevermore.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { InitGameCommand } from './commands/init-game-command';
1212
import { InitPackageCommand } from './commands/init-package-command';
1313
import { InitPluginCommand } from './commands/init-plugin-command';
1414
import { PackCommand } from './commands/pack-command';
15+
import { InstallPackageCommand } from './commands/install-package';
1516

1617
yargs(hideBin(process.argv))
1718
.scriptName('nevermore')
@@ -34,10 +35,11 @@ yargs(hideBin(process.argv))
3435
.command(new InitPackageCommand() as any)
3536
.command(new InitPluginCommand() as any)
3637
.command(new PackCommand() as any)
38+
.command(new InstallPackageCommand() as any)
3739
.recommendCommands()
3840
.demandCommand(
3941
1,
4042
OutputHelper.formatHint("Hint: See 'nevermore help' for more help")
4143
)
4244
.wrap(null)
43-
.strict().argv;
45+
.strict().argv;

0 commit comments

Comments
 (0)