-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfast-node-manager.ts
More file actions
119 lines (102 loc) · 3.47 KB
/
fast-node-manager.ts
File metadata and controls
119 lines (102 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { ExampleConfig, FileUtils, getPty, Resource, ResourceSettings, SpawnStatus, Utils, z } from '@codifycli/plugin-core';
import { OS } from '@codifycli/schemas';
import os from 'node:os';
import path from 'node:path';
import { FnmDefaultVersionParameter } from './default-version-parameter.js';
import { FnmNodeVersionsParameter } from './node-versions-parameter.js';
const FNM_DIR = path.join(os.homedir(), '.fnm');
const FNM_MULTISHELL_EXPORT = 'export FNM_MULTISHELL_PATH="${TMPDIR:-/tmp}/fnm_multishells"';
const schema = z.object({
nodeVersions: z
.array(z.string())
.describe('Node.js versions to install via fnm (e.g. ["20", "18.20.0", "lts"])')
.optional(),
defaultVersion: z
.string()
.describe('The default (global) Node.js version set by fnm.')
.optional(),
})
.describe('fast-node-manager resource — install and manage multiple Node.js versions via fnm');
export type FnmConfig = z.infer<typeof schema>;
const defaultConfig: Partial<FnmConfig> = {
nodeVersions: [],
};
const exampleLts: ExampleConfig = {
title: 'Install Node.js LTS via fnm',
description: 'Install fnm and set the latest LTS release as the global Node.js version.',
configs: [{
type: 'fnm',
nodeVersions: ['lts'],
defaultVersion: 'lts',
}],
};
const exampleMultiVersion: ExampleConfig = {
title: 'Install multiple Node.js versions via fnm',
description: 'Install fnm with multiple Node.js versions side by side, using Node.js 22 as the global default.',
configs: [{
type: 'fnm',
nodeVersions: ['18', '20', '22'],
defaultVersion: '22',
}],
};
export class FnmResource extends Resource<FnmConfig> {
getSettings(): ResourceSettings<FnmConfig> {
return {
id: 'fnm',
operatingSystems: [OS.Darwin, OS.Linux],
schema,
defaultConfig,
exampleConfigs: {
example1: exampleLts,
example2: exampleMultiVersion,
},
parameterSettings: {
nodeVersions: { type: 'stateful', definition: new FnmNodeVersionsParameter(), order: 1 },
defaultVersion: { type: 'stateful', definition: new FnmDefaultVersionParameter(), order: 2 },
},
};
}
override async refresh(): Promise<Partial<FnmConfig> | null> {
const $ = getPty();
const { status } = await $.spawnSafe('fnm --version', { interactive: true });
return status === SpawnStatus.SUCCESS ? {} : null;
}
override async create(): Promise<void> {
await install();
}
override async destroy(): Promise<void> {
await uninstall();
}
}
async function install(): Promise<void> {
if (Utils.isLinux()) {
await Utils.installViaPkgMgr('curl unzip');
}
const $ = getPty();
await $.spawn('curl -fsSL https://fnm.vercel.app/install | bash', { interactive: true });
await FileUtils.addToShellRc(FNM_MULTISHELL_EXPORT);
}
async function uninstall(): Promise<void> {
const $ = getPty();
const { status: brewStatus } = await $.spawnSafe('brew list fnm', {
env: { HOMEBREW_NO_AUTO_UPDATE: '1' },
});
if (brewStatus === SpawnStatus.SUCCESS) {
await Utils.uninstallViaPkgMgr('fnm');
} else {
await $.spawnSafe(`rm -rf ${FNM_DIR}`);
}
// Remove the block the installer appends to the shell rc file
for (const line of [
'# fnm',
`FNM_PATH="${FNM_DIR}"`,
'if [ -d "$FNM_PATH" ]; then',
' export PATH="$FNM_PATH:$PATH"',
' eval "$(fnm env --shell zsh)"',
' eval "$(fnm env --shell bash)"',
'fi',
FNM_MULTISHELL_EXPORT,
]) {
await FileUtils.removeLineFromShellRc(line);
}
}