magicpath-ai 1.2.0 ā 1.3.0-beta.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/dist/cli.js +8 -212
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +237 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.js +76 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/clone.d.ts +2 -0
- package/dist/commands/clone.js +215 -0
- package/dist/commands/clone.js.map +1 -0
- package/dist/commands/integrate.d.ts +2 -0
- package/dist/commands/integrate.js +269 -0
- package/dist/commands/integrate.js.map +1 -0
- package/dist/util/api.d.ts +5 -1
- package/dist/util/api.js +16 -3
- package/dist/util/api.js.map +1 -1
- package/dist/util/auth.d.ts +11 -0
- package/dist/util/auth.js +38 -0
- package/dist/util/auth.js.map +1 -0
- package/dist/util/authError.d.ts +4 -0
- package/dist/util/authError.js +7 -0
- package/dist/util/authError.js.map +1 -0
- package/dist/util/component.d.ts +186 -0
- package/dist/util/component.js +343 -0
- package/dist/util/component.js.map +1 -0
- package/dist/util/dependencies.d.ts +11 -0
- package/dist/util/dependencies.js +71 -6
- package/dist/util/dependencies.js.map +1 -1
- package/dist/util/diff.d.ts +9 -0
- package/dist/util/diff.js +55 -0
- package/dist/util/diff.js.map +1 -0
- package/dist/util/error.d.ts +0 -1
- package/dist/util/error.js +0 -1
- package/dist/util/error.js.map +1 -1
- package/dist/util/ide.js +1 -1
- package/dist/util/integrate.d.ts +73 -0
- package/dist/util/integrate.js +660 -0
- package/dist/util/integrate.js.map +1 -0
- package/dist/util/ui.d.ts +11 -0
- package/dist/util/ui.js +30 -0
- package/dist/util/ui.js.map +1 -0
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -1,217 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import prompts from 'prompts';
|
|
3
2
|
import { program } from 'commander';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { downloadProject, releaseProject, unpackProject, } from './util/project.js';
|
|
9
|
-
import { installDependencies } from './util/dependencies.js';
|
|
10
|
-
import { openInIDE, openInFileManager } from './util/ide.js';
|
|
11
|
-
import path from 'path';
|
|
12
|
-
import os from 'os';
|
|
13
|
-
import fs from 'fs-extra';
|
|
3
|
+
import { registerCloneCommand } from './commands/clone.js';
|
|
4
|
+
import { registerAddCommand } from './commands/add.js';
|
|
5
|
+
import { registerIntegrateCommand } from './commands/integrate.js';
|
|
6
|
+
import { registerAuthCommands } from './commands/auth.js';
|
|
14
7
|
program.name('magicpath').description('CLI for MagicPath AI').version('1.2.0');
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
-
program
|
|
21
|
-
.command('clone')
|
|
22
|
-
.description('⨠Instantly bring your MagicPath project to your local playground. Edit, remix, and create in your own vibe.')
|
|
23
|
-
.requiredOption('-k, --key <accessKey>', 'š One-time magic access key to unlock and download your project')
|
|
24
|
-
.option('-d, --debug', 'Get verbose debug logs in the CLI')
|
|
25
|
-
.option('-i, --ide <ide>', 'Pre-select IDE to open project in (cursor, antigravity, vscode, webstorm)')
|
|
26
|
-
.action(async (options) => {
|
|
27
|
-
let cloneOptions;
|
|
28
|
-
try {
|
|
29
|
-
cloneOptions = cloneOptionsSchema.parse(options);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
throw new Error('Invalid CLI options for clone command.');
|
|
33
|
-
}
|
|
34
|
-
if (cloneOptions.debug)
|
|
35
|
-
enableDebugLogger();
|
|
36
|
-
logger.debug({ options });
|
|
37
|
-
logger.debug({ options: cloneOptions });
|
|
38
|
-
// Step 1: Ask the user where to drop their fresh code
|
|
39
|
-
const homeDir = os.homedir();
|
|
40
|
-
const commonDirs = [
|
|
41
|
-
{ name: 'Documents', path: path.join(homeDir, 'Documents') },
|
|
42
|
-
{ name: 'Desktop', path: path.join(homeDir, 'Desktop') },
|
|
43
|
-
{ name: 'Downloads', path: path.join(homeDir, 'Downloads') },
|
|
44
|
-
];
|
|
45
|
-
// Filter to only include directories that actually exist
|
|
46
|
-
const existingDirs = await Promise.all(commonDirs.map(async (dir) => {
|
|
47
|
-
try {
|
|
48
|
-
const exists = await fs.pathExists(dir.path);
|
|
49
|
-
return exists ? dir : null;
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}));
|
|
55
|
-
const validDirs = existingDirs.filter((dir) => dir !== null);
|
|
56
|
-
// Build choices array starting with current directory and home directory
|
|
57
|
-
const choices = [
|
|
58
|
-
{
|
|
59
|
-
title: `Right here (current folder: ${process.cwd()})`,
|
|
60
|
-
value: process.cwd(),
|
|
61
|
-
},
|
|
62
|
-
{ title: `Home directory (${homeDir})`, value: homeDir },
|
|
63
|
-
];
|
|
64
|
-
// Add existing standard directories
|
|
65
|
-
validDirs.forEach((dir) => {
|
|
66
|
-
choices.push({ title: dir.name, value: dir.path });
|
|
67
|
-
});
|
|
68
|
-
// Add option for custom directory
|
|
69
|
-
choices.push({ title: 'Other (specify custom path)', value: 'custom' });
|
|
70
|
-
const { targetDir } = await prompts({
|
|
71
|
-
type: 'select',
|
|
72
|
-
name: 'targetDir',
|
|
73
|
-
message: 'Where should we put your code?',
|
|
74
|
-
choices,
|
|
75
|
-
initial: 0,
|
|
76
|
-
});
|
|
77
|
-
let finalTargetDir = targetDir;
|
|
78
|
-
// Handle custom directory selection
|
|
79
|
-
if (targetDir === 'custom') {
|
|
80
|
-
const { customPath } = await prompts({
|
|
81
|
-
type: 'text',
|
|
82
|
-
name: 'customPath',
|
|
83
|
-
message: 'Enter the full path where you want to create your project:',
|
|
84
|
-
initial: homeDir,
|
|
85
|
-
validate: (value) => {
|
|
86
|
-
if (!value)
|
|
87
|
-
return 'Please enter a path';
|
|
88
|
-
try {
|
|
89
|
-
// Try to resolve the path to check if it's valid
|
|
90
|
-
const resolvedPath = path.resolve(value);
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return 'Please enter a valid path';
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
if (!customPath) {
|
|
99
|
-
throw new MagicPathError('Project creation cancelled');
|
|
100
|
-
}
|
|
101
|
-
finalTargetDir = path.resolve(customPath);
|
|
102
|
-
// Ensure the custom directory exists, create if it doesn't
|
|
103
|
-
try {
|
|
104
|
-
await fs.ensureDir(finalTargetDir);
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
throw new MagicPathError(`Failed to create or access directory: ${finalTargetDir}`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (!finalTargetDir) {
|
|
111
|
-
throw new MagicPathError('Download cancelled');
|
|
112
|
-
}
|
|
113
|
-
// Step 2: Ask for project name
|
|
114
|
-
const { projectName } = await prompts({
|
|
115
|
-
type: 'text',
|
|
116
|
-
name: 'projectName',
|
|
117
|
-
message: 'What would you like to name your project?',
|
|
118
|
-
initial: 'magicpath-project',
|
|
119
|
-
});
|
|
120
|
-
if (!projectName) {
|
|
121
|
-
throw new MagicPathError('Project creation cancelled');
|
|
122
|
-
}
|
|
123
|
-
let filename;
|
|
124
|
-
// Step 3: Download project
|
|
125
|
-
const downloadSpinner = ora('š„ Downloading project...').start();
|
|
126
|
-
try {
|
|
127
|
-
filename = await downloadProject(cloneOptions.key);
|
|
128
|
-
logger.debug({ filename });
|
|
129
|
-
downloadSpinner.succeed('Project downloaded');
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
downloadSpinner.fail('Download failed');
|
|
133
|
-
if (err instanceof MagicPathError) {
|
|
134
|
-
throw err;
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
throw GenericError;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Step 3: Unpack project
|
|
141
|
-
const unpackSpinner = ora('š¦ Unpacking project...').start();
|
|
142
|
-
let projectDir;
|
|
143
|
-
try {
|
|
144
|
-
projectDir = unpackProject(filename, projectName, finalTargetDir);
|
|
145
|
-
unpackSpinner.succeed(`Project unpacked to ${projectName}`);
|
|
146
|
-
}
|
|
147
|
-
catch (err) {
|
|
148
|
-
unpackSpinner.fail('Failed to unpack project');
|
|
149
|
-
releaseProject(filename);
|
|
150
|
-
if (err instanceof MagicPathError) {
|
|
151
|
-
throw err;
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
throw GenericError;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// Step 5: Install dependencies
|
|
158
|
-
try {
|
|
159
|
-
installDependencies(projectDir);
|
|
160
|
-
}
|
|
161
|
-
catch (err) {
|
|
162
|
-
if (err instanceof MagicPathError) {
|
|
163
|
-
throw err;
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
throw GenericError;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
// Step 6: Ask which IDE to open the project in (or use pre-selected one)
|
|
170
|
-
const ideChoices = [
|
|
171
|
-
{ title: 'Cursor', value: 'cursor' },
|
|
172
|
-
{ title: 'Antigravity', value: 'antigravity' },
|
|
173
|
-
{ title: 'VS Code', value: 'vscode' },
|
|
174
|
-
{ title: 'WebStorm', value: 'webstorm' },
|
|
175
|
-
{ title: 'Open in file manager', value: 'filemanager' },
|
|
176
|
-
{ title: 'None (just finish)', value: 'none' },
|
|
177
|
-
];
|
|
178
|
-
// Determine initial selection based on --ide flag
|
|
179
|
-
let initialSelection = 0;
|
|
180
|
-
if (cloneOptions.ide) {
|
|
181
|
-
const preselectedIndex = ideChoices.findIndex((choice) => choice.value === cloneOptions.ide);
|
|
182
|
-
if (preselectedIndex !== -1) {
|
|
183
|
-
initialSelection = preselectedIndex;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const ideResponse = await prompts({
|
|
187
|
-
type: 'select',
|
|
188
|
-
name: 'ide',
|
|
189
|
-
message: 'Which IDE would you like to open the project in?',
|
|
190
|
-
choices: ideChoices,
|
|
191
|
-
initial: initialSelection,
|
|
192
|
-
});
|
|
193
|
-
// Step 7: Open in IDE or file manager if selected
|
|
194
|
-
if (ideResponse.ide && ideResponse.ide !== 'none') {
|
|
195
|
-
try {
|
|
196
|
-
if (ideResponse.ide === 'filemanager') {
|
|
197
|
-
openInFileManager(projectDir);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
openInIDE(projectDir, ideResponse.ide);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
catch (err) {
|
|
204
|
-
logger.debug({ err });
|
|
205
|
-
// Don't throw error if opening fails, just continue
|
|
206
|
-
if (err instanceof MagicPathError) {
|
|
207
|
-
console.log(err.message);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
console.log('ā ļø Opening failed, but your project is ready!');
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
console.log(`\nš Done! Your project is ready to go at: ${projectDir}`);
|
|
215
|
-
});
|
|
8
|
+
registerCloneCommand(program);
|
|
9
|
+
registerAddCommand(program);
|
|
10
|
+
registerIntegrateCommand(program);
|
|
11
|
+
registerAuthCommands(program);
|
|
216
12
|
program.parse();
|
|
217
13
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/E,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAE9B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import { enableDebugLogger, logger } from '../util/logger.js';
|
|
6
|
+
import { MagicPathError } from '../util/error.js';
|
|
7
|
+
import { AuthRequiredError } from '../util/authError.js';
|
|
8
|
+
import { brandSpinner } from '../util/ui.js';
|
|
9
|
+
import { fetchComponent, checkExistingFiles, writeComponentFiles, checkUtilsExists, writeUtilsFile, resolveComponentsPath, resolveUtilsPath, sanitizeComponentFolderName, extractComponentExports, generateImportStatement, generateUsageExample, writeUsageFile, DEFAULT_COMPONENTS_PATH, } from '../util/component.js';
|
|
10
|
+
import { installPackages } from '../util/dependencies.js';
|
|
11
|
+
import { runLoginFlow } from './auth.js';
|
|
12
|
+
const addOptionsSchema = z.object({
|
|
13
|
+
yes: z.boolean().default(false),
|
|
14
|
+
overwrite: z.boolean().default(false),
|
|
15
|
+
path: z.string().optional(),
|
|
16
|
+
debug: z.boolean().default(false),
|
|
17
|
+
});
|
|
18
|
+
export function registerAddCommand(program) {
|
|
19
|
+
program
|
|
20
|
+
.command('add')
|
|
21
|
+
.description('Add a MagicPath component to your project')
|
|
22
|
+
.argument('<generatedName>', 'The generated name of the component (e.g., wispy-river-5234)')
|
|
23
|
+
.option('-y, --yes', 'Skip confirmation prompts', false)
|
|
24
|
+
.option('-o, --overwrite', 'Overwrite existing files', false)
|
|
25
|
+
.option('-p, --path <path>', `Custom path for components (default: ${DEFAULT_COMPONENTS_PATH})`)
|
|
26
|
+
.option('-d, --debug', 'Enable debug logging', false)
|
|
27
|
+
.action(async (generatedName, options) => {
|
|
28
|
+
try {
|
|
29
|
+
let addOptions;
|
|
30
|
+
try {
|
|
31
|
+
addOptions = addOptionsSchema.parse(options);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error('Invalid CLI options for add command.');
|
|
35
|
+
}
|
|
36
|
+
if (addOptions.debug)
|
|
37
|
+
enableDebugLogger();
|
|
38
|
+
logger.debug({ generatedName, options: addOptions });
|
|
39
|
+
const cwd = process.cwd();
|
|
40
|
+
// Check if we're in a valid project directory
|
|
41
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
42
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
43
|
+
throw new MagicPathError('No package.json found. Please run this command from the root of your project.');
|
|
44
|
+
}
|
|
45
|
+
// Step 1: Fetch component from registry
|
|
46
|
+
const fetchSpinner = brandSpinner(`Fetching component "${generatedName}"...`).start();
|
|
47
|
+
let componentData;
|
|
48
|
+
try {
|
|
49
|
+
componentData = await fetchComponent(generatedName);
|
|
50
|
+
fetchSpinner.succeed(`Found component: ${componentData.name}`);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof AuthRequiredError) {
|
|
54
|
+
fetchSpinner.fail('Not logged in');
|
|
55
|
+
const { shouldLogin } = await prompts({
|
|
56
|
+
type: 'confirm',
|
|
57
|
+
name: 'shouldLogin',
|
|
58
|
+
message: 'You need to be logged in to install components. Log in now?',
|
|
59
|
+
initial: true,
|
|
60
|
+
});
|
|
61
|
+
if (!shouldLogin) {
|
|
62
|
+
console.log('Installation cancelled.');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const loggedIn = await runLoginFlow();
|
|
66
|
+
if (!loggedIn) {
|
|
67
|
+
console.log('Installation cancelled.');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Retry fetch after login
|
|
71
|
+
const retrySpinner = brandSpinner(`Fetching component "${generatedName}"...`).start();
|
|
72
|
+
try {
|
|
73
|
+
componentData = await fetchComponent(generatedName);
|
|
74
|
+
retrySpinner.succeed(`Found component: ${componentData.name}`);
|
|
75
|
+
}
|
|
76
|
+
catch (retryErr) {
|
|
77
|
+
retrySpinner.fail('Failed to fetch component');
|
|
78
|
+
if (retryErr instanceof MagicPathError) {
|
|
79
|
+
throw retryErr;
|
|
80
|
+
}
|
|
81
|
+
throw new MagicPathError('Something went wrong!');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
fetchSpinner.fail('Failed to fetch component');
|
|
86
|
+
if (err instanceof MagicPathError) {
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
throw new MagicPathError('Something went wrong!');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Resolve paths - include component-specific subfolder
|
|
93
|
+
const basePath = resolveComponentsPath(addOptions.path, cwd);
|
|
94
|
+
const componentFolderName = sanitizeComponentFolderName(componentData.name);
|
|
95
|
+
const componentsPath = path.join(basePath, componentFolderName);
|
|
96
|
+
const utilsPath = resolveUtilsPath(cwd);
|
|
97
|
+
logger.debug({
|
|
98
|
+
basePath,
|
|
99
|
+
componentFolderName,
|
|
100
|
+
componentsPath,
|
|
101
|
+
utilsPath,
|
|
102
|
+
});
|
|
103
|
+
// Step 2: Check for existing files
|
|
104
|
+
const existingFiles = checkExistingFiles(componentData.files, componentsPath);
|
|
105
|
+
if (existingFiles.length > 0 && !addOptions.overwrite) {
|
|
106
|
+
console.log('\nThe following files already exist:');
|
|
107
|
+
existingFiles.forEach((file) => console.log(` - ${file}`));
|
|
108
|
+
if (!addOptions.yes) {
|
|
109
|
+
const { shouldOverwrite } = await prompts({
|
|
110
|
+
type: 'confirm',
|
|
111
|
+
name: 'shouldOverwrite',
|
|
112
|
+
message: 'Do you want to overwrite these files?',
|
|
113
|
+
initial: false,
|
|
114
|
+
});
|
|
115
|
+
if (!shouldOverwrite) {
|
|
116
|
+
console.log('Installation cancelled.');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.log('Use --overwrite to replace existing files.');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Step 3: Confirm installation (unless --yes flag)
|
|
126
|
+
if (!addOptions.yes && existingFiles.length === 0) {
|
|
127
|
+
console.log(`\nThis will install:`);
|
|
128
|
+
console.log(` Component: ${componentData.name}`);
|
|
129
|
+
console.log(` Files: ${componentData.files.length} file(s) to ${path.relative(cwd, componentsPath) || '.'}`);
|
|
130
|
+
console.log(` Dependencies: ${componentData.dependencies.length} package(s)`);
|
|
131
|
+
const { shouldProceed } = await prompts({
|
|
132
|
+
type: 'confirm',
|
|
133
|
+
name: 'shouldProceed',
|
|
134
|
+
message: 'Proceed with installation?',
|
|
135
|
+
initial: true,
|
|
136
|
+
});
|
|
137
|
+
if (!shouldProceed) {
|
|
138
|
+
console.log('Installation cancelled.');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Step 4: Write component files
|
|
143
|
+
const writeSpinner = brandSpinner('Writing component files...').start();
|
|
144
|
+
try {
|
|
145
|
+
writeComponentFiles(componentData.files, componentsPath, true);
|
|
146
|
+
writeSpinner.succeed(`Wrote ${componentData.files.length} file(s) to ${path.relative(cwd, componentsPath) || '.'}`);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
writeSpinner.fail('Failed to write component files');
|
|
150
|
+
throw new MagicPathError('Failed to write component files. Please check permissions and try again.');
|
|
151
|
+
}
|
|
152
|
+
// Step 5: Install utils if needed
|
|
153
|
+
const utilsExists = checkUtilsExists(utilsPath);
|
|
154
|
+
if (!utilsExists && componentData.utils.content) {
|
|
155
|
+
const utilsSpinner = brandSpinner('Installing utilities...').start();
|
|
156
|
+
try {
|
|
157
|
+
writeUtilsFile(componentData.utils.content, utilsPath);
|
|
158
|
+
utilsSpinner.succeed(`Wrote utils.ts to ${path.relative(cwd, utilsPath) || '.'}`);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
utilsSpinner.fail('Failed to write utils file');
|
|
162
|
+
logger.debug({ err });
|
|
163
|
+
// Non-fatal - continue with installation
|
|
164
|
+
console.log(' Warning: Could not write utils.ts. You may need to create it manually.');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Step 6: Install dependencies
|
|
168
|
+
if (componentData.dependencies.length > 0) {
|
|
169
|
+
try {
|
|
170
|
+
const { installed, skipped } = installPackages(componentData.dependencies, cwd);
|
|
171
|
+
if (skipped.length > 0) {
|
|
172
|
+
logger.debug({
|
|
173
|
+
message: 'Skipped already installed packages',
|
|
174
|
+
skipped,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
if (err instanceof MagicPathError) {
|
|
180
|
+
// Non-fatal - show warning but don't fail
|
|
181
|
+
console.log(`\nā ļø ${err.message}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Step 7: Show success message and write usage file
|
|
186
|
+
console.log(`\nā
Successfully added "${componentData.name}" to your project!`);
|
|
187
|
+
console.log(`\nUsage:`);
|
|
188
|
+
// Show import and usage example
|
|
189
|
+
const mainFile = componentData.files[0];
|
|
190
|
+
if (mainFile) {
|
|
191
|
+
const fileName = mainFile.name.replace(/\.tsx?$/, '');
|
|
192
|
+
const importPath = addOptions.path
|
|
193
|
+
? `@/${addOptions.path}/${componentFolderName}/${fileName}`
|
|
194
|
+
: `@/components/magicpath/${componentFolderName}/${fileName}`;
|
|
195
|
+
// Try to extract actual export info from the component source
|
|
196
|
+
const exportInfo = extractComponentExports(mainFile.content);
|
|
197
|
+
if (exportInfo) {
|
|
198
|
+
// Show accurate import statement based on actual exports
|
|
199
|
+
console.log(` ${generateImportStatement(exportInfo, importPath)}`);
|
|
200
|
+
console.log('');
|
|
201
|
+
console.log(` ${generateUsageExample(exportInfo)}`);
|
|
202
|
+
// Show required props hint if there are any
|
|
203
|
+
if (exportInfo.requiredProps.length > 0) {
|
|
204
|
+
console.log('');
|
|
205
|
+
console.log(` Required props: ${exportInfo.requiredProps.join(', ')}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// Fallback to simple named export assumption
|
|
210
|
+
console.log(` import { ${fileName} } from '${importPath}';`);
|
|
211
|
+
}
|
|
212
|
+
// Write usage.md file to the component folder
|
|
213
|
+
try {
|
|
214
|
+
writeUsageFile(componentsPath, {
|
|
215
|
+
componentName: componentData.name,
|
|
216
|
+
importPath,
|
|
217
|
+
exportInfo,
|
|
218
|
+
fileName,
|
|
219
|
+
});
|
|
220
|
+
console.log(`\nš Usage documentation written to ${path.relative(cwd, path.join(componentsPath, 'usage.md'))}`);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
logger.debug({ err });
|
|
224
|
+
// Non-fatal - just skip writing the usage file
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
if (err instanceof MagicPathError) {
|
|
230
|
+
console.error(`\n${err.message}`);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Run the interactive login flow: open browser, prompt for code, exchange for tokens.
|
|
4
|
+
* Returns true if login succeeded, false if cancelled.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runLoginFlow(): Promise<boolean>;
|
|
7
|
+
export declare function registerAuthCommands(program: Command): void;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { MagicPathError } from '../util/error.js';
|
|
6
|
+
import { makeWebUrl, makeAuthUrl } from '../util/api.js';
|
|
7
|
+
import { saveTokens, clearTokens } from '../util/auth.js';
|
|
8
|
+
/**
|
|
9
|
+
* Run the interactive login flow: open browser, prompt for code, exchange for tokens.
|
|
10
|
+
* Returns true if login succeeded, false if cancelled.
|
|
11
|
+
*/
|
|
12
|
+
export async function runLoginFlow() {
|
|
13
|
+
const authUrl = makeWebUrl('/auth/cli');
|
|
14
|
+
console.log(`\nOpening your browser to log in...\n`);
|
|
15
|
+
console.log(`If the browser doesn't open, visit: ${authUrl}\n`);
|
|
16
|
+
const platform = process.platform;
|
|
17
|
+
const openCmd = platform === 'darwin'
|
|
18
|
+
? 'open'
|
|
19
|
+
: platform === 'win32'
|
|
20
|
+
? 'start'
|
|
21
|
+
: 'xdg-open';
|
|
22
|
+
exec(`${openCmd} ${authUrl}`);
|
|
23
|
+
const { code } = await prompts({
|
|
24
|
+
type: 'text',
|
|
25
|
+
name: 'code',
|
|
26
|
+
message: 'Paste the authorization code from your browser:',
|
|
27
|
+
});
|
|
28
|
+
if (!code) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const spinner = ora('Logging in...').start();
|
|
32
|
+
try {
|
|
33
|
+
const response = await axios.post(makeAuthUrl('extension/tokens'), {
|
|
34
|
+
token: code,
|
|
35
|
+
});
|
|
36
|
+
const { access_token, refresh_token } = response.data;
|
|
37
|
+
saveTokens(access_token, refresh_token);
|
|
38
|
+
spinner.succeed('Logged in successfully!');
|
|
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.');
|
|
45
|
+
}
|
|
46
|
+
throw new MagicPathError('Failed to log in. Please check your internet connection and try again.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function registerAuthCommands(program) {
|
|
50
|
+
program
|
|
51
|
+
.command('login')
|
|
52
|
+
.description('Log in to your MagicPath account')
|
|
53
|
+
.action(async () => {
|
|
54
|
+
try {
|
|
55
|
+
const loggedIn = await runLoginFlow();
|
|
56
|
+
if (!loggedIn) {
|
|
57
|
+
console.log('Login cancelled.');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof MagicPathError) {
|
|
62
|
+
console.error(`\n${err.message}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
program
|
|
69
|
+
.command('logout')
|
|
70
|
+
.description('Log out of your MagicPath account')
|
|
71
|
+
.action(() => {
|
|
72
|
+
clearTokens();
|
|
73
|
+
console.log('Logged out successfully.');
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|