@quenty/nevermore-cli 4.43.2 → 4.43.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/commands/init-command/init-game-command.js +2 -2
- package/dist/commands/init-command/init-game-command.js.map +1 -1
- package/dist/commands/install-package-command.d.ts +14 -0
- package/dist/commands/install-package-command.d.ts.map +1 -1
- package/dist/commands/install-package-command.js +65 -12
- package/dist/commands/install-package-command.js.map +1 -1
- package/dist/utils/package-manager-utils.d.ts +29 -0
- package/dist/utils/package-manager-utils.d.ts.map +1 -0
- package/dist/utils/package-manager-utils.js +89 -0
- package/dist/utils/package-manager-utils.js.map +1 -0
- package/dist/utils/package-manager-utils.test.d.ts +2 -0
- package/dist/utils/package-manager-utils.test.d.ts.map +1 -0
- package/dist/utils/package-manager-utils.test.js +96 -0
- package/dist/utils/package-manager-utils.test.js.map +1 -0
- package/package.json +8 -8
- package/src/commands/init-command/init-game-command.ts +2 -2
- package/src/commands/install-package-command.ts +107 -14
- package/src/utils/package-manager-utils.test.ts +147 -0
- package/src/utils/package-manager-utils.ts +115 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [4.43.4](https://github.com/Quenty/NevermoreEngine/compare/@quenty/nevermore-cli@4.43.3...@quenty/nevermore-cli@4.43.4) (2026-08-16)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **nevermore-cli:** install with the project's package manager ([80f2a19](https://github.com/Quenty/NevermoreEngine/commit/80f2a190e0bc05191221d0a10efed50416869507))
|
|
11
|
+
|
|
12
|
+
## [4.43.3](https://github.com/Quenty/NevermoreEngine/compare/@quenty/nevermore-cli@4.43.2...@quenty/nevermore-cli@4.43.3) (2026-08-13)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @quenty/nevermore-cli
|
|
15
|
+
|
|
6
16
|
## [4.43.2](https://github.com/Quenty/Nevermore/compare/@quenty/nevermore-cli@4.43.1...@quenty/nevermore-cli@4.43.2) (2026-08-12)
|
|
7
17
|
|
|
8
18
|
### Bug Fixes
|
|
@@ -42,12 +42,12 @@ export class InitGameCommand {
|
|
|
42
42
|
OutputHelper.error('Failed to install aftman, is aftman installed?');
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
|
-
await runCommandAsync(args, '
|
|
45
|
+
await runCommandAsync(args, 'pnpm', ['run', 'format'], {
|
|
46
46
|
cwd: srcRoot,
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
catch {
|
|
50
|
-
OutputHelper.error('Failed to run `
|
|
50
|
+
OutputHelper.error('Failed to run `pnpm run format`, is stylua installed?');
|
|
51
51
|
}
|
|
52
52
|
try {
|
|
53
53
|
await runCommandAsync(args, 'selene', ['generate-roblox-std'], {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-game-command.js","sourceRoot":"","sources":["../../../src/commands/init-command/init-game-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAKrE;;GAEG;AACH,MAAM,OAAO,eAAe;IACnB,OAAO,GAAG,CAAC,kBAAkB,EAAE,gBAAgB,CAAQ,CAAC;IACxD,QAAQ,GAAG,iDAAiD,CAAC;IAE7D,OAAO,CAAC,IAAa;QAC1B,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE;YAC3B,QAAQ,EAAE,iCAAiC;YAC3C,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QACH,OAAO,IAA0B,CAAC;IACpC,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,kBAAkB,CACpC,IAAyB,EACzB,OAAe,EACf,QAAkB;QAElB,4EAA4E;QAC5E,MAAM,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;QAE9D,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,EAAE;YAC5D,GAAG,EAAE,OAAO;SACb,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;gBAC3C,GAAG,EAAE,OAAO;aACb,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,CAAC,KAAK,CAChB,wDAAwD,CACzD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE;gBACjD,GAAG,EAAE,OAAO;aACb,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"init-game-command.js","sourceRoot":"","sources":["../../../src/commands/init-command/init-game-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { Argv, CommandModule } from 'yargs';
|
|
|
5
5
|
import { NevermoreGlobalArgs } from '../args/global-args.js';
|
|
6
6
|
export interface InstallPackageArgs extends NevermoreGlobalArgs {
|
|
7
7
|
packages: string[];
|
|
8
|
+
packageManager?: string;
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Install a Nevermore package from npm
|
|
@@ -14,8 +15,21 @@ export declare class InstallPackageCommand<T> implements CommandModule<T, Instal
|
|
|
14
15
|
aliases: string[];
|
|
15
16
|
describe: string;
|
|
16
17
|
private static _validatePackageName;
|
|
18
|
+
/**
|
|
19
|
+
* Lists the published `@quenty/*` package names, without the scope.
|
|
20
|
+
*
|
|
21
|
+
* The registry caps search results at 250 per request, well under the number
|
|
22
|
+
* of published packages, so this pages through until the reported total is
|
|
23
|
+
* covered.
|
|
24
|
+
*/
|
|
17
25
|
private static _getPackages;
|
|
26
|
+
/**
|
|
27
|
+
* Asks the registry about one package directly. Returns undefined when the
|
|
28
|
+
* registry can't be reached, so an offline run doesn't look like a typo.
|
|
29
|
+
*/
|
|
30
|
+
private static _packageExistsAsync;
|
|
18
31
|
builder(args: Argv<T>): Argv<InstallPackageArgs>;
|
|
32
|
+
private static _resolvePackageManagerAsync;
|
|
19
33
|
handler(args: InstallPackageArgs): Promise<void>;
|
|
20
34
|
}
|
|
21
35
|
//# sourceMappingURL=install-package-command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-package-command.d.ts","sourceRoot":"","sources":["../../src/commands/install-package-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"install-package-command.d.ts","sourceRoot":"","sources":["../../src/commands/install-package-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAU7D,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,qBAAqB,CAAC,CAAC,CAClC,YAAW,aAAa,CAAC,CAAC,EAAE,kBAAkB,CAAC;IAExC,OAAO,SAA0B;IACjC,OAAO,WAAS;IAChB,QAAQ,SAAyC;IAExD,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAMnC;;;;;;OAMG;mBACkB,YAAY;IAgCjC;;;OAGG;mBACkB,mBAAmB;IAmBjC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAgBX,IAAI,CAAC,kBAAkB,CAAC;mBAGpB,2BAA2B;IAmBnC,OAAO,CAAC,IAAI,EAAE,kBAAkB;CA4C9C"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
5
5
|
import { runCommandAsync } from '../utils/nevermore-cli-utils.js';
|
|
6
|
+
import { buildAddPackagesCommand, detectPackageManagerAsync, isPackageManager, PACKAGE_MANAGERS, } from '../utils/package-manager-utils.js';
|
|
6
7
|
/**
|
|
7
8
|
* Install a Nevermore package from npm
|
|
8
9
|
*/
|
|
@@ -15,19 +16,54 @@ export class InstallPackageCommand {
|
|
|
15
16
|
throw new Error('Package name is required!');
|
|
16
17
|
}
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Lists the published `@quenty/*` package names, without the scope.
|
|
21
|
+
*
|
|
22
|
+
* The registry caps search results at 250 per request, well under the number
|
|
23
|
+
* of published packages, so this pages through until the reported total is
|
|
24
|
+
* covered.
|
|
25
|
+
*/
|
|
18
26
|
static async _getPackages() {
|
|
27
|
+
const pageSize = 250;
|
|
28
|
+
const names = new Set();
|
|
19
29
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
let from = 0;
|
|
31
|
+
for (;;) {
|
|
32
|
+
const response = await fetch(`https://registry.npmjs.org/-/v1/search?text=@quenty/&size=${pageSize}&from=${from}`);
|
|
33
|
+
const data = await response.json();
|
|
34
|
+
const objects = data.objects ?? [];
|
|
35
|
+
for (const entry of objects) {
|
|
36
|
+
const name = entry.package?.name ?? '';
|
|
37
|
+
if (name.startsWith('@quenty/')) {
|
|
38
|
+
names.add(name.slice('@quenty/'.length));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
from += objects.length;
|
|
42
|
+
if (objects.length < pageSize || from >= (data.total ?? 0)) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
27
46
|
}
|
|
28
47
|
catch {
|
|
29
48
|
return [];
|
|
30
49
|
}
|
|
50
|
+
return [...names].sort();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Asks the registry about one package directly. Returns undefined when the
|
|
54
|
+
* registry can't be reached, so an offline run doesn't look like a typo.
|
|
55
|
+
*/
|
|
56
|
+
static async _packageExistsAsync(scopedName) {
|
|
57
|
+
try {
|
|
58
|
+
const response = await fetch(`https://registry.npmjs.org/${scopedName.replace('/', '%2f')}`, { method: 'HEAD' });
|
|
59
|
+
if (response.status === 404) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return response.ok ? true : undefined;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
31
67
|
}
|
|
32
68
|
builder(args) {
|
|
33
69
|
args.positional('packages', {
|
|
@@ -39,22 +75,39 @@ export class InstallPackageCommand {
|
|
|
39
75
|
return packages.filter((name) => !current || name.startsWith(current));
|
|
40
76
|
},
|
|
41
77
|
});
|
|
78
|
+
args.option('package-manager', {
|
|
79
|
+
describe: 'Package manager to install with. Detected from the project by default.',
|
|
80
|
+
type: 'string',
|
|
81
|
+
choices: PACKAGE_MANAGERS,
|
|
82
|
+
});
|
|
42
83
|
return args;
|
|
43
84
|
}
|
|
85
|
+
static async _resolvePackageManagerAsync(args, srcRoot) {
|
|
86
|
+
const requested = args.packageManager;
|
|
87
|
+
if (requested) {
|
|
88
|
+
if (!isPackageManager(requested)) {
|
|
89
|
+
throw new Error(`Unsupported package manager '${requested}'. Expected one of: ${PACKAGE_MANAGERS.join(', ')}`);
|
|
90
|
+
}
|
|
91
|
+
return requested;
|
|
92
|
+
}
|
|
93
|
+
return detectPackageManagerAsync(srcRoot);
|
|
94
|
+
}
|
|
44
95
|
async handler(args) {
|
|
45
96
|
const srcRoot = process.cwd();
|
|
46
97
|
if (!args.packages?.length) {
|
|
47
98
|
throw new Error('No packages specified!');
|
|
48
99
|
}
|
|
49
100
|
args.packages.forEach((packageName) => InstallPackageCommand._validatePackageName(packageName));
|
|
50
|
-
const
|
|
51
|
-
const
|
|
101
|
+
const prefixedPackages = args.packages.map((packageName) => `@quenty/${packageName}`);
|
|
102
|
+
const existence = await Promise.all(prefixedPackages.map((scopedName) => InstallPackageCommand._packageExistsAsync(scopedName)));
|
|
103
|
+
const invalidPackages = args.packages.filter((_, index) => existence[index] === false);
|
|
52
104
|
if (invalidPackages.length > 0) {
|
|
53
105
|
throw new Error(`Invalid packages: ${invalidPackages.join(', ')}`);
|
|
54
106
|
}
|
|
55
|
-
const
|
|
56
|
-
OutputHelper.info(`Installing packages: ${args.packages.join(', ')}`);
|
|
57
|
-
|
|
107
|
+
const packageManager = await InstallPackageCommand._resolvePackageManagerAsync(args, srcRoot);
|
|
108
|
+
OutputHelper.info(`Installing packages with ${packageManager}: ${args.packages.join(', ')}`);
|
|
109
|
+
const { command, args: commandArgs } = buildAddPackagesCommand(packageManager, prefixedPackages);
|
|
110
|
+
await runCommandAsync(args, command, commandArgs, {
|
|
58
111
|
cwd: srcRoot,
|
|
59
112
|
});
|
|
60
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-package-command.js","sourceRoot":"","sources":["../../src/commands/install-package-command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"install-package-command.js","sourceRoot":"","sources":["../../src/commands/install-package-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects which package manager owns a project so commands install with the
|
|
3
|
+
* same tool the project was set up with.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PACKAGE_MANAGERS: readonly ["pnpm", "npm", "yarn", "bun"];
|
|
6
|
+
export type PackageManager = typeof PACKAGE_MANAGERS[number];
|
|
7
|
+
export declare const DEFAULT_PACKAGE_MANAGER: PackageManager;
|
|
8
|
+
export declare function isPackageManager(value: string): value is PackageManager;
|
|
9
|
+
/**
|
|
10
|
+
* Detects the package manager for a project, walking up from the given
|
|
11
|
+
* directory so this works from a subfolder of the project.
|
|
12
|
+
*
|
|
13
|
+
* A `packageManager` field wins over a lockfile in the same directory, and the
|
|
14
|
+
* nearest directory with either wins over anything further up. Falls back to
|
|
15
|
+
* pnpm: Nevermore projects are pnpm projects — the templates pin it and gate it
|
|
16
|
+
* behind `only-allow pnpm` — so pnpm is the right guess for a directory that
|
|
17
|
+
* hasn't declared anything yet.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectPackageManagerAsync(startDirectory: string): Promise<PackageManager>;
|
|
20
|
+
/**
|
|
21
|
+
* Builds the command that adds dependencies to a project. Only npm spells this
|
|
22
|
+
* `install`; the rest treat a bare `install` as "install the lockfile" and need
|
|
23
|
+
* `add` to record new dependencies.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildAddPackagesCommand(packageManager: PackageManager, packages: string[]): {
|
|
26
|
+
command: string;
|
|
27
|
+
args: string[];
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=package-manager-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager-utils.d.ts","sourceRoot":"","sources":["../../src/utils/package-manager-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,eAAO,MAAM,gBAAgB,yCAA0C,CAAC;AAExE,MAAM,MAAM,cAAc,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,cAAuB,CAAC;AAW9D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CAEvE;AA4CD;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,cAAc,CAAC,CAiBzB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAMrC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects which package manager owns a project so commands install with the
|
|
3
|
+
* same tool the project was set up with.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
export const PACKAGE_MANAGERS = ['pnpm', 'npm', 'yarn', 'bun'];
|
|
8
|
+
export const DEFAULT_PACKAGE_MANAGER = 'pnpm';
|
|
9
|
+
const LOCKFILES = [
|
|
10
|
+
['pnpm-lock.yaml', 'pnpm'],
|
|
11
|
+
['pnpm-workspace.yaml', 'pnpm'],
|
|
12
|
+
['bun.lock', 'bun'],
|
|
13
|
+
['bun.lockb', 'bun'],
|
|
14
|
+
['yarn.lock', 'yarn'],
|
|
15
|
+
['package-lock.json', 'npm'],
|
|
16
|
+
];
|
|
17
|
+
export function isPackageManager(value) {
|
|
18
|
+
return PACKAGE_MANAGERS.includes(value);
|
|
19
|
+
}
|
|
20
|
+
function parsePackageManagerField(value) {
|
|
21
|
+
if (typeof value !== 'string') {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const name = value.split('@')[0]?.trim();
|
|
25
|
+
if (name && isPackageManager(name)) {
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
async function detectInDirectoryAsync(directory) {
|
|
31
|
+
try {
|
|
32
|
+
const contents = await fs.readFile(path.join(directory, 'package.json'), 'utf-8');
|
|
33
|
+
const parsed = JSON.parse(contents);
|
|
34
|
+
const declared = parsePackageManagerField(parsed.packageManager);
|
|
35
|
+
if (declared) {
|
|
36
|
+
return declared;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// No readable package.json here, fall through to lockfiles
|
|
41
|
+
}
|
|
42
|
+
for (const [fileName, packageManager] of LOCKFILES) {
|
|
43
|
+
try {
|
|
44
|
+
await fs.access(path.join(directory, fileName));
|
|
45
|
+
return packageManager;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Detects the package manager for a project, walking up from the given
|
|
55
|
+
* directory so this works from a subfolder of the project.
|
|
56
|
+
*
|
|
57
|
+
* A `packageManager` field wins over a lockfile in the same directory, and the
|
|
58
|
+
* nearest directory with either wins over anything further up. Falls back to
|
|
59
|
+
* pnpm: Nevermore projects are pnpm projects — the templates pin it and gate it
|
|
60
|
+
* behind `only-allow pnpm` — so pnpm is the right guess for a directory that
|
|
61
|
+
* hasn't declared anything yet.
|
|
62
|
+
*/
|
|
63
|
+
export async function detectPackageManagerAsync(startDirectory) {
|
|
64
|
+
let directory = path.resolve(startDirectory);
|
|
65
|
+
for (;;) {
|
|
66
|
+
const detected = await detectInDirectoryAsync(directory);
|
|
67
|
+
if (detected) {
|
|
68
|
+
return detected;
|
|
69
|
+
}
|
|
70
|
+
const parent = path.dirname(directory);
|
|
71
|
+
if (parent === directory) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
directory = parent;
|
|
75
|
+
}
|
|
76
|
+
return DEFAULT_PACKAGE_MANAGER;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Builds the command that adds dependencies to a project. Only npm spells this
|
|
80
|
+
* `install`; the rest treat a bare `install` as "install the lockfile" and need
|
|
81
|
+
* `add` to record new dependencies.
|
|
82
|
+
*/
|
|
83
|
+
export function buildAddPackagesCommand(packageManager, packages) {
|
|
84
|
+
if (packageManager === 'npm') {
|
|
85
|
+
return { command: 'npm', args: ['install', ...packages] };
|
|
86
|
+
}
|
|
87
|
+
return { command: packageManager, args: ['add', ...packages] };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=package-manager-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager-utils.js","sourceRoot":"","sources":["../../src/utils/package-manager-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager-utils.test.d.ts","sourceRoot":"","sources":["../../src/utils/package-manager-utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { buildAddPackagesCommand, detectPackageManagerAsync, isPackageManager, } from './package-manager-utils.js';
|
|
6
|
+
describe('package-manager-utils', () => {
|
|
7
|
+
let root;
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), 'nevermore-pm-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
async function writeFileAsync(relativePath, contents) {
|
|
15
|
+
const filePath = path.join(root, relativePath);
|
|
16
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
17
|
+
await fs.writeFile(filePath, contents);
|
|
18
|
+
}
|
|
19
|
+
describe('detectPackageManagerAsync', () => {
|
|
20
|
+
it('reads the packageManager field', async () => {
|
|
21
|
+
await writeFileAsync('package.json', JSON.stringify({ packageManager: 'pnpm@10.27.0' }));
|
|
22
|
+
expect(await detectPackageManagerAsync(root)).toBe('pnpm');
|
|
23
|
+
});
|
|
24
|
+
it('prefers the packageManager field over a lockfile', async () => {
|
|
25
|
+
await writeFileAsync('package.json', JSON.stringify({ packageManager: 'yarn@4.0.0' }));
|
|
26
|
+
await writeFileAsync('package-lock.json', '{}');
|
|
27
|
+
expect(await detectPackageManagerAsync(root)).toBe('yarn');
|
|
28
|
+
});
|
|
29
|
+
it('falls back to lockfiles', async () => {
|
|
30
|
+
await writeFileAsync('package.json', JSON.stringify({ name: 'game' }));
|
|
31
|
+
await writeFileAsync('pnpm-lock.yaml', '');
|
|
32
|
+
expect(await detectPackageManagerAsync(root)).toBe('pnpm');
|
|
33
|
+
});
|
|
34
|
+
it('treats a pnpm workspace file as pnpm', async () => {
|
|
35
|
+
await writeFileAsync('pnpm-workspace.yaml', 'packages:\n');
|
|
36
|
+
expect(await detectPackageManagerAsync(root)).toBe('pnpm');
|
|
37
|
+
});
|
|
38
|
+
it('walks up from a subdirectory', async () => {
|
|
39
|
+
await writeFileAsync('package.json', JSON.stringify({ packageManager: 'pnpm@10.27.0' }));
|
|
40
|
+
await fs.mkdir(path.join(root, 'src', 'shared'), { recursive: true });
|
|
41
|
+
expect(await detectPackageManagerAsync(path.join(root, 'src', 'shared'))).toBe('pnpm');
|
|
42
|
+
});
|
|
43
|
+
it('lets the nearest project win', async () => {
|
|
44
|
+
await writeFileAsync('package.json', JSON.stringify({ packageManager: 'pnpm@10.27.0' }));
|
|
45
|
+
await writeFileAsync('nested/package.json', JSON.stringify({ packageManager: 'yarn@4.0.0' }));
|
|
46
|
+
expect(await detectPackageManagerAsync(path.join(root, 'nested'))).toBe('yarn');
|
|
47
|
+
});
|
|
48
|
+
it('ignores an unknown packageManager field', async () => {
|
|
49
|
+
await writeFileAsync('package.json', JSON.stringify({ packageManager: 'cnpm@1.0.0' }));
|
|
50
|
+
await writeFileAsync('yarn.lock', '');
|
|
51
|
+
expect(await detectPackageManagerAsync(root)).toBe('yarn');
|
|
52
|
+
});
|
|
53
|
+
it('survives malformed package.json', async () => {
|
|
54
|
+
await writeFileAsync('package.json', '{ not json');
|
|
55
|
+
await writeFileAsync('pnpm-lock.yaml', '');
|
|
56
|
+
expect(await detectPackageManagerAsync(root)).toBe('pnpm');
|
|
57
|
+
});
|
|
58
|
+
it('defaults to pnpm', async () => {
|
|
59
|
+
expect(await detectPackageManagerAsync(root)).toBe('pnpm');
|
|
60
|
+
});
|
|
61
|
+
it('still honors an npm project', async () => {
|
|
62
|
+
await writeFileAsync('package.json', JSON.stringify({ name: 'game' }));
|
|
63
|
+
await writeFileAsync('package-lock.json', '{}');
|
|
64
|
+
expect(await detectPackageManagerAsync(root)).toBe('npm');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('buildAddPackagesCommand', () => {
|
|
68
|
+
it('uses install for npm', () => {
|
|
69
|
+
expect(buildAddPackagesCommand('npm', ['@quenty/blend'])).toEqual({
|
|
70
|
+
command: 'npm',
|
|
71
|
+
args: ['install', '@quenty/blend'],
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
it('uses add for everything else', () => {
|
|
75
|
+
expect(buildAddPackagesCommand('pnpm', ['@quenty/blend'])).toEqual({
|
|
76
|
+
command: 'pnpm',
|
|
77
|
+
args: ['add', '@quenty/blend'],
|
|
78
|
+
});
|
|
79
|
+
expect(buildAddPackagesCommand('yarn', ['@quenty/maid'])).toEqual({
|
|
80
|
+
command: 'yarn',
|
|
81
|
+
args: ['add', '@quenty/maid'],
|
|
82
|
+
});
|
|
83
|
+
expect(buildAddPackagesCommand('bun', ['@quenty/maid'])).toEqual({
|
|
84
|
+
command: 'bun',
|
|
85
|
+
args: ['add', '@quenty/maid'],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('isPackageManager', () => {
|
|
90
|
+
it('accepts known managers and rejects others', () => {
|
|
91
|
+
expect(isPackageManager('pnpm')).toBe(true);
|
|
92
|
+
expect(isPackageManager('deno')).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=package-manager-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager-utils.test.js","sourceRoot":"","sources":["../../src/utils/package-manager-utils.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/nevermore-cli",
|
|
3
|
-
"version": "4.43.
|
|
3
|
+
"version": "4.43.4",
|
|
4
4
|
"description": "CLI interface for Nevermore",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "https://github.com/Quenty/
|
|
20
|
+
"url": "https://github.com/Quenty/NevermoreEngine.git",
|
|
21
21
|
"directory": "tools/nevermore-cli/"
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/cli-output-helpers": "1.17.
|
|
29
|
-
"@quenty/nevermore-cli-helpers": "1.17.
|
|
30
|
-
"@quenty/nevermore-deploy": "1.1.
|
|
31
|
-
"@quenty/nevermore-template-helpers": "1.18.
|
|
32
|
-
"@quenty/studio-bridge": "0.18.
|
|
28
|
+
"@quenty/cli-output-helpers": "1.17.2",
|
|
29
|
+
"@quenty/nevermore-cli-helpers": "1.17.1",
|
|
30
|
+
"@quenty/nevermore-deploy": "1.1.1",
|
|
31
|
+
"@quenty/nevermore-template-helpers": "1.18.2",
|
|
32
|
+
"@quenty/studio-bridge": "0.18.1",
|
|
33
33
|
"execa": "^9.6.1",
|
|
34
34
|
"find-git-root": "^1.0.4",
|
|
35
35
|
"inquirer": "^13.2.0",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"engines": {
|
|
61
61
|
"node": ">=16"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "7dac4ebe32676fcfaa3748bfc1d57b6d7e442ad4"
|
|
64
64
|
}
|
|
@@ -62,12 +62,12 @@ export class InitGameCommand<T> implements CommandModule<T, InitGameArgs> {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
try {
|
|
65
|
-
await runCommandAsync(args, '
|
|
65
|
+
await runCommandAsync(args, 'pnpm', ['run', 'format'], {
|
|
66
66
|
cwd: srcRoot,
|
|
67
67
|
});
|
|
68
68
|
} catch {
|
|
69
69
|
OutputHelper.error(
|
|
70
|
-
'Failed to run `
|
|
70
|
+
'Failed to run `pnpm run format`, is stylua installed?'
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
|