magicpath-ai 1.3.0-beta.3 → 1.3.0-beta.5
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 +63 -8
- package/dist/cli.js +28 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.d.ts +49 -0
- package/dist/commands/add.js +129 -25
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/auth.d.ts +2 -2
- package/dist/commands/auth.js +139 -38
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/clone.js +112 -86
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.js +124 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +284 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/integrate.js +282 -81
- package/dist/commands/integrate.js.map +1 -1
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +138 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/schema.d.ts +2 -0
- package/dist/commands/schema.js +213 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +120 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/skills.d.ts +2 -0
- package/dist/commands/skills.js +55 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +27 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +58 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/util/api.d.ts +3 -0
- package/dist/util/api.js +9 -0
- package/dist/util/api.js.map +1 -1
- package/dist/util/auth.js +5 -0
- package/dist/util/auth.js.map +1 -1
- package/dist/util/component.d.ts +8 -8
- package/dist/util/diff.d.ts +4 -0
- package/dist/util/diff.js +11 -3
- package/dist/util/diff.js.map +1 -1
- package/dist/util/integrate.d.ts +13 -2
- package/dist/util/integrate.js +67 -10
- package/dist/util/integrate.js.map +1 -1
- package/dist/util/output.d.ts +14 -0
- package/dist/util/output.js +27 -0
- package/dist/util/output.js.map +1 -0
- package/package.json +3 -2
- package/skills/magicpath-add-component/SKILL.md +49 -0
- package/skills/magicpath-integrate/SKILL.md +50 -0
- package/skills/magicpath-list/SKILL.md +38 -0
- package/skills/magicpath-shared/SKILL.md +34 -0
package/dist/commands/auth.js
CHANGED
|
@@ -1,63 +1,161 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http from 'http';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { exec } from 'child_process';
|
|
5
5
|
import { MagicPathError } from '../util/error.js';
|
|
6
6
|
import { makeWebUrl, makeAuthUrl } from '../util/api.js';
|
|
7
|
-
import { saveTokens, clearTokens } from '../util/auth.js';
|
|
7
|
+
import { saveTokens, clearTokens, loadTokens } from '../util/auth.js';
|
|
8
|
+
import { isJsonMode, jsonResult, jsonError } from '../util/output.js';
|
|
9
|
+
const LOGIN_TIMEOUT_MS = 120_000;
|
|
10
|
+
const PAGE_STYLE = `
|
|
11
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
12
|
+
body{font-family:Geist,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;background:#fff;color:#1a1a1a;padding:1rem}
|
|
13
|
+
.card{position:relative;width:100%;max-width:32rem;background:#fff;border-radius:1.5rem;box-shadow:0 1px 3px rgba(0,0,0,.1),0 8px 10px -1px rgba(0,0,0,.1);overflow:hidden}
|
|
14
|
+
.gradient{position:absolute;top:0;left:0;right:0;height:12rem;background:radial-gradient(circle at center top,#DCF1E3 0%,#fff 80%);opacity:.2;pointer-events:none}
|
|
15
|
+
.content{position:relative;z-index:1;padding:2rem;display:flex;flex-direction:column;align-items:center}
|
|
16
|
+
.icon-box{width:4rem;height:4rem;border-radius:1rem;background:rgba(220,241,227,.1);display:flex;align-items:center;justify-content:center;margin-bottom:1rem}
|
|
17
|
+
.icon-box svg{width:2rem;height:2rem}
|
|
18
|
+
h1{font-size:1.5rem;font-weight:600;margin-bottom:.5rem;text-align:center}
|
|
19
|
+
p{color:#999;font-size:.9rem;text-align:center;max-width:24rem;line-height:1.5}
|
|
20
|
+
`;
|
|
21
|
+
const CHECK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#085C34"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>`;
|
|
22
|
+
const ERROR_ICON = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#dc2626"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"/></svg>`;
|
|
23
|
+
const SUCCESS_HTML = `<!DOCTYPE html>
|
|
24
|
+
<html><head><meta charset="utf-8"><title>MagicPath CLI</title>
|
|
25
|
+
<style>${PAGE_STYLE}</style>
|
|
26
|
+
</head><body><div class="card"><div class="gradient"></div><div class="content">
|
|
27
|
+
<div class="icon-box">${CHECK_ICON}</div>
|
|
28
|
+
<h1>Logged in!</h1>
|
|
29
|
+
<p>You can close this tab and return to your terminal.</p>
|
|
30
|
+
</div></div></body></html>`;
|
|
31
|
+
const ERROR_HTML = (msg) => `<!DOCTYPE html>
|
|
32
|
+
<html><head><meta charset="utf-8"><title>MagicPath CLI</title>
|
|
33
|
+
<style>${PAGE_STYLE}</style>
|
|
34
|
+
</head><body><div class="card"><div class="gradient"></div><div class="content">
|
|
35
|
+
<div class="icon-box">${ERROR_ICON}</div>
|
|
36
|
+
<h1>Login failed</h1>
|
|
37
|
+
<p>${msg}</p>
|
|
38
|
+
</div></div></body></html>`;
|
|
8
39
|
/**
|
|
9
|
-
* Run the interactive login flow: open browser,
|
|
10
|
-
* Returns true if login succeeded, false if cancelled.
|
|
40
|
+
* Run the interactive login flow: start localhost server, open browser, receive callback with code.
|
|
41
|
+
* Returns true if login succeeded, false if cancelled/timed out.
|
|
11
42
|
*/
|
|
12
43
|
export async function runLoginFlow() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
let settled = false;
|
|
46
|
+
let timeout;
|
|
47
|
+
const server = http.createServer(async (req, res) => {
|
|
48
|
+
const url = new URL(req.url || '/', `http://localhost`);
|
|
49
|
+
if (url.pathname !== '/callback') {
|
|
50
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
51
|
+
res.end('Not found');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const code = url.searchParams.get('code');
|
|
55
|
+
if (!code) {
|
|
56
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
57
|
+
res.end(ERROR_HTML('No authorization code received.'));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const response = await axios.post(makeAuthUrl('extension/tokens'), {
|
|
62
|
+
token: code,
|
|
63
|
+
});
|
|
64
|
+
const { access_token, refresh_token } = response.data;
|
|
65
|
+
saveTokens(access_token, refresh_token);
|
|
66
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
67
|
+
res.end(SUCCESS_HTML);
|
|
68
|
+
cleanup();
|
|
69
|
+
spinner.succeed('Logged in successfully!');
|
|
70
|
+
settled = true;
|
|
71
|
+
resolve(true);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const msg = axios.isAxiosError(error) && error.response?.status === 400
|
|
75
|
+
? 'Invalid or expired authorization code. Please try again.'
|
|
76
|
+
: 'Failed to exchange code. Please try again.';
|
|
77
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
78
|
+
res.end(ERROR_HTML(msg));
|
|
79
|
+
cleanup();
|
|
80
|
+
spinner.fail('Login failed');
|
|
81
|
+
settled = true;
|
|
82
|
+
reject(new MagicPathError(msg));
|
|
83
|
+
}
|
|
35
84
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
spinner.fail('Login failed');
|
|
43
|
-
if (axios.isAxiosError(error) && error.response?.status === 400) {
|
|
44
|
-
throw new MagicPathError('Invalid or expired authorization code. Please try again.');
|
|
85
|
+
function cleanup() {
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
server.close();
|
|
45
88
|
}
|
|
46
|
-
|
|
47
|
-
|
|
89
|
+
server.listen(0, '127.0.0.1', () => {
|
|
90
|
+
const addr = server.address();
|
|
91
|
+
if (!addr || typeof addr === 'string') {
|
|
92
|
+
settled = true;
|
|
93
|
+
reject(new MagicPathError('Failed to start local auth server.'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const port = addr.port;
|
|
97
|
+
const authUrl = makeWebUrl(`/auth/cli?port=${port}`);
|
|
98
|
+
console.log(`\nOpening your browser to log in...\n`);
|
|
99
|
+
console.log(`If the browser doesn't open, visit: ${authUrl}\n`);
|
|
100
|
+
const platform = process.platform;
|
|
101
|
+
const openCmd = platform === 'darwin'
|
|
102
|
+
? 'open'
|
|
103
|
+
: platform === 'win32'
|
|
104
|
+
? 'start'
|
|
105
|
+
: 'xdg-open';
|
|
106
|
+
exec(`${openCmd} "${authUrl}"`);
|
|
107
|
+
});
|
|
108
|
+
const spinner = ora('Waiting for browser login...').start();
|
|
109
|
+
timeout = setTimeout(() => {
|
|
110
|
+
if (!settled) {
|
|
111
|
+
cleanup();
|
|
112
|
+
spinner.fail('Login timed out');
|
|
113
|
+
console.log('\nTip: You can also log in with `magicpath-ai login --code <code>`.');
|
|
114
|
+
settled = true;
|
|
115
|
+
resolve(false);
|
|
116
|
+
}
|
|
117
|
+
}, LOGIN_TIMEOUT_MS);
|
|
118
|
+
});
|
|
48
119
|
}
|
|
49
120
|
export function registerAuthCommands(program) {
|
|
50
121
|
program
|
|
51
122
|
.command('login')
|
|
52
123
|
.description('Log in to your MagicPath account')
|
|
53
|
-
.
|
|
124
|
+
.option('--code <code>', 'Exchange an authorization code non-interactively')
|
|
125
|
+
.action(async (options) => {
|
|
54
126
|
try {
|
|
127
|
+
if (options.code) {
|
|
128
|
+
// Non-interactive: exchange auth code directly
|
|
129
|
+
const response = await axios.post(makeAuthUrl('extension/tokens'), {
|
|
130
|
+
token: options.code,
|
|
131
|
+
});
|
|
132
|
+
const { access_token, refresh_token } = response.data;
|
|
133
|
+
saveTokens(access_token, refresh_token);
|
|
134
|
+
if (isJsonMode()) {
|
|
135
|
+
jsonResult({ authenticated: true, method: 'code' });
|
|
136
|
+
}
|
|
137
|
+
console.log('Logged in successfully!');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (isJsonMode()) {
|
|
141
|
+
// In JSON mode, check if already authenticated via env var or stored tokens
|
|
142
|
+
if (process.env.MAGICPATH_TOKEN) {
|
|
143
|
+
jsonResult({ authenticated: true, method: 'environment' });
|
|
144
|
+
}
|
|
145
|
+
const tokens = loadTokens();
|
|
146
|
+
if (tokens) {
|
|
147
|
+
jsonResult({ authenticated: true, method: 'stored' });
|
|
148
|
+
}
|
|
149
|
+
jsonError(new Error('Not authenticated. Set MAGICPATH_TOKEN environment variable or run login interactively.'));
|
|
150
|
+
}
|
|
55
151
|
const loggedIn = await runLoginFlow();
|
|
56
152
|
if (!loggedIn) {
|
|
57
153
|
console.log('Login cancelled.');
|
|
58
154
|
}
|
|
59
155
|
}
|
|
60
156
|
catch (err) {
|
|
157
|
+
if (isJsonMode())
|
|
158
|
+
jsonError(err);
|
|
61
159
|
if (err instanceof MagicPathError) {
|
|
62
160
|
console.error(`\n${err.message}`);
|
|
63
161
|
process.exit(1);
|
|
@@ -70,6 +168,9 @@ export function registerAuthCommands(program) {
|
|
|
70
168
|
.description('Log out of your MagicPath account')
|
|
71
169
|
.action(() => {
|
|
72
170
|
clearTokens();
|
|
171
|
+
if (isJsonMode()) {
|
|
172
|
+
jsonResult({ loggedOut: true });
|
|
173
|
+
}
|
|
73
174
|
console.log('Logged out successfully.');
|
|
74
175
|
});
|
|
75
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/clone.js
CHANGED
|
@@ -6,6 +6,7 @@ import os from 'os';
|
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import { enableDebugLogger, logger } from '../util/logger.js';
|
|
8
8
|
import { MagicPathError } from '../util/error.js';
|
|
9
|
+
import { isJsonMode, jsonResult, jsonError } from '../util/output.js';
|
|
9
10
|
import { downloadProject, releaseProject, unpackProject, } from '../util/project.js';
|
|
10
11
|
import { installDependencies } from '../util/dependencies.js';
|
|
11
12
|
import { openInIDE, openInFileManager } from '../util/ide.js';
|
|
@@ -13,6 +14,8 @@ const cloneOptionsSchema = z.object({
|
|
|
13
14
|
key: z.string(),
|
|
14
15
|
debug: z.boolean().default(false),
|
|
15
16
|
ide: z.enum(['cursor', 'antigravity', 'vscode', 'webstorm']).optional(),
|
|
17
|
+
dir: z.string().optional(),
|
|
18
|
+
name: z.string().optional(),
|
|
16
19
|
});
|
|
17
20
|
export function registerCloneCommand(program) {
|
|
18
21
|
program
|
|
@@ -21,6 +24,8 @@ export function registerCloneCommand(program) {
|
|
|
21
24
|
.requiredOption('-k, --key <accessKey>', '🔑 One-time magic access key to unlock and download your project')
|
|
22
25
|
.option('-d, --debug', 'Get verbose debug logs in the CLI')
|
|
23
26
|
.option('-i, --ide <ide>', 'Pre-select IDE to open project in (cursor, antigravity, vscode, webstorm)')
|
|
27
|
+
.option('--dir <directory>', 'Target directory for non-interactive use')
|
|
28
|
+
.option('--name <projectName>', 'Project name for non-interactive use')
|
|
24
29
|
.action(async (options) => {
|
|
25
30
|
let cloneOptions;
|
|
26
31
|
try {
|
|
@@ -31,103 +36,119 @@ export function registerCloneCommand(program) {
|
|
|
31
36
|
}
|
|
32
37
|
if (cloneOptions.debug)
|
|
33
38
|
enableDebugLogger();
|
|
39
|
+
const json = isJsonMode();
|
|
40
|
+
// In JSON mode, require --dir and --name
|
|
41
|
+
if (json && (!cloneOptions.dir || !cloneOptions.name)) {
|
|
42
|
+
jsonError(new Error('In JSON mode, --dir and --name are required for clone.'));
|
|
43
|
+
}
|
|
34
44
|
logger.debug({ options });
|
|
35
45
|
logger.debug({ options: cloneOptions });
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
let finalTargetDir;
|
|
47
|
+
let projectName;
|
|
48
|
+
if (cloneOptions.dir && cloneOptions.name) {
|
|
49
|
+
// Non-interactive mode
|
|
50
|
+
finalTargetDir = path.resolve(cloneOptions.dir);
|
|
51
|
+
projectName = cloneOptions.name;
|
|
52
|
+
await fs.ensureDir(finalTargetDir);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Step 1: Ask the user where to drop their fresh code
|
|
56
|
+
const homeDir = os.homedir();
|
|
57
|
+
const commonDirs = [
|
|
58
|
+
{ name: 'Documents', path: path.join(homeDir, 'Documents') },
|
|
59
|
+
{ name: 'Desktop', path: path.join(homeDir, 'Desktop') },
|
|
60
|
+
{ name: 'Downloads', path: path.join(homeDir, 'Downloads') },
|
|
61
|
+
];
|
|
62
|
+
// Filter to only include directories that actually exist
|
|
63
|
+
const existingDirs = await Promise.all(commonDirs.map(async (dir) => {
|
|
64
|
+
try {
|
|
65
|
+
const exists = await fs.pathExists(dir.path);
|
|
66
|
+
return exists ? dir : null;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}));
|
|
72
|
+
const validDirs = existingDirs.filter((dir) => dir !== null);
|
|
73
|
+
// Build choices array starting with current directory and home directory
|
|
74
|
+
const choices = [
|
|
75
|
+
{
|
|
76
|
+
title: `Right here (current folder: ${process.cwd()})`,
|
|
77
|
+
value: process.cwd(),
|
|
78
|
+
},
|
|
79
|
+
{ title: `Home directory (${homeDir})`, value: homeDir },
|
|
80
|
+
];
|
|
81
|
+
// Add existing standard directories
|
|
82
|
+
validDirs.forEach((dir) => {
|
|
83
|
+
choices.push({ title: dir.name, value: dir.path });
|
|
84
|
+
});
|
|
85
|
+
// Add option for custom directory
|
|
86
|
+
choices.push({ title: 'Other (specify custom path)', value: 'custom' });
|
|
87
|
+
const { targetDir } = await prompts({
|
|
88
|
+
type: 'select',
|
|
89
|
+
name: 'targetDir',
|
|
90
|
+
message: 'Where should we put your code?',
|
|
91
|
+
choices,
|
|
92
|
+
initial: 0,
|
|
93
|
+
});
|
|
94
|
+
finalTargetDir = targetDir;
|
|
95
|
+
// Handle custom directory selection
|
|
96
|
+
if (targetDir === 'custom') {
|
|
97
|
+
const { customPath } = await prompts({
|
|
98
|
+
type: 'text',
|
|
99
|
+
name: 'customPath',
|
|
100
|
+
message: 'Enter the full path where you want to create your project:',
|
|
101
|
+
initial: homeDir,
|
|
102
|
+
validate: (value) => {
|
|
103
|
+
if (!value)
|
|
104
|
+
return 'Please enter a path';
|
|
105
|
+
try {
|
|
106
|
+
path.resolve(value);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return 'Please enter a valid path';
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
if (!customPath) {
|
|
115
|
+
throw new MagicPathError('Project creation cancelled');
|
|
116
|
+
}
|
|
117
|
+
finalTargetDir = path.resolve(customPath);
|
|
118
|
+
try {
|
|
119
|
+
await fs.ensureDir(finalTargetDir);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
throw new MagicPathError(`Failed to create or access directory: ${finalTargetDir}`);
|
|
123
|
+
}
|
|
48
124
|
}
|
|
49
|
-
|
|
50
|
-
|
|
125
|
+
if (!finalTargetDir) {
|
|
126
|
+
throw new MagicPathError('Download cancelled');
|
|
51
127
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Build choices array starting with current directory and home directory
|
|
55
|
-
const choices = [
|
|
56
|
-
{
|
|
57
|
-
title: `Right here (current folder: ${process.cwd()})`,
|
|
58
|
-
value: process.cwd(),
|
|
59
|
-
},
|
|
60
|
-
{ title: `Home directory (${homeDir})`, value: homeDir },
|
|
61
|
-
];
|
|
62
|
-
// Add existing standard directories
|
|
63
|
-
validDirs.forEach((dir) => {
|
|
64
|
-
choices.push({ title: dir.name, value: dir.path });
|
|
65
|
-
});
|
|
66
|
-
// Add option for custom directory
|
|
67
|
-
choices.push({ title: 'Other (specify custom path)', value: 'custom' });
|
|
68
|
-
const { targetDir } = await prompts({
|
|
69
|
-
type: 'select',
|
|
70
|
-
name: 'targetDir',
|
|
71
|
-
message: 'Where should we put your code?',
|
|
72
|
-
choices,
|
|
73
|
-
initial: 0,
|
|
74
|
-
});
|
|
75
|
-
let finalTargetDir = targetDir;
|
|
76
|
-
// Handle custom directory selection
|
|
77
|
-
if (targetDir === 'custom') {
|
|
78
|
-
const { customPath } = await prompts({
|
|
128
|
+
// Step 2: Ask for project name
|
|
129
|
+
const nameResult = await prompts({
|
|
79
130
|
type: 'text',
|
|
80
|
-
name: '
|
|
81
|
-
message: '
|
|
82
|
-
initial:
|
|
83
|
-
validate: (value) => {
|
|
84
|
-
if (!value)
|
|
85
|
-
return 'Please enter a path';
|
|
86
|
-
try {
|
|
87
|
-
// Try to resolve the path to check if it's valid
|
|
88
|
-
const resolvedPath = path.resolve(value);
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return 'Please enter a valid path';
|
|
93
|
-
}
|
|
94
|
-
},
|
|
131
|
+
name: 'projectName',
|
|
132
|
+
message: 'What would you like to name your project?',
|
|
133
|
+
initial: 'magicpath-project',
|
|
95
134
|
});
|
|
96
|
-
|
|
135
|
+
projectName = nameResult.projectName;
|
|
136
|
+
if (!projectName) {
|
|
97
137
|
throw new MagicPathError('Project creation cancelled');
|
|
98
138
|
}
|
|
99
|
-
finalTargetDir = path.resolve(customPath);
|
|
100
|
-
// Ensure the custom directory exists, create if it doesn't
|
|
101
|
-
try {
|
|
102
|
-
await fs.ensureDir(finalTargetDir);
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
throw new MagicPathError(`Failed to create or access directory: ${finalTargetDir}`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (!finalTargetDir) {
|
|
109
|
-
throw new MagicPathError('Download cancelled');
|
|
110
|
-
}
|
|
111
|
-
// Step 2: Ask for project name
|
|
112
|
-
const { projectName } = await prompts({
|
|
113
|
-
type: 'text',
|
|
114
|
-
name: 'projectName',
|
|
115
|
-
message: 'What would you like to name your project?',
|
|
116
|
-
initial: 'magicpath-project',
|
|
117
|
-
});
|
|
118
|
-
if (!projectName) {
|
|
119
|
-
throw new MagicPathError('Project creation cancelled');
|
|
120
139
|
}
|
|
121
140
|
let filename;
|
|
122
141
|
// Step 3: Download project
|
|
123
|
-
const downloadSpinner =
|
|
142
|
+
const downloadSpinner = json
|
|
143
|
+
? null
|
|
144
|
+
: ora('📥 Downloading project...').start();
|
|
124
145
|
try {
|
|
125
146
|
filename = await downloadProject(cloneOptions.key);
|
|
126
147
|
logger.debug({ filename });
|
|
127
|
-
downloadSpinner
|
|
148
|
+
downloadSpinner?.succeed('Project downloaded');
|
|
128
149
|
}
|
|
129
150
|
catch (err) {
|
|
130
|
-
downloadSpinner
|
|
151
|
+
downloadSpinner?.fail('Download failed');
|
|
131
152
|
if (err instanceof MagicPathError) {
|
|
132
153
|
throw err;
|
|
133
154
|
}
|
|
@@ -135,15 +156,17 @@ export function registerCloneCommand(program) {
|
|
|
135
156
|
throw new MagicPathError('Something went wrong!');
|
|
136
157
|
}
|
|
137
158
|
}
|
|
138
|
-
// Step
|
|
139
|
-
const unpackSpinner =
|
|
159
|
+
// Step 4: Unpack project
|
|
160
|
+
const unpackSpinner = json
|
|
161
|
+
? null
|
|
162
|
+
: ora('📦 Unpacking project...').start();
|
|
140
163
|
let projectDir;
|
|
141
164
|
try {
|
|
142
165
|
projectDir = unpackProject(filename, projectName, finalTargetDir);
|
|
143
|
-
unpackSpinner
|
|
166
|
+
unpackSpinner?.succeed(`Project unpacked to ${projectName}`);
|
|
144
167
|
}
|
|
145
168
|
catch (err) {
|
|
146
|
-
unpackSpinner
|
|
169
|
+
unpackSpinner?.fail('Failed to unpack project');
|
|
147
170
|
releaseProject(filename);
|
|
148
171
|
if (err instanceof MagicPathError) {
|
|
149
172
|
throw err;
|
|
@@ -164,6 +187,10 @@ export function registerCloneCommand(program) {
|
|
|
164
187
|
throw new MagicPathError('Something went wrong!');
|
|
165
188
|
}
|
|
166
189
|
}
|
|
190
|
+
// JSON mode: return result
|
|
191
|
+
if (json) {
|
|
192
|
+
jsonResult({ projectDir });
|
|
193
|
+
}
|
|
167
194
|
// Step 6: Ask which IDE to open the project in (or use pre-selected one)
|
|
168
195
|
const ideChoices = [
|
|
169
196
|
{ title: 'Cursor', value: 'cursor' },
|
|
@@ -200,7 +227,6 @@ export function registerCloneCommand(program) {
|
|
|
200
227
|
}
|
|
201
228
|
catch (err) {
|
|
202
229
|
logger.debug({ err });
|
|
203
|
-
// Don't throw error if opening fails, just continue
|
|
204
230
|
if (err instanceof MagicPathError) {
|
|
205
231
|
console.log(err.message);
|
|
206
232
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAU,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACjC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"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"}
|