figma-console-mcp-cli 0.2.1 → 0.4.0
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/README.md +17 -4
- package/dist/index.js +40 -20
- package/dist/index.js.map +1 -1
- package/dist/steps/auth.js +6 -1
- package/dist/steps/auth.js.map +1 -1
- package/dist/steps/clientDetect.d.ts +2 -0
- package/dist/steps/clientDetect.js +62 -12
- package/dist/steps/clientDetect.js.map +1 -1
- package/dist/steps/configure.d.ts +5 -1
- package/dist/steps/configure.js +22 -12
- package/dist/steps/configure.js.map +1 -1
- package/dist/steps/connection.d.ts +2 -1
- package/dist/steps/connection.js +39 -131
- package/dist/steps/connection.js.map +1 -1
- package/dist/steps/doctor.d.ts +1 -0
- package/dist/steps/doctor.js +192 -0
- package/dist/steps/doctor.js.map +1 -0
- package/dist/steps/healthCheck.d.ts +2 -2
- package/dist/steps/healthCheck.js +60 -109
- package/dist/steps/healthCheck.js.map +1 -1
- package/dist/steps/installMethod.d.ts +7 -0
- package/dist/steps/installMethod.js +110 -0
- package/dist/steps/installMethod.js.map +1 -0
- package/dist/steps/systemCheck.js.map +1 -1
- package/dist/utils/config.d.ts +3 -1
- package/dist/utils/config.js +22 -3
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.js +5 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/platform.d.ts +1 -0
- package/dist/utils/platform.js +7 -1
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/process.d.ts +7 -0
- package/dist/utils/process.js +67 -0
- package/dist/utils/process.js.map +1 -0
- package/package.json +5 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/steps/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/steps/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAA4B;IAE5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;IAE1D,MAAM,OAAO,GACX,aAAa,CAAC,IAAI,KAAK,OAAO;QAC5B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,eAAwB;IACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAEvD,IAAI,YAAoB,CAAC;IAEzB,IAAI,eAAe,EAAE,CAAC;QACpB,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC;QAE3D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,4CAA4C,YAAY,EAAE,CAAC,CACtE,CAAC;YACF,OAAO;QACT,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAElD,MAAM,MAAM,GAAG,SAAS,CACtB,KAAK,EACL,CAAC,0BAA0B,EAAE,cAAc,CAAC,EAC5C;YACE,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,KAAK,EAAE,IAAI;SACZ,CACF,CAAC;QAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,oEAAoE,CACrE,CACF,CAAC;YACF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YACtD,CAAC;YACD,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CACT,iEAAiE,CAClE,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,YAAY,IAAI,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CACT,qEAAqE,CACtE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runDoctor(): Promise<void>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { select, checkbox } from '@inquirer/prompts';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { getClients } from './clientDetect.js';
|
|
5
|
+
import { readJsonConfig, writeJsonConfig, detectInstallMethodFromConfig, } from '../utils/config.js';
|
|
6
|
+
import { configureClaudeCode, configureJsonClient, isFigmaConsoleConfigured, } from './configure.js';
|
|
7
|
+
import { promptForToken } from './auth.js';
|
|
8
|
+
import { selectInstallMethod } from './installMethod.js';
|
|
9
|
+
function maskToken(token) {
|
|
10
|
+
if (token.length <= 9)
|
|
11
|
+
return token;
|
|
12
|
+
return `${token.slice(0, 5)}****${token.slice(-4)}`;
|
|
13
|
+
}
|
|
14
|
+
async function scanClients() {
|
|
15
|
+
const clients = await getClients();
|
|
16
|
+
return clients.map((client) => {
|
|
17
|
+
if (client.id === 'claude-code') {
|
|
18
|
+
return {
|
|
19
|
+
client,
|
|
20
|
+
configured: client.detected && isFigmaConsoleConfigured(),
|
|
21
|
+
token: null,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (!client.detected || !client.configPath) {
|
|
25
|
+
return { client, configured: false, token: null };
|
|
26
|
+
}
|
|
27
|
+
const config = readJsonConfig(client.configPath);
|
|
28
|
+
const mcpServers = config.mcpServers;
|
|
29
|
+
const figmaConsole = mcpServers?.['figma-console'];
|
|
30
|
+
if (!figmaConsole) {
|
|
31
|
+
return { client, configured: false, token: null };
|
|
32
|
+
}
|
|
33
|
+
const env = figmaConsole.env;
|
|
34
|
+
const token = env?.FIGMA_ACCESS_TOKEN ?? null;
|
|
35
|
+
return { client, configured: true, token };
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function displayResults(results) {
|
|
39
|
+
console.log(chalk.bold('\n Integration Status:\n'));
|
|
40
|
+
for (const { client, configured, token } of results) {
|
|
41
|
+
if (!client.detected) {
|
|
42
|
+
console.log(chalk.dim(` · ${client.name.padEnd(20)} not detected`));
|
|
43
|
+
}
|
|
44
|
+
else if (!configured) {
|
|
45
|
+
console.log(chalk.dim(` · ${client.name.padEnd(20)} not configured`));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const tokenDisplay = client.id === 'claude-code'
|
|
49
|
+
? 'managed by CLI'
|
|
50
|
+
: token
|
|
51
|
+
? maskToken(token)
|
|
52
|
+
: 'no token';
|
|
53
|
+
console.log(chalk.green(` ✓ ${client.name.padEnd(20)} configured`) +
|
|
54
|
+
chalk.dim(` (token: ${tokenDisplay})`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
console.log('');
|
|
58
|
+
}
|
|
59
|
+
async function updateToken(results) {
|
|
60
|
+
const token = await promptForToken();
|
|
61
|
+
const configured = results.filter((r) => r.configured);
|
|
62
|
+
for (const { client } of configured) {
|
|
63
|
+
try {
|
|
64
|
+
const method = client.configPath
|
|
65
|
+
? detectInstallMethodFromConfig(client.configPath)
|
|
66
|
+
: { type: 'npx' };
|
|
67
|
+
if (client.id === 'claude-code') {
|
|
68
|
+
await configureClaudeCode(token, method);
|
|
69
|
+
}
|
|
70
|
+
else if (client.configPath) {
|
|
71
|
+
configureJsonClient(client, token, method);
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk.green(` ✓ ${client.name} updated`));
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
77
|
+
console.log(chalk.red(` ✗ ${client.name} failed: ${message}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async function removeIntegrations(results) {
|
|
82
|
+
const configured = results.filter((r) => r.configured);
|
|
83
|
+
const toRemove = await checkbox({
|
|
84
|
+
message: 'Select clients to remove integration from:',
|
|
85
|
+
choices: configured.map((r) => ({
|
|
86
|
+
name: r.client.name,
|
|
87
|
+
value: r.client.id,
|
|
88
|
+
})),
|
|
89
|
+
});
|
|
90
|
+
if (toRemove.length === 0) {
|
|
91
|
+
console.log(chalk.dim(' No clients selected.'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const id of toRemove) {
|
|
95
|
+
const result = configured.find((r) => r.client.id === id);
|
|
96
|
+
try {
|
|
97
|
+
if (id === 'claude-code') {
|
|
98
|
+
execSync('claude mcp remove figma-console -s user', {
|
|
99
|
+
stdio: 'ignore',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else if (result.client.configPath) {
|
|
103
|
+
const config = readJsonConfig(result.client.configPath);
|
|
104
|
+
const mcpServers = config.mcpServers ?? {};
|
|
105
|
+
delete mcpServers['figma-console'];
|
|
106
|
+
config.mcpServers = mcpServers;
|
|
107
|
+
writeJsonConfig(result.client.configPath, config);
|
|
108
|
+
}
|
|
109
|
+
console.log(chalk.green(` ✓ ${result.client.name} removed`));
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
113
|
+
console.log(chalk.red(` ✗ ${result.client.name} failed: ${message}`));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function addIntegrations(results) {
|
|
118
|
+
const unconfigured = results.filter((r) => r.client.detected && !r.configured);
|
|
119
|
+
const toAdd = await checkbox({
|
|
120
|
+
message: 'Select clients to add integration to:',
|
|
121
|
+
choices: unconfigured.map((r) => ({
|
|
122
|
+
name: r.client.name,
|
|
123
|
+
value: r.client.id,
|
|
124
|
+
})),
|
|
125
|
+
});
|
|
126
|
+
if (toAdd.length === 0) {
|
|
127
|
+
console.log(chalk.dim(' No clients selected.'));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const existingToken = results.find((r) => r.token)?.token;
|
|
131
|
+
let token;
|
|
132
|
+
if (existingToken) {
|
|
133
|
+
const reuse = await select({
|
|
134
|
+
message: `Use existing token (${maskToken(existingToken)})?`,
|
|
135
|
+
choices: [
|
|
136
|
+
{ name: 'Yes, reuse existing token', value: 'reuse' },
|
|
137
|
+
{ name: 'No, enter a new token', value: 'new' },
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
token = reuse === 'reuse' ? existingToken : await promptForToken();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
token = await promptForToken();
|
|
144
|
+
}
|
|
145
|
+
const method = await selectInstallMethod();
|
|
146
|
+
for (const id of toAdd) {
|
|
147
|
+
const result = unconfigured.find((r) => r.client.id === id);
|
|
148
|
+
try {
|
|
149
|
+
if (id === 'claude-code') {
|
|
150
|
+
await configureClaudeCode(token, method);
|
|
151
|
+
}
|
|
152
|
+
else if (result.client.configPath) {
|
|
153
|
+
configureJsonClient(result.client, token, method);
|
|
154
|
+
}
|
|
155
|
+
console.log(chalk.green(` ✓ ${result.client.name} configured`));
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
159
|
+
console.log(chalk.red(` ✗ ${result.client.name} failed: ${message}`));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export async function runDoctor() {
|
|
164
|
+
while (true) {
|
|
165
|
+
const results = await scanClients();
|
|
166
|
+
displayResults(results);
|
|
167
|
+
const hasConfigured = results.some((r) => r.configured);
|
|
168
|
+
const hasUnconfigured = results.some((r) => r.client.detected && !r.configured);
|
|
169
|
+
const choices = [];
|
|
170
|
+
if (hasConfigured) {
|
|
171
|
+
choices.push({ name: 'Update Figma token', value: 'update' });
|
|
172
|
+
choices.push({ name: 'Remove integration', value: 'remove' });
|
|
173
|
+
}
|
|
174
|
+
if (hasUnconfigured) {
|
|
175
|
+
choices.push({ name: 'Add to unconfigured clients', value: 'add' });
|
|
176
|
+
}
|
|
177
|
+
choices.push({ name: 'Done', value: 'done' });
|
|
178
|
+
const action = await select({
|
|
179
|
+
message: 'What would you like to do?',
|
|
180
|
+
choices,
|
|
181
|
+
});
|
|
182
|
+
if (action === 'done')
|
|
183
|
+
break;
|
|
184
|
+
if (action === 'update')
|
|
185
|
+
await updateToken(results);
|
|
186
|
+
else if (action === 'remove')
|
|
187
|
+
await removeIntegrations(results);
|
|
188
|
+
else if (action === 'add')
|
|
189
|
+
await addIntegrations(results);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/steps/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { Client } from
|
|
2
|
-
export declare function runHealthCheck(clients: Client[]
|
|
1
|
+
import type { Client } from './clientDetect.js';
|
|
2
|
+
export declare function runHealthCheck(clients: Client[]): Promise<void>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import { createServer } from
|
|
3
|
-
import { createHash } from
|
|
4
|
-
import {
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { select } from '@inquirer/prompts';
|
|
5
5
|
const BRIDGE_PORTS = [
|
|
6
6
|
9223, 9224, 9225, 9226, 9227, 9228, 9229, 9230, 9231, 9232,
|
|
7
7
|
];
|
|
8
8
|
const BRIDGE_TIMEOUT_MS = 60_000;
|
|
9
9
|
function tryListen(server, port) {
|
|
10
10
|
return new Promise((resolve) => {
|
|
11
|
-
server.once(
|
|
12
|
-
server.listen(port,
|
|
11
|
+
server.once('error', () => resolve(false));
|
|
12
|
+
server.listen(port, '127.0.0.1', () => resolve(true));
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
function restoreStdin() {
|
|
@@ -35,9 +35,9 @@ async function waitForBridgeWithCancel() {
|
|
|
35
35
|
break;
|
|
36
36
|
}
|
|
37
37
|
if (!bound) {
|
|
38
|
-
return
|
|
38
|
+
return 'connected';
|
|
39
39
|
}
|
|
40
|
-
const spinnerMessage =
|
|
40
|
+
const spinnerMessage = `Waiting for Bridge plugin... ${chalk.dim('(press Escape to cancel)')}`;
|
|
41
41
|
return new Promise((resolve) => {
|
|
42
42
|
let resolved = false;
|
|
43
43
|
const cleanup = () => {
|
|
@@ -47,14 +47,14 @@ async function waitForBridgeWithCancel() {
|
|
|
47
47
|
clearInterval(spinnerInterval);
|
|
48
48
|
clearTimeout(timer);
|
|
49
49
|
// Clear spinner line
|
|
50
|
-
process.stdout.write(`\r${
|
|
50
|
+
process.stdout.write(`\r${' '.repeat(spinnerMessage.length + 6)}\r`);
|
|
51
51
|
server.close();
|
|
52
52
|
restoreStdin();
|
|
53
|
-
process.removeListener(
|
|
53
|
+
process.removeListener('exit', restoreStdin);
|
|
54
54
|
};
|
|
55
55
|
// Spinner
|
|
56
56
|
let frame = 0;
|
|
57
|
-
const SPINNER_FRAMES = [
|
|
57
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
58
58
|
const spinnerInterval = setInterval(() => {
|
|
59
59
|
const f = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
60
60
|
process.stdout.write(`\r ${chalk.cyan(f)} ${spinnerMessage}`);
|
|
@@ -63,61 +63,47 @@ async function waitForBridgeWithCancel() {
|
|
|
63
63
|
// Timeout
|
|
64
64
|
const timer = setTimeout(() => {
|
|
65
65
|
cleanup();
|
|
66
|
-
resolve(
|
|
66
|
+
resolve('timeout');
|
|
67
67
|
}, BRIDGE_TIMEOUT_MS);
|
|
68
68
|
// Escape listener
|
|
69
69
|
if (process.stdin.isTTY) {
|
|
70
70
|
process.stdin.setRawMode(true);
|
|
71
71
|
process.stdin.resume();
|
|
72
|
-
process.stdin.setEncoding(
|
|
73
|
-
process.on(
|
|
72
|
+
process.stdin.setEncoding('utf8');
|
|
73
|
+
process.on('exit', restoreStdin);
|
|
74
74
|
const onData = (data) => {
|
|
75
|
-
if (data ===
|
|
76
|
-
process.stdin.removeListener(
|
|
75
|
+
if (data === '\x1b') {
|
|
76
|
+
process.stdin.removeListener('data', onData);
|
|
77
77
|
cleanup();
|
|
78
|
-
resolve(
|
|
78
|
+
resolve('cancelled');
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
|
-
process.stdin.on(
|
|
81
|
+
process.stdin.on('data', onData);
|
|
82
82
|
// Remove data listener when server closes from other paths
|
|
83
|
-
server.on(
|
|
84
|
-
process.stdin.removeListener(
|
|
83
|
+
server.on('close', () => {
|
|
84
|
+
process.stdin.removeListener('data', onData);
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
// WebSocket upgrade
|
|
88
|
-
server.on(
|
|
89
|
-
const key = req.headers[
|
|
90
|
-
if (typeof key ===
|
|
91
|
-
const accept = createHash(
|
|
92
|
-
.update(key +
|
|
93
|
-
.digest(
|
|
94
|
-
socket.write(
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
server.on('upgrade', (req, socket) => {
|
|
89
|
+
const key = req.headers['sec-websocket-key'];
|
|
90
|
+
if (typeof key === 'string') {
|
|
91
|
+
const accept = createHash('sha1')
|
|
92
|
+
.update(key + '258EAFA5-E914-47DA-95CA-5AB5E34B13E5')
|
|
93
|
+
.digest('base64');
|
|
94
|
+
socket.write('HTTP/1.1 101 Switching Protocols\r\n' +
|
|
95
|
+
'Upgrade: websocket\r\n' +
|
|
96
|
+
'Connection: Upgrade\r\n' +
|
|
97
97
|
`Sec-WebSocket-Accept: ${accept}\r\n` +
|
|
98
|
-
|
|
98
|
+
'\r\n');
|
|
99
99
|
}
|
|
100
100
|
socket.destroy();
|
|
101
101
|
cleanup();
|
|
102
|
-
resolve(
|
|
102
|
+
resolve('connected');
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
const controller = new AbortController();
|
|
109
|
-
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
110
|
-
const res = await fetch("http://localhost:9222", {
|
|
111
|
-
signal: controller.signal,
|
|
112
|
-
});
|
|
113
|
-
clearTimeout(timeout);
|
|
114
|
-
return res.ok || res.status > 0;
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
106
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
121
107
|
async function withSpinner(message, fn) {
|
|
122
108
|
let i = 0;
|
|
123
109
|
const id = setInterval(() => {
|
|
@@ -127,87 +113,52 @@ async function withSpinner(message, fn) {
|
|
|
127
113
|
}, 80);
|
|
128
114
|
try {
|
|
129
115
|
const result = await fn();
|
|
130
|
-
process.stdout.write(`\r${
|
|
116
|
+
process.stdout.write(`\r${' '.repeat(message.length + 6)}\r`);
|
|
131
117
|
return result;
|
|
132
118
|
}
|
|
133
119
|
finally {
|
|
134
120
|
clearInterval(id);
|
|
135
121
|
}
|
|
136
122
|
}
|
|
137
|
-
export async function runHealthCheck(clients
|
|
138
|
-
console.log(chalk.bold(
|
|
139
|
-
if (method === "cdp") {
|
|
140
|
-
const ready = await confirm({
|
|
141
|
-
message: "Have you relaunched Figma with the --remote-debugging-port flag?",
|
|
142
|
-
default: true,
|
|
143
|
-
});
|
|
144
|
-
if (!ready) {
|
|
145
|
-
console.log(chalk.yellow("\n Complete the setup steps above, then run the wizard again.\n"));
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
123
|
+
export async function runHealthCheck(clients) {
|
|
124
|
+
console.log(chalk.bold('\n🏥 Health Check\n'));
|
|
149
125
|
let healthy = false;
|
|
150
126
|
while (!healthy) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const action = await select({
|
|
161
|
-
message: "What would you like to do?",
|
|
162
|
-
choices: [
|
|
163
|
-
{ name: "Retry health check", value: "retry" },
|
|
164
|
-
{ name: "Exit setup", value: "exit" },
|
|
165
|
-
],
|
|
166
|
-
});
|
|
167
|
-
if (action === "exit") {
|
|
168
|
-
console.log(chalk.yellow("\n Setup incomplete. Run the wizard again when ready.\n"));
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
console.log("");
|
|
172
|
-
}
|
|
127
|
+
console.log(chalk.cyan('\n → Start (or restart) the Figma Console Bridge plugin in Figma now.\n'));
|
|
128
|
+
const result = await waitForBridgeWithCancel();
|
|
129
|
+
if (result === 'connected') {
|
|
130
|
+
console.log(chalk.green(' ✓ Bridge plugin connected'));
|
|
131
|
+
healthy = true;
|
|
132
|
+
}
|
|
133
|
+
else if (result === 'cancelled') {
|
|
134
|
+
console.log(chalk.yellow('\n Setup cancelled. Run the wizard again when ready.\n'));
|
|
135
|
+
return;
|
|
173
136
|
}
|
|
174
137
|
else {
|
|
175
|
-
console.log(chalk.
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
138
|
+
console.log(chalk.yellow(' ⚠ Bridge plugin not detected — make sure you started/restarted the plugin after seeing this prompt'));
|
|
139
|
+
const action = await select({
|
|
140
|
+
message: 'What would you like to do?',
|
|
141
|
+
choices: [
|
|
142
|
+
{ name: 'Retry health check', value: 'retry' },
|
|
143
|
+
{ name: 'Exit setup', value: 'exit' },
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
if (action === 'exit') {
|
|
147
|
+
console.log(chalk.yellow('\n Setup incomplete. Run the wizard again when ready.\n'));
|
|
183
148
|
return;
|
|
184
149
|
}
|
|
185
|
-
|
|
186
|
-
console.log(chalk.yellow(" ⚠ Bridge plugin not detected — make sure you started/restarted the plugin after seeing this prompt"));
|
|
187
|
-
const action = await select({
|
|
188
|
-
message: "What would you like to do?",
|
|
189
|
-
choices: [
|
|
190
|
-
{ name: "Retry health check", value: "retry" },
|
|
191
|
-
{ name: "Exit setup", value: "exit" },
|
|
192
|
-
],
|
|
193
|
-
});
|
|
194
|
-
if (action === "exit") {
|
|
195
|
-
console.log(chalk.yellow("\n Setup incomplete. Run the wizard again when ready.\n"));
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
console.log("");
|
|
199
|
-
}
|
|
150
|
+
console.log('');
|
|
200
151
|
}
|
|
201
152
|
}
|
|
202
153
|
// Success dashboard
|
|
203
|
-
console.log(chalk.bold.green(
|
|
204
|
-
console.log(chalk.bold.green(
|
|
205
|
-
console.log(chalk.bold.green(
|
|
206
|
-
console.log(chalk.bold(
|
|
154
|
+
console.log(chalk.bold.green('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
155
|
+
console.log(chalk.bold.green(' ✅ Setup Complete!'));
|
|
156
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
157
|
+
console.log(chalk.bold(' Configured clients:'));
|
|
207
158
|
for (const c of clients) {
|
|
208
159
|
console.log(chalk.green(` • ${c.name}`));
|
|
209
160
|
}
|
|
210
|
-
console.log(chalk.bold(
|
|
161
|
+
console.log(chalk.bold('\n Try these prompts in your AI client:\n'));
|
|
211
162
|
console.log(chalk.dim(' "Take a screenshot of the current Figma file"'));
|
|
212
163
|
console.log(chalk.dim(' "List all components in the design system"'));
|
|
213
164
|
console.log(chalk.dim(' "Create a 400×300 frame with a blue background"\n'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"healthCheck.js","sourceRoot":"","sources":["../../src/steps/healthCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"healthCheck.js","sourceRoot":"","sources":["../../src/steps/healthCheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,MAAM,YAAY,GAAG;IACnB,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;CAC3D,CAAC;AAEF,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAIjC,SAAS,SAAS,CAChB,MAAuC,EACvC,IAAY;IAEZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY;IACnB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,uBAAuB;IACpC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,KAAK;YAAE,MAAM;IACnB,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,cAAc,GAAG,gCAAgC,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,EAAE,CAAC;IAE/F,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE;QAC3C,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,aAAa,CAAC,eAAe,CAAC,CAAC;YAC/B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,qBAAqB;YACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YACrE,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC,CAAC;QAEF,UAAU;QACV,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1E,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACvC,MAAM,CAAC,GAAG,cAAc,CAAC,KAAK,GAAG,cAAc,CAAC,MAAM,CAAE,CAAC;YACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;YAC/D,KAAK,EAAE,CAAC;QACV,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,UAAU;QACV,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,SAAS,CAAC,CAAC;QACrB,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAEtB,kBAAkB;QAClB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAClC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAEjC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAQ,EAAE;gBACpC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpB,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;oBAC7C,OAAO,EAAE,CAAC;oBACV,OAAO,CAAC,WAAW,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC,CAAC;YACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEjC,2DAA2D;YAC3D,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACtB,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,oBAAoB;QACpB,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;YAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;qBAC9B,MAAM,CAAC,GAAG,GAAG,sCAAsC,CAAC;qBACpD,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACpB,MAAM,CAAC,KAAK,CACV,sCAAsC;oBACpC,wBAAwB;oBACxB,yBAAyB;oBACzB,yBAAyB,MAAM,MAAM;oBACrC,MAAM,CACT,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE1E,KAAK,UAAU,WAAW,CACxB,OAAe,EACf,EAAoB;IAEpB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;QAC1B,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAE,CAAC;QACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC,EAAE,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,aAAa,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAiB;IAEjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAE/C,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,OAAO,CAAC,OAAO,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CACR,0EAA0E,CAC3E,CACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,uBAAuB,EAAE,CAAC;QAE/C,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YACxD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,yDAAyD,CAC1D,CACF,CAAC;YACF,OAAO;QACT,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,sGAAsG,CACvG,CACF,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;gBAC1B,OAAO,EAAE,4BAA4B;gBACrC,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,OAAgB,EAAE;oBACvD,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAe,EAAE;iBAC/C;aACF,CAAC,CAAC;YAEH,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,0DAA0D,CAC3D,CACF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAEvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,uDAAuD,CAAC,CACnE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { select, input } from '@inquirer/prompts';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { REPO_URL, DEFAULT_CLONE_DIR_NAME, PACKAGE_NAME, } from '../utils/constants.js';
|
|
8
|
+
import { expandPath } from '../utils/platform.js';
|
|
9
|
+
import { runCommandWithSpinner } from '../utils/process.js';
|
|
10
|
+
function isGitInstalled() {
|
|
11
|
+
try {
|
|
12
|
+
const result = spawnSync('git', ['--version'], {
|
|
13
|
+
encoding: 'utf-8',
|
|
14
|
+
timeout: 5_000,
|
|
15
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
16
|
+
});
|
|
17
|
+
return result.status === 0;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isExistingClone(dir) {
|
|
24
|
+
if (!existsSync(path.join(dir, '.git')))
|
|
25
|
+
return false;
|
|
26
|
+
try {
|
|
27
|
+
const result = spawnSync('git', ['-C', dir, 'remote', 'get-url', 'origin'], {
|
|
28
|
+
encoding: 'utf-8',
|
|
29
|
+
timeout: 5_000,
|
|
30
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
31
|
+
});
|
|
32
|
+
const remote = result.stdout?.trim() ?? '';
|
|
33
|
+
return remote.includes('figma-console-mcp');
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function cloneOrUpdateRepo(targetDir) {
|
|
40
|
+
if (isExistingClone(targetDir)) {
|
|
41
|
+
console.log(chalk.dim(' Existing clone detected — pulling latest…'));
|
|
42
|
+
try {
|
|
43
|
+
await runCommandWithSpinner('git', ['-C', targetDir, 'pull'], 'Pulling updates...', { timeout: 30_000, stdio: 'ignore' });
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// non-fatal — existing clone is still usable
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (existsSync(targetDir)) {
|
|
51
|
+
throw new Error(`Directory already exists but is not the ${PACKAGE_NAME} repo: ${targetDir}`);
|
|
52
|
+
}
|
|
53
|
+
console.log(chalk.dim(` Cloning ${PACKAGE_NAME}…`));
|
|
54
|
+
await runCommandWithSpinner('git', ['clone', REPO_URL, targetDir], 'Cloning repository...', { timeout: 60_000 });
|
|
55
|
+
}
|
|
56
|
+
async function runInstallAndBuild(dir) {
|
|
57
|
+
console.log(chalk.dim(' Installing dependencies…'));
|
|
58
|
+
await runCommandWithSpinner('npm', ['install'], 'Installing dependencies...', { cwd: dir, timeout: 120_000 });
|
|
59
|
+
console.log(chalk.dim(' Building…'));
|
|
60
|
+
await runCommandWithSpinner('npm', ['run', 'build:local'], 'Building project...', { cwd: dir, timeout: 60_000 });
|
|
61
|
+
}
|
|
62
|
+
export async function selectInstallMethod() {
|
|
63
|
+
const method = await select({
|
|
64
|
+
message: 'How should the MCP server be installed?',
|
|
65
|
+
choices: [
|
|
66
|
+
{
|
|
67
|
+
name: 'NPX (Recommended) — auto-updates',
|
|
68
|
+
value: 'npx',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Local Git Clone — for manual update control or contributing',
|
|
72
|
+
value: 'local',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
if (method === 'npx') {
|
|
77
|
+
return { type: 'npx' };
|
|
78
|
+
}
|
|
79
|
+
if (!isGitInstalled()) {
|
|
80
|
+
throw new Error('git is not installed or not on PATH. Install git and try again.');
|
|
81
|
+
}
|
|
82
|
+
const defaultRepoPath = path.join(os.homedir(), DEFAULT_CLONE_DIR_NAME);
|
|
83
|
+
let targetDir;
|
|
84
|
+
if (isExistingClone(defaultRepoPath)) {
|
|
85
|
+
console.log(chalk.dim(` Existing clone found at ${defaultRepoPath}`));
|
|
86
|
+
targetDir = defaultRepoPath;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const repoPath = await input({
|
|
90
|
+
message: `Where should we clone ${PACKAGE_NAME}?`,
|
|
91
|
+
default: defaultRepoPath,
|
|
92
|
+
validate(value) {
|
|
93
|
+
if (!path.isAbsolute(expandPath(value))) {
|
|
94
|
+
return 'Path must be absolute';
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
targetDir = expandPath(repoPath.trim());
|
|
100
|
+
}
|
|
101
|
+
await cloneOrUpdateRepo(targetDir);
|
|
102
|
+
await runInstallAndBuild(targetDir);
|
|
103
|
+
const localJsPath = path.join(targetDir, 'dist', 'local.js');
|
|
104
|
+
if (!existsSync(localJsPath)) {
|
|
105
|
+
throw new Error(`Build succeeded but dist/local.js not found at: ${localJsPath}`);
|
|
106
|
+
}
|
|
107
|
+
console.log(chalk.dim(` Using ${localJsPath}`));
|
|
108
|
+
return { type: 'local', path: localJsPath };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=installMethod.js.map
|