Skip to content

Commit 3eb6b8a

Browse files
authored
feat: add support for the fnm version manager
* refactor * feat: implements fnm support * fix tests maybe * fix: fnm windows path
2 parents 7fe038e + 64d9bab commit 3eb6b8a

File tree

3 files changed

+80
-6
lines changed

3 files changed

+80
-6
lines changed

src/dap/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export function createUserError(text: string, code = ErrorCodes.UserError): Dap.
6565
export const nvmNotFound = () =>
6666
createUserError(
6767
l10n.t(
68-
"Attribute 'runtimeVersion' requires Node.js version manager 'nvs' or 'nvm' to be installed.",
68+
"Attribute 'runtimeVersion' requires Node.js version manager 'nvs', 'nvm' or 'fnm' to be installed.",
6969
),
7070
ErrorCodes.NvmOrNvsNotFound,
7171
);

src/targets/node/nvmResolver.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const enum Vars {
3636
NvsHome = 'NVS_HOME',
3737
WindowsNvmHome = 'NVM_HOME',
3838
UnixNvmHome = 'NVM_DIR',
39+
FnmHome = 'FNM_DIR',
3940
}
4041

4142
@injectable()
@@ -49,6 +50,10 @@ export class NvmResolver implements INvmResolver {
4950
) {}
5051

5152
public async resolveNvmVersionPath(version: string) {
53+
let directory: string | undefined = undefined;
54+
const versionManagers: string[] = [];
55+
const versionData = this.parseVersionString(version);
56+
5257
let nvsHome = this.env[Vars.NvsHome];
5358
if (!nvsHome) {
5459
// NVS_HOME is not always set. Probe for 'nvs' directory instead
@@ -61,9 +66,6 @@ export class NvmResolver implements INvmResolver {
6166
}
6267
}
6368

64-
let directory: string | undefined = undefined;
65-
const versionManagers: string[] = [];
66-
const versionData = this.parseVersionString(version);
6769
if (versionData.nvsFormat || nvsHome) {
6870
directory = await this.resolveNvs(nvsHome, versionData);
6971
if (!directory && versionData.nvsFormat) {
@@ -87,6 +89,17 @@ export class NvmResolver implements INvmResolver {
8789
}
8890
}
8991

92+
if (!directory) {
93+
const fnmDir =
94+
this.platform === 'win32'
95+
? this.env[Vars.FnmHome] || path.join(this.env['APPDATA'] || '', 'fnm')
96+
: this.env[Vars.FnmHome] || path.join(this.homedir, '.fnm');
97+
if (await this.fsUtils.exists(fnmDir)) {
98+
directory = await this.resolveFnm(version, fnmDir);
99+
versionManagers.push('fnm');
100+
}
101+
}
102+
90103
if (!versionManagers.length) {
91104
throw new ProtocolError(nvmNotFound());
92105
}
@@ -160,6 +173,19 @@ export class NvmResolver implements INvmResolver {
160173
return this.findBinFolderForVersion(nvmHome, `v${version}`);
161174
}
162175

176+
private async resolveFnm(version: string, fnmHome: string) {
177+
const directory = this.findBinFolderForVersion(
178+
path.join(fnmHome, 'node-versions'),
179+
`v${version}`,
180+
);
181+
182+
if (!directory) return;
183+
184+
return this.platform === 'win32'
185+
? path.join(directory, 'installation')
186+
: path.join(directory, 'installation', 'bin');
187+
}
188+
163189
private findBinFolderForVersion(
164190
dir: string,
165191
version: string,

src/test/node/runtimeVersion.test.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ describe('runtimeVersion', () => {
3030
'nvs/node/13.12.0/x64/bin/node': '',
3131
'nvs/node/13.11.0/x86/bin/node': '',
3232
'nvm/versions/node/v13.11.0/bin/node': '',
33+
'fnm/node-versions/v13.10.0/installation/bin/node': '',
3334
});
3435

3536
resolver = new NvmResolver(
3637
fsUtils,
37-
{ NVS_HOME: path.join(testFixturesDir, 'nvs'), NVM_DIR: path.join(testFixturesDir, 'nvm') },
38+
{
39+
NVS_HOME: path.join(testFixturesDir, 'nvs'),
40+
NVM_DIR: path.join(testFixturesDir, 'nvm'),
41+
FNM_DIR: path.join(testFixturesDir, 'fnm'),
42+
},
3843
'x64',
3944
'linux',
4045
testWorkspace,
@@ -48,9 +53,12 @@ describe('runtimeVersion', () => {
4853
const { directory: b } = await resolver.resolveNvmVersionPath('13.11');
4954
expect(b).to.equal(path.join(testFixturesDir, 'nvm/versions/node/v13.11.0/bin'));
5055

56+
const { directory: c } = await resolver.resolveNvmVersionPath('13.10');
57+
expect(c).to.equal(path.join(testFixturesDir, 'fnm/node-versions/v13.10.0/installation/bin'));
58+
5159
await expect(resolver.resolveNvmVersionPath('14')).to.eventually.be.rejectedWith(
5260
ProtocolError,
53-
/not installed using version manager nvs\/nvm/,
61+
/not installed using version manager nvs\/nvm\/fnm/,
5462
);
5563
});
5664

@@ -229,4 +237,44 @@ describe('runtimeVersion', () => {
229237
);
230238
});
231239
});
240+
241+
describe('fnm', () => {
242+
beforeEach(() => {
243+
createFileTree(testFixturesDir, {
244+
'node-versions/v13.12.0/installation/bin/node': '',
245+
'node-versions/v13.3.0/installation/bin/node': '',
246+
'node-versions/v13.invalid/installation/bin/node': '',
247+
});
248+
249+
resolver = new NvmResolver(
250+
fsUtils,
251+
{ FNM_DIR: testFixturesDir },
252+
'x64',
253+
'linux',
254+
testWorkspace,
255+
);
256+
});
257+
258+
it('gets an exact match', async () => {
259+
const { directory, binary } = await resolver.resolveNvmVersionPath('13.3.0');
260+
expect(directory).to.equal(
261+
path.join(testFixturesDir, 'node-versions/v13.3.0/installation/bin'),
262+
);
263+
expect(binary).to.equal('node');
264+
});
265+
266+
it('gets the best matching version', async () => {
267+
const { directory } = await resolver.resolveNvmVersionPath('13');
268+
expect(directory).to.equal(
269+
path.join(testFixturesDir, 'node-versions/v13.12.0/installation/bin'),
270+
);
271+
});
272+
273+
it('throws if no version match', async () => {
274+
await expect(resolver.resolveNvmVersionPath('14')).to.eventually.be.rejectedWith(
275+
ProtocolError,
276+
/not installed/,
277+
);
278+
});
279+
});
232280
});

0 commit comments

Comments
 (0)