zerostart-cli 0.0.31 → 0.0.35
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/out/cli.js +138 -611
- package/package.json +1 -1
package/out/cli.js
CHANGED
|
@@ -51,7 +51,7 @@ const VercelManager_1 = require("./managers/VercelManager");
|
|
|
51
51
|
const NetlifyManager_1 = require("./managers/NetlifyManager");
|
|
52
52
|
const child_process_1 = require("child_process");
|
|
53
53
|
const program = new commander_1.Command();
|
|
54
|
-
// Basic ASCII banner
|
|
54
|
+
// Basic ASCII banner
|
|
55
55
|
function showBanner() {
|
|
56
56
|
console.log();
|
|
57
57
|
console.log(chalk_1.default.cyan('------------------------------------------------------------'));
|
|
@@ -59,13 +59,10 @@ function showBanner() {
|
|
|
59
59
|
console.log(chalk_1.default.gray(' Create and deploy projects in seconds '));
|
|
60
60
|
console.log(chalk_1.default.cyan('------------------------------------------------------------'));
|
|
61
61
|
}
|
|
62
|
-
// Show GitHub token help (ASCII only)
|
|
63
|
-
// Open URL in default browser
|
|
64
62
|
function openUrl(url) {
|
|
65
63
|
const start = (process.platform == 'darwin' ? 'open' : process.platform == 'win32' ? 'start' : 'xdg-open');
|
|
66
64
|
(0, child_process_1.exec)(`${start} "${url}"`);
|
|
67
65
|
}
|
|
68
|
-
// Show GitHub token help (ASCII only)
|
|
69
66
|
function showGitHubTokenHelp() {
|
|
70
67
|
const tokenUrl = 'https://github.com/settings/tokens/new?scopes=repo&description=ZeroStart%20CLI%20Token';
|
|
71
68
|
console.log();
|
|
@@ -73,17 +70,99 @@ function showGitHubTokenHelp() {
|
|
|
73
70
|
console.log(chalk_1.default.gray(' +----------------------------------------------------------+'));
|
|
74
71
|
console.log(chalk_1.default.gray(' | ') + chalk_1.default.white('Opening GitHub in your browser... ') + chalk_1.default.gray(' |'));
|
|
75
72
|
console.log(chalk_1.default.gray(' | ') + chalk_1.default.cyan(tokenUrl.substring(0, 50) + '...') + chalk_1.default.gray(' |'));
|
|
76
|
-
console.log(chalk_1.default.gray(' | |'));
|
|
77
|
-
console.log(chalk_1.default.gray(' | ') + chalk_1.default.white('1. Scroll down and click "Generate token" ') + chalk_1.default.gray(' |'));
|
|
78
|
-
console.log(chalk_1.default.gray(' | ') + chalk_1.default.white('2. Copy the token and paste it below ') + chalk_1.default.gray(' |'));
|
|
79
73
|
console.log(chalk_1.default.gray(' +----------------------------------------------------------+'));
|
|
80
74
|
console.log();
|
|
81
75
|
openUrl(tokenUrl);
|
|
82
76
|
}
|
|
77
|
+
async function initializeProject(name, language, type, options) {
|
|
78
|
+
const cwd = process.cwd();
|
|
79
|
+
const projectPath = path.join(cwd, name);
|
|
80
|
+
if (fs.existsSync(projectPath)) {
|
|
81
|
+
console.log(chalk_1.default.red('\n Error: Directory "' + name + '" already exists!'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const config = {
|
|
85
|
+
name,
|
|
86
|
+
language,
|
|
87
|
+
type,
|
|
88
|
+
isTheRepoPublic: options.isPublic,
|
|
89
|
+
description: `A ${type} project in ${language}`,
|
|
90
|
+
path: projectPath
|
|
91
|
+
};
|
|
92
|
+
const spinner = (0, ora_1.default)({ text: 'Initializing...', color: 'cyan' }).start();
|
|
93
|
+
try {
|
|
94
|
+
const templateManager = new TemplateManager_1.TemplateManager();
|
|
95
|
+
const gitManager = new GitManager_1.GitManager();
|
|
96
|
+
const gitHubService = options.githubToken ? new GitHubServiceCLI_1.GitHubServiceCLI(options.githubToken) : null;
|
|
97
|
+
if (!await gitManager.checkGitInstalled()) {
|
|
98
|
+
spinner.fail(chalk_1.default.red('Git is not installed!'));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
spinner.text = chalk_1.default.cyan('Generating project structure...');
|
|
102
|
+
await templateManager.createProjectStructure(config);
|
|
103
|
+
spinner.succeed(chalk_1.default.green('Project structure created'));
|
|
104
|
+
if (type !== types_1.ProjectType.DSAPractice) {
|
|
105
|
+
spinner.start(chalk_1.default.cyan('Initializing Git repository...'));
|
|
106
|
+
await gitManager.init(projectPath);
|
|
107
|
+
await gitManager.commit(projectPath, "Initial commit");
|
|
108
|
+
spinner.succeed(chalk_1.default.green('Git repository initialized'));
|
|
109
|
+
}
|
|
110
|
+
if (options.createRemote) {
|
|
111
|
+
spinner.start(chalk_1.default.cyan('Creating GitHub repository...'));
|
|
112
|
+
let repoUrl;
|
|
113
|
+
if (options.authMethod === 'GitHub CLI') {
|
|
114
|
+
repoUrl = await gitManager.createRepoWithGh(projectPath, name, options.isPublic);
|
|
115
|
+
}
|
|
116
|
+
else if (gitHubService) {
|
|
117
|
+
repoUrl = await gitHubService.createRepo(config);
|
|
118
|
+
}
|
|
119
|
+
if (repoUrl) {
|
|
120
|
+
spinner.succeed(chalk_1.default.green('GitHub repository created'));
|
|
121
|
+
spinner.start(chalk_1.default.cyan('Pushing to GitHub...'));
|
|
122
|
+
if (options.authMethod !== 'GitHub CLI')
|
|
123
|
+
await gitManager.addRemote(projectPath, repoUrl);
|
|
124
|
+
await gitManager.push(projectPath);
|
|
125
|
+
spinner.succeed(chalk_1.default.green('Pushed to GitHub'));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
spinner.warn(chalk_1.default.yellow('GitHub repository creation failed'));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
console.log();
|
|
132
|
+
console.log(chalk_1.default.bold.green(' Success! Your project is ready!'));
|
|
133
|
+
console.log(chalk_1.default.gray(' Location: ') + chalk_1.default.cyan(projectPath));
|
|
134
|
+
console.log();
|
|
135
|
+
const isWeb = [types_1.ProjectLanguage.React, types_1.ProjectLanguage.HTMLCSS].includes(language);
|
|
136
|
+
const isPractice = type === types_1.ProjectType.DSAPractice;
|
|
137
|
+
if (!isWeb || isPractice) {
|
|
138
|
+
const gdbLinks = {
|
|
139
|
+
[types_1.ProjectLanguage.Python]: 'https://www.onlinegdb.com/online_python_compiler',
|
|
140
|
+
[types_1.ProjectLanguage.Java]: 'https://www.onlinegdb.com/online_java_compiler',
|
|
141
|
+
[types_1.ProjectLanguage.CPP]: 'https://www.onlinegdb.com/online_c++_compiler',
|
|
142
|
+
[types_1.ProjectLanguage.NodeJS]: 'https://www.onlinegdb.com/online_node.js_compiler',
|
|
143
|
+
[types_1.ProjectLanguage.React]: 'https://www.onlinegdb.com/'
|
|
144
|
+
};
|
|
145
|
+
const link = gdbLinks[language] || 'https://www.onlinegdb.com/';
|
|
146
|
+
console.log(chalk_1.default.bold.yellow(' Practice Online:'));
|
|
147
|
+
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(link));
|
|
148
|
+
console.log(chalk_1.default.gray(' (Opening in your browser...)'));
|
|
149
|
+
openUrl(link);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(chalk_1.default.bold(' Get started:'));
|
|
153
|
+
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(`cd ${name}`));
|
|
154
|
+
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan('code .') + chalk_1.default.gray(' (or your favorite editor)'));
|
|
155
|
+
console.log();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
spinner.fail(chalk_1.default.red('Error: ' + error.message));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
83
161
|
program
|
|
84
162
|
.name('zerostart')
|
|
85
163
|
.description('Create and deploy a complete project with one command')
|
|
86
|
-
.version('0.0.
|
|
164
|
+
.version('0.0.35');
|
|
165
|
+
// Standalone deployment commands
|
|
87
166
|
program
|
|
88
167
|
.command('deploy-vercel')
|
|
89
168
|
.description('Deploy the current project to Vercel')
|
|
@@ -91,80 +170,11 @@ program
|
|
|
91
170
|
showBanner();
|
|
92
171
|
const vercelManager = new VercelManager_1.VercelManager();
|
|
93
172
|
const cwd = process.cwd();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (!vercelInstalled) {
|
|
97
|
-
const { installVercel } = await inquirer_1.default.prompt([{
|
|
98
|
-
type: 'confirm',
|
|
99
|
-
name: 'installVercel',
|
|
100
|
-
message: 'Vercel CLI not found. Install it globally?',
|
|
101
|
-
default: true
|
|
102
|
-
}]);
|
|
103
|
-
if (installVercel) {
|
|
104
|
-
const iSpinner = (0, ora_1.default)('Installing Vercel CLI...').start();
|
|
105
|
-
if (await vercelManager.installGlobal()) {
|
|
106
|
-
iSpinner.succeed(chalk_1.default.green('Vercel CLI installed!'));
|
|
107
|
-
vercelInstalled = true;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
iSpinner.fail(chalk_1.default.red('Failed to install Vercel CLI.'));
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// 2. Auth & Deploy
|
|
119
|
-
if (vercelInstalled) {
|
|
120
|
-
const vSpinner = (0, ora_1.default)('Checking Vercel authentication...').start();
|
|
121
|
-
const loggedIn = await vercelManager.checkAuth();
|
|
122
|
-
if (!loggedIn) {
|
|
123
|
-
vSpinner.stop();
|
|
124
|
-
console.log(chalk_1.default.yellow('\n Authentication required.'));
|
|
125
|
-
const { doLogin } = await inquirer_1.default.prompt([{
|
|
126
|
-
type: 'confirm',
|
|
127
|
-
name: 'doLogin',
|
|
128
|
-
message: 'Log in to Vercel now?',
|
|
129
|
-
default: true
|
|
130
|
-
}]);
|
|
131
|
-
if (doLogin) {
|
|
132
|
-
const loginSuccess = await vercelManager.login();
|
|
133
|
-
if (!loginSuccess) {
|
|
134
|
-
console.log(chalk_1.default.red('\n Login failed.'));
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
vSpinner.succeed(chalk_1.default.green('Authenticated'));
|
|
144
|
-
}
|
|
145
|
-
// Prompt for project name for Vercel
|
|
146
|
-
const defaultName = path.basename(cwd);
|
|
147
|
-
const { vName } = await inquirer_1.default.prompt([{
|
|
148
|
-
type: 'input',
|
|
149
|
-
name: 'vName',
|
|
150
|
-
message: 'Vercel Project Name:',
|
|
151
|
-
default: defaultName,
|
|
152
|
-
validate: (input) => {
|
|
153
|
-
if (input.trim() === '')
|
|
154
|
-
return 'Name is required';
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
}]);
|
|
158
|
-
const dSpinner = (0, ora_1.default)('Deploying to Vercel...').start();
|
|
173
|
+
if (await vercelManager.checkAuth()) {
|
|
174
|
+
const { vName } = await inquirer_1.default.prompt([{ type: 'input', name: 'vName', message: 'Vercel Project Name:', default: path.basename(cwd) }]);
|
|
159
175
|
const url = await vercelManager.deploy(cwd, vName);
|
|
160
|
-
if (url)
|
|
161
|
-
|
|
162
|
-
console.log(chalk_1.default.gray(' URL: ') + chalk_1.default.cyan(url));
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
dSpinner.fail(chalk_1.default.red('Deployment failed'));
|
|
166
|
-
console.log(chalk_1.default.gray(' Try running ') + chalk_1.default.cyan('vercel deploy') + chalk_1.default.gray(' manually.'));
|
|
167
|
-
}
|
|
176
|
+
if (url)
|
|
177
|
+
console.log(chalk_1.default.green(' ✔ Deployed! URL: ') + chalk_1.default.cyan(url));
|
|
168
178
|
}
|
|
169
179
|
});
|
|
170
180
|
program
|
|
@@ -174,539 +184,56 @@ program
|
|
|
174
184
|
showBanner();
|
|
175
185
|
const netlifyManager = new NetlifyManager_1.NetlifyManager();
|
|
176
186
|
const cwd = process.cwd();
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
name: 'installNetlify',
|
|
183
|
-
message: 'Netlify CLI not found. Install it globally?',
|
|
184
|
-
default: true
|
|
185
|
-
}]);
|
|
186
|
-
if (installNetlify) {
|
|
187
|
-
const iSpinner = (0, ora_1.default)('Installing Netlify CLI...').start();
|
|
188
|
-
if (await netlifyManager.installGlobal()) {
|
|
189
|
-
iSpinner.succeed(chalk_1.default.green('Netlify CLI installed!'));
|
|
190
|
-
netlifyInstalled = true;
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
iSpinner.fail(chalk_1.default.red('Failed to install Netlify CLI.'));
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
// 2. Auth & Deploy
|
|
202
|
-
if (netlifyInstalled) {
|
|
203
|
-
const nSpinner = (0, ora_1.default)('Checking Netlify authentication...').start();
|
|
204
|
-
const loggedIn = await netlifyManager.checkAuth();
|
|
205
|
-
if (!loggedIn) {
|
|
206
|
-
nSpinner.stop();
|
|
207
|
-
console.log(chalk_1.default.yellow('\n Authentication required.'));
|
|
208
|
-
const { doLogin } = await inquirer_1.default.prompt([{
|
|
209
|
-
type: 'confirm',
|
|
210
|
-
name: 'doLogin',
|
|
211
|
-
message: 'Log in to Netlify now?',
|
|
212
|
-
default: true
|
|
213
|
-
}]);
|
|
214
|
-
if (doLogin) {
|
|
215
|
-
const loginSuccess = await netlifyManager.login();
|
|
216
|
-
if (!loginSuccess) {
|
|
217
|
-
console.log(chalk_1.default.red('\n Login failed.'));
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
nSpinner.succeed(chalk_1.default.green('Authenticated'));
|
|
227
|
-
}
|
|
228
|
-
// Enforce name for standalone deploy
|
|
229
|
-
const defaultName = path.basename(cwd);
|
|
230
|
-
let siteName = defaultName;
|
|
231
|
-
let siteCreated = false;
|
|
232
|
-
let activeSiteId = undefined;
|
|
233
|
-
while (!siteCreated) {
|
|
234
|
-
const result = await netlifyManager.createSite(siteName, cwd);
|
|
235
|
-
if (result.success) {
|
|
236
|
-
siteCreated = true;
|
|
237
|
-
activeSiteId = result.siteId;
|
|
238
|
-
}
|
|
239
|
-
else if (result.reason === 'taken') {
|
|
240
|
-
console.log(chalk_1.default.yellow(`\n The site name "${siteName}" is already taken.`));
|
|
241
|
-
const { newName } = await inquirer_1.default.prompt([{
|
|
242
|
-
type: 'input',
|
|
243
|
-
name: 'newName',
|
|
244
|
-
message: 'Enter a unique name for your Netlify site:',
|
|
245
|
-
validate: (input) => {
|
|
246
|
-
if (input.trim() === '')
|
|
247
|
-
return 'Name is required';
|
|
248
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(input))
|
|
249
|
-
return 'Use only letters, numbers, hyphens, and underscores';
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
|
-
}]);
|
|
253
|
-
siteName = newName;
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
console.log(chalk_1.default.red('\n Failed to configure Netlify site.'));
|
|
257
|
-
const { action } = await inquirer_1.default.prompt([{
|
|
258
|
-
type: 'list',
|
|
259
|
-
name: 'action',
|
|
260
|
-
message: 'What would you like to do?',
|
|
261
|
-
choices: ['Try again with a different name', 'Continue deployment anyway', 'Abort']
|
|
262
|
-
}]);
|
|
263
|
-
if (action === 'Abort')
|
|
264
|
-
return;
|
|
265
|
-
if (action === 'Continue deployment anyway')
|
|
266
|
-
break;
|
|
267
|
-
const { retryName } = await inquirer_1.default.prompt([{
|
|
268
|
-
type: 'input',
|
|
269
|
-
name: 'retryName',
|
|
270
|
-
message: 'Enter a unique name:',
|
|
271
|
-
validate: (input) => {
|
|
272
|
-
if (input.trim() === '')
|
|
273
|
-
return 'Name is required';
|
|
274
|
-
return true;
|
|
275
|
-
}
|
|
276
|
-
}]);
|
|
277
|
-
siteName = retryName;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
const dSpinner = (0, ora_1.default)('Deploying to Netlify...').start();
|
|
281
|
-
dSpinner.stop();
|
|
282
|
-
const success = await netlifyManager.deploy(cwd, activeSiteId);
|
|
283
|
-
if (success) {
|
|
284
|
-
console.log();
|
|
187
|
+
if (await netlifyManager.checkAuth()) {
|
|
188
|
+
const { nName } = await inquirer_1.default.prompt([{ type: 'input', name: 'nName', message: 'Netlify Project Name:', default: path.basename(cwd) }]);
|
|
189
|
+
const res = await netlifyManager.createSite(nName, cwd);
|
|
190
|
+
const success = await netlifyManager.deploy(cwd, res.siteId);
|
|
191
|
+
if (success)
|
|
285
192
|
console.log(chalk_1.default.green(' ✔ Deployed to Netlify!'));
|
|
286
|
-
console.log(chalk_1.default.gray(' Run ') + chalk_1.default.cyan('netlify open') + chalk_1.default.gray(' to view your site.'));
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
console.log();
|
|
290
|
-
console.log(chalk_1.default.red(' ✖ Deployment failed'));
|
|
291
|
-
console.log(chalk_1.default.gray(' Try running ') + chalk_1.default.cyan('netlify login') + chalk_1.default.gray(' and ') + chalk_1.default.cyan('netlify deploy') + chalk_1.default.gray(' manually.'));
|
|
292
|
-
}
|
|
293
193
|
}
|
|
294
194
|
});
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
.
|
|
298
|
-
|
|
195
|
+
// Shortcut commands (18 total)
|
|
196
|
+
const shortcuts = [
|
|
197
|
+
{ cmd: 'dsa-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.DSAPractice },
|
|
198
|
+
{ cmd: 'dsa-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.DSAPractice },
|
|
199
|
+
{ cmd: 'dsa-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.DSAPractice },
|
|
200
|
+
{ cmd: 'dsa-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.DSAPractice },
|
|
201
|
+
{ cmd: 'web-react', lang: types_1.ProjectLanguage.React, type: types_1.ProjectType.WebApp },
|
|
202
|
+
{ cmd: 'web-html', lang: types_1.ProjectLanguage.HTMLCSS, type: types_1.ProjectType.WebApp },
|
|
203
|
+
{ cmd: 'web-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.WebApp },
|
|
204
|
+
{ cmd: 'web-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.WebApp },
|
|
205
|
+
{ cmd: 'web-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.WebApp },
|
|
206
|
+
{ cmd: 'web-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.WebApp },
|
|
207
|
+
{ cmd: 'cli-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.CLITool },
|
|
208
|
+
{ cmd: 'cli-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.CLITool },
|
|
209
|
+
{ cmd: 'cli-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.CLITool },
|
|
210
|
+
{ cmd: 'cli-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.CLITool },
|
|
211
|
+
{ cmd: 'ml-py', lang: types_1.ProjectLanguage.Python, type: types_1.ProjectType.MLProject },
|
|
212
|
+
{ cmd: 'ml-node', lang: types_1.ProjectLanguage.NodeJS, type: types_1.ProjectType.MLProject },
|
|
213
|
+
{ cmd: 'ml-java', lang: types_1.ProjectLanguage.Java, type: types_1.ProjectType.MLProject },
|
|
214
|
+
{ cmd: 'ml-cpp', lang: types_1.ProjectLanguage.CPP, type: types_1.ProjectType.MLProject },
|
|
215
|
+
];
|
|
216
|
+
shortcuts.forEach(s => {
|
|
217
|
+
program.command(s.cmd).argument('[name]', 'Project name', `my-${s.cmd}`).action(n => {
|
|
299
218
|
showBanner();
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
type: 'list',
|
|
320
|
-
message: 'Select Programming Language:',
|
|
321
|
-
choices: (ans) => {
|
|
322
|
-
const base = Object.values(types_1.ProjectLanguage);
|
|
323
|
-
return ans.name ? ['<- Back', ...base] : base;
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
id: 'type',
|
|
328
|
-
type: 'list',
|
|
329
|
-
message: 'Select Project Type:',
|
|
330
|
-
choices: ['<- Back', ...Object.values(types_1.ProjectType)]
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
id: 'visibility',
|
|
334
|
-
type: 'list',
|
|
335
|
-
message: 'Select Repository Visibility:',
|
|
336
|
-
choices: ['<- Back', 'Public', 'Private'],
|
|
337
|
-
default: 'Private',
|
|
338
|
-
when: (ans) => ans.type !== types_1.ProjectType.DSAPractice
|
|
339
|
-
},
|
|
340
|
-
{
|
|
341
|
-
id: 'createRemote',
|
|
342
|
-
type: 'list',
|
|
343
|
-
message: 'Push to GitHub?',
|
|
344
|
-
choices: ['<- Back', 'Yes', 'No'],
|
|
345
|
-
default: 'No',
|
|
346
|
-
when: (ans) => ans.type !== types_1.ProjectType.DSAPractice
|
|
347
|
-
}
|
|
348
|
-
];
|
|
349
|
-
const answers = { name: projectName };
|
|
350
|
-
let stepIndex = projectName ? 1 : 0;
|
|
351
|
-
while (stepIndex < wizardSteps.length) {
|
|
352
|
-
const step = wizardSteps[stepIndex];
|
|
353
|
-
// Skip if needed
|
|
354
|
-
if (step.skip) {
|
|
355
|
-
stepIndex++;
|
|
356
|
-
continue;
|
|
357
|
-
}
|
|
358
|
-
// Handle 'when' logic manually
|
|
359
|
-
if (typeof step.when === 'function' && !step.when(answers)) {
|
|
360
|
-
stepIndex++;
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
// Prepare choices (handle dynamic choices)
|
|
364
|
-
const promptConfig = { ...step, name: 'value' };
|
|
365
|
-
if (typeof step.choices === 'function') {
|
|
366
|
-
promptConfig.choices = step.choices(answers);
|
|
367
|
-
}
|
|
368
|
-
const result = await inquirer_1.default.prompt([promptConfig]);
|
|
369
|
-
const value = result.value;
|
|
370
|
-
if (value === '<- Back') {
|
|
371
|
-
// Go back
|
|
372
|
-
stepIndex--;
|
|
373
|
-
// Skip back further if the previous step was skipped or not shown
|
|
374
|
-
while (stepIndex >= 0) {
|
|
375
|
-
const prevStep = wizardSteps[stepIndex];
|
|
376
|
-
const isSkipped = !!prevStep.skip;
|
|
377
|
-
const whenCondition = prevStep.when;
|
|
378
|
-
const isWhenFalse = typeof whenCondition === 'function' && !whenCondition(answers);
|
|
379
|
-
if (isSkipped || isWhenFalse) {
|
|
380
|
-
stepIndex--;
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
if (stepIndex < 0)
|
|
387
|
-
stepIndex = 0;
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
390
|
-
// Save answer and move forward
|
|
391
|
-
answers[step.id] = value;
|
|
392
|
-
stepIndex++;
|
|
393
|
-
}
|
|
394
|
-
// Normalizing answers for later logic
|
|
395
|
-
const normalizedAnswers = {
|
|
396
|
-
...answers,
|
|
397
|
-
createRemote: answers.createRemote === 'Yes',
|
|
398
|
-
visibility: answers.visibility
|
|
399
|
-
};
|
|
400
|
-
let githubToken = null;
|
|
401
|
-
let authMethod = 'Personal Access Token';
|
|
402
|
-
const gitManager = new GitManager_1.GitManager();
|
|
403
|
-
// 3. GitHub Auth Flow (also support Back?)
|
|
404
|
-
if (normalizedAnswers.createRemote) {
|
|
405
|
-
const ghInstalled = await gitManager.checkGhInstalled();
|
|
406
|
-
const ghAuth = await gitManager.checkGhAuth();
|
|
407
|
-
if (ghInstalled && ghAuth) {
|
|
408
|
-
const authAnswer = await inquirer_1.default.prompt([
|
|
409
|
-
{
|
|
410
|
-
type: 'list',
|
|
411
|
-
name: 'method',
|
|
412
|
-
message: 'How would you like to authenticate?',
|
|
413
|
-
choices: ['<- Back', 'GitHub CLI (Recommended)', 'Personal Access Token']
|
|
414
|
-
}
|
|
415
|
-
]);
|
|
416
|
-
if (authAnswer.method === '<- Back') {
|
|
417
|
-
// This is a special case, we'd need to loop the whole thing
|
|
418
|
-
// For now, let's just allow returning to the 'Push to GitHub' question
|
|
419
|
-
stepIndex--;
|
|
420
|
-
// Re-run the main loop
|
|
421
|
-
// Wait, to make this work we should probably put the auth into the wizard steps
|
|
422
|
-
// But for simplicity, let's just move forward or let user re-run the whole tool
|
|
423
|
-
}
|
|
424
|
-
authMethod = authAnswer.method;
|
|
425
|
-
}
|
|
426
|
-
if (authMethod === 'Personal Access Token') {
|
|
427
|
-
showGitHubTokenHelp();
|
|
428
|
-
const tokenAnswer = await inquirer_1.default.prompt([
|
|
429
|
-
{
|
|
430
|
-
type: 'password',
|
|
431
|
-
name: 'githubToken',
|
|
432
|
-
message: 'Enter GitHub Token (or press Enter to skip):',
|
|
433
|
-
mask: '*'
|
|
434
|
-
}
|
|
435
|
-
]);
|
|
436
|
-
githubToken = tokenAnswer.githubToken?.trim() || null;
|
|
437
|
-
if (!githubToken) {
|
|
438
|
-
console.log(chalk_1.default.yellow('\n Skipping GitHub integration (no token provided)'));
|
|
439
|
-
console.log(chalk_1.default.gray(' You can manually push later with: ') + chalk_1.default.cyan('git remote add origin <url>'));
|
|
440
|
-
normalizedAnswers.createRemote = false;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
const cwd = process.cwd();
|
|
445
|
-
const projectPath = path.join(cwd, name);
|
|
446
|
-
if (fs.existsSync(projectPath)) {
|
|
447
|
-
console.log();
|
|
448
|
-
console.log(chalk_1.default.red(' Error: Directory "' + name + '" already exists!'));
|
|
449
|
-
console.log(chalk_1.default.gray(' Try a different name or remove the existing directory'));
|
|
450
|
-
console.log();
|
|
451
|
-
process.exit(1);
|
|
452
|
-
}
|
|
453
|
-
const config = {
|
|
454
|
-
name: name,
|
|
455
|
-
language: answers.language,
|
|
456
|
-
type: answers.type,
|
|
457
|
-
isTheRepoPublic: answers.visibility === 'Public',
|
|
458
|
-
description: `A ${answers.type} project in ${answers.language}`,
|
|
459
|
-
path: projectPath
|
|
460
|
-
};
|
|
461
|
-
console.log();
|
|
462
|
-
const spinner = (0, ora_1.default)({
|
|
463
|
-
text: 'Initializing...',
|
|
464
|
-
color: 'cyan',
|
|
465
|
-
spinner: 'dots'
|
|
466
|
-
}).start();
|
|
467
|
-
try {
|
|
468
|
-
// Managers
|
|
469
|
-
const templateManager = new TemplateManager_1.TemplateManager();
|
|
470
|
-
// gitManager already instantiated
|
|
471
|
-
const gitHubService = githubToken ? new GitHubServiceCLI_1.GitHubServiceCLI(githubToken) : null;
|
|
472
|
-
// 0. Check Git
|
|
473
|
-
if (!await gitManager.checkGitInstalled()) {
|
|
474
|
-
spinner.fail(chalk_1.default.red('Git is not installed!'));
|
|
475
|
-
console.log(chalk_1.default.yellow('\n Install Git from: ') + chalk_1.default.cyan('https://git-scm.com/'));
|
|
476
|
-
console.log();
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
// 1. Structure
|
|
480
|
-
spinner.text = chalk_1.default.cyan('Generating project structure...');
|
|
481
|
-
await templateManager.createProjectStructure(config);
|
|
482
|
-
spinner.succeed(chalk_1.default.green('Project structure created'));
|
|
483
|
-
// 2. Git Init & Initial Commits
|
|
484
|
-
if (config.type !== types_1.ProjectType.DSAPractice) {
|
|
485
|
-
spinner.start(chalk_1.default.cyan('Initializing Git repository...'));
|
|
486
|
-
await gitManager.init(config.path);
|
|
487
|
-
await gitManager.commit(config.path, "Initial commit");
|
|
488
|
-
// Update README and create second commit
|
|
489
|
-
try {
|
|
490
|
-
const readmePath = path.join(config.path, 'README.md');
|
|
491
|
-
if (fs.existsSync(readmePath)) {
|
|
492
|
-
fs.appendFileSync(readmePath, '\n\nProject initialized by ZeroStart CLI');
|
|
493
|
-
await gitManager.commit(config.path, "Update README.md");
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
catch (error) {
|
|
497
|
-
console.warn(`Failed to update README: ${error}`);
|
|
498
|
-
}
|
|
499
|
-
spinner.succeed(chalk_1.default.green('Git repository initialized'));
|
|
500
|
-
}
|
|
501
|
-
// 3. GitHub
|
|
502
|
-
if (normalizedAnswers.createRemote) {
|
|
503
|
-
spinner.start(chalk_1.default.cyan('Creating GitHub repository...'));
|
|
504
|
-
let repoUrl;
|
|
505
|
-
if (authMethod === 'GitHub CLI') {
|
|
506
|
-
try {
|
|
507
|
-
repoUrl = await gitManager.createRepoWithGh(config.path, config.name, config.isTheRepoPublic);
|
|
508
|
-
}
|
|
509
|
-
catch (error) {
|
|
510
|
-
repoUrl = undefined;
|
|
511
|
-
spinner.fail(chalk_1.default.red(`GH CLI Error: ${error.message}`));
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
else if (gitHubService) {
|
|
515
|
-
repoUrl = await gitHubService.createRepo(config);
|
|
516
|
-
}
|
|
517
|
-
if (repoUrl) {
|
|
518
|
-
spinner.succeed(chalk_1.default.green('GitHub repository created'));
|
|
519
|
-
spinner.start(chalk_1.default.cyan('Pushing to GitHub...'));
|
|
520
|
-
// If GH CLI used, remote is already set to 'origin'
|
|
521
|
-
if (authMethod !== 'GitHub CLI') {
|
|
522
|
-
await gitManager.addRemote(config.path, repoUrl);
|
|
523
|
-
}
|
|
524
|
-
await gitManager.push(config.path);
|
|
525
|
-
// Cleanup token if used in URL (only for non-CLI)
|
|
526
|
-
if (authMethod !== 'GitHub CLI' && repoUrl.includes('@github.com')) {
|
|
527
|
-
const cleanUrl = repoUrl.replace(/\/\/[^@]+@/, '//');
|
|
528
|
-
await gitManager.setRemoteUrl(config.path, cleanUrl);
|
|
529
|
-
}
|
|
530
|
-
spinner.succeed(chalk_1.default.green('Pushed to GitHub'));
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
// Only warn if we actually tried to create a repo (repoUrl is undefined but we entered the block)
|
|
534
|
-
if (!spinner.isSpinning) {
|
|
535
|
-
// It might have failed in GH CLI block with spinner.fail
|
|
536
|
-
}
|
|
537
|
-
else {
|
|
538
|
-
spinner.warn(chalk_1.default.yellow('GitHub repository creation failed'));
|
|
539
|
-
console.log(chalk_1.default.gray(' Check your token permissions and try again'));
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
// Success message
|
|
544
|
-
console.log();
|
|
545
|
-
console.log(chalk_1.default.bold.green(' Success! Your project is ready!'));
|
|
546
|
-
console.log();
|
|
547
|
-
console.log(chalk_1.default.gray(' Location: ') + chalk_1.default.cyan(config.path));
|
|
548
|
-
console.log();
|
|
549
|
-
console.log(chalk_1.default.bold(' Get started:'));
|
|
550
|
-
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(`cd ${name}`));
|
|
551
|
-
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan('code .') + chalk_1.default.gray(' (or your favorite editor)'));
|
|
552
|
-
console.log();
|
|
553
|
-
// Conditional logic based on language OR project type
|
|
554
|
-
const isWebLanguage = [types_1.ProjectLanguage.React, types_1.ProjectLanguage.HTMLCSS].includes(config.language);
|
|
555
|
-
const isPractice = config.type === types_1.ProjectType.DSAPractice;
|
|
556
|
-
if (!isWebLanguage || isPractice) {
|
|
557
|
-
const gdbLinks = {
|
|
558
|
-
[types_1.ProjectLanguage.Python]: 'https://www.onlinegdb.com/online_python_compiler',
|
|
559
|
-
[types_1.ProjectLanguage.Java]: 'https://www.onlinegdb.com/online_java_compiler',
|
|
560
|
-
[types_1.ProjectLanguage.CPP]: 'https://www.onlinegdb.com/online_c++_compiler',
|
|
561
|
-
[types_1.ProjectLanguage.NodeJS]: 'https://www.onlinegdb.com/online_node.js_compiler',
|
|
562
|
-
[types_1.ProjectLanguage.React]: 'https://www.onlinegdb.com/' // Fallback
|
|
563
|
-
};
|
|
564
|
-
const link = gdbLinks[config.language] || 'https://www.onlinegdb.com/';
|
|
565
|
-
if (link) {
|
|
566
|
-
console.log(chalk_1.default.bold.yellow(' Practice Online:'));
|
|
567
|
-
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan(link));
|
|
568
|
-
console.log(chalk_1.default.gray(' (Opening in your browser...)'));
|
|
569
|
-
console.log();
|
|
570
|
-
openUrl(link);
|
|
571
|
-
}
|
|
572
|
-
return; // Skip deployment
|
|
573
|
-
}
|
|
574
|
-
// Deployment Integration (Only for Web)
|
|
575
|
-
const { deploymentTarget } = await inquirer_1.default.prompt([
|
|
576
|
-
{
|
|
577
|
-
type: 'list',
|
|
578
|
-
name: 'deploymentTarget',
|
|
579
|
-
message: 'Select Deployment Provider:',
|
|
580
|
-
choices: ['Vercel', 'None'],
|
|
581
|
-
default: 'None'
|
|
582
|
-
}
|
|
583
|
-
]);
|
|
584
|
-
// 4. Install Dependencies & Build (Required for Deployment)
|
|
585
|
-
if (deploymentTarget !== 'None' && config.language !== types_1.ProjectLanguage.HTMLCSS) {
|
|
586
|
-
console.log();
|
|
587
|
-
const iSpinner = (0, ora_1.default)('Installing dependencies...').start();
|
|
588
|
-
try {
|
|
589
|
-
await new Promise((resolve, reject) => {
|
|
590
|
-
(0, child_process_1.exec)('npm install', { cwd: config.path }, (error, stdout, stderr) => {
|
|
591
|
-
if (error)
|
|
592
|
-
reject(error);
|
|
593
|
-
else
|
|
594
|
-
resolve(stdout);
|
|
595
|
-
});
|
|
596
|
-
});
|
|
597
|
-
iSpinner.succeed(chalk_1.default.green('Dependencies installed'));
|
|
598
|
-
if (config.language === types_1.ProjectLanguage.React || config.type === types_1.ProjectType.WebApp) {
|
|
599
|
-
const bSpinner = (0, ora_1.default)('Building project...').start();
|
|
600
|
-
await new Promise((resolve, reject) => {
|
|
601
|
-
(0, child_process_1.exec)('npm run build', { cwd: config.path }, (error, stdout, stderr) => {
|
|
602
|
-
if (error)
|
|
603
|
-
reject(error);
|
|
604
|
-
else
|
|
605
|
-
resolve(stdout);
|
|
606
|
-
});
|
|
607
|
-
});
|
|
608
|
-
bSpinner.succeed(chalk_1.default.green('Project built successfully'));
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
catch (error) {
|
|
612
|
-
iSpinner.fail(chalk_1.default.red(`Build failed: ${error.message}`));
|
|
613
|
-
console.log(chalk_1.default.yellow(' Deployment might fail. Continuing...'));
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
if (deploymentTarget === 'Vercel') {
|
|
617
|
-
const vercelManager = new VercelManager_1.VercelManager();
|
|
618
|
-
let vercelInstalled = await vercelManager.checkVercelInstalled();
|
|
619
|
-
if (!vercelInstalled) {
|
|
620
|
-
console.log();
|
|
621
|
-
const { installVercel } = await inquirer_1.default.prompt([
|
|
622
|
-
{
|
|
623
|
-
type: 'confirm',
|
|
624
|
-
name: 'installVercel',
|
|
625
|
-
message: 'Vercel CLI not found. Install it globally?',
|
|
626
|
-
default: false
|
|
627
|
-
}
|
|
628
|
-
]);
|
|
629
|
-
if (installVercel) {
|
|
630
|
-
const iSpinner = (0, ora_1.default)('Installing Vercel CLI...').start();
|
|
631
|
-
const installed = await vercelManager.installGlobal();
|
|
632
|
-
if (installed) {
|
|
633
|
-
iSpinner.succeed(chalk_1.default.green('Vercel CLI installed!'));
|
|
634
|
-
vercelInstalled = true;
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
iSpinner.fail(chalk_1.default.red('Failed to install Vercel CLI.'));
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
if (vercelInstalled) {
|
|
642
|
-
// Check Auth
|
|
643
|
-
const vSpinner = (0, ora_1.default)('Checking Vercel authentication...').start();
|
|
644
|
-
const loggedIn = await vercelManager.checkAuth();
|
|
645
|
-
if (!loggedIn) {
|
|
646
|
-
vSpinner.stop();
|
|
647
|
-
console.log(chalk_1.default.yellow('\n Authentication required to deploy.'));
|
|
648
|
-
const { doLogin } = await inquirer_1.default.prompt([
|
|
649
|
-
{
|
|
650
|
-
type: 'confirm',
|
|
651
|
-
name: 'doLogin',
|
|
652
|
-
message: 'Log in to Vercel now?',
|
|
653
|
-
default: true
|
|
654
|
-
}
|
|
655
|
-
]);
|
|
656
|
-
if (doLogin) {
|
|
657
|
-
console.log(chalk_1.default.gray(' Opening Vercel login...'));
|
|
658
|
-
const loginSuccess = await vercelManager.login();
|
|
659
|
-
if (!loginSuccess) {
|
|
660
|
-
console.log(chalk_1.default.red('\n Login failed. Skipping deployment.'));
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
|
-
console.log(chalk_1.default.green('\n Successfully logged in!'));
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
console.log(chalk_1.default.yellow(' Skipping deployment (not logged in).'));
|
|
667
|
-
return;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
else {
|
|
671
|
-
vSpinner.succeed(chalk_1.default.green('Authenticated with Vercel'));
|
|
672
|
-
}
|
|
673
|
-
const dSpinner = (0, ora_1.default)('Deploying to Vercel...').start();
|
|
674
|
-
const deploymentUrl = await vercelManager.deploy(config.path, config.name);
|
|
675
|
-
if (deploymentUrl) {
|
|
676
|
-
dSpinner.succeed(chalk_1.default.green('Deployed to Vercel!'));
|
|
677
|
-
console.log(chalk_1.default.gray(' URL: ') + chalk_1.default.cyan(deploymentUrl));
|
|
678
|
-
}
|
|
679
|
-
else {
|
|
680
|
-
dSpinner.fail(chalk_1.default.red('Vercel deployment failed'));
|
|
681
|
-
console.log(chalk_1.default.gray(' Try running ') + chalk_1.default.cyan('vercel deploy') + chalk_1.default.gray(' manually inside the project folder.'));
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
if (!answers.createRemote || !githubToken && authMethod !== 'GitHub CLI') {
|
|
686
|
-
console.log(chalk_1.default.bold.yellow(' To push to GitHub later:'));
|
|
687
|
-
console.log(chalk_1.default.gray(' - Create a repository on GitHub'));
|
|
688
|
-
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan('git remote add origin <your-repo-url>'));
|
|
689
|
-
console.log(chalk_1.default.gray(' - ') + chalk_1.default.cyan('git push -u origin main'));
|
|
690
|
-
console.log();
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
catch (error) {
|
|
694
|
-
spinner.fail(chalk_1.default.red('Error: ' + error.message));
|
|
695
|
-
console.log();
|
|
696
|
-
console.log(chalk_1.default.gray(' Need help? Check the documentation or open an issue'));
|
|
697
|
-
console.log();
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
catch (error) {
|
|
701
|
-
console.error(chalk_1.default.red('\n Unexpected error:'), error);
|
|
702
|
-
console.log();
|
|
703
|
-
}
|
|
219
|
+
initializeProject(n, s.lang, s.type, { isPublic: false, createRemote: false, githubToken: null, authMethod: 'none' });
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
// Main wizard
|
|
223
|
+
program.argument('[projectName]').action(async (projectName) => {
|
|
224
|
+
showBanner();
|
|
225
|
+
let name = projectName;
|
|
226
|
+
const answers = await inquirer_1.default.prompt([
|
|
227
|
+
{ type: 'input', name: 'name', message: 'Project Name:', skip: !!projectName, when: !projectName },
|
|
228
|
+
{ type: 'list', name: 'language', message: 'Language:', choices: Object.values(types_1.ProjectLanguage) },
|
|
229
|
+
{ type: 'list', name: 'type', message: 'Type:', choices: Object.values(types_1.ProjectType) },
|
|
230
|
+
{ type: 'list', name: 'createRemote', message: 'Push to GitHub?', choices: ['Yes', 'No'], default: 'No', when: (ans) => ans.type !== types_1.ProjectType.DSAPractice }
|
|
231
|
+
]);
|
|
232
|
+
await initializeProject(projectName || answers.name, answers.language, answers.type, {
|
|
233
|
+
isPublic: false,
|
|
234
|
+
createRemote: answers.createRemote === 'Yes',
|
|
235
|
+
githubToken: null,
|
|
236
|
+
authMethod: 'none'
|
|
237
|
+
});
|
|
704
238
|
});
|
|
705
|
-
// Helper functions for emojis (Now text based)
|
|
706
|
-
function getLanguageEmoji(lang) {
|
|
707
|
-
return '[LANG]';
|
|
708
|
-
}
|
|
709
|
-
function getTypeEmoji(type) {
|
|
710
|
-
return '[TYPE]';
|
|
711
|
-
}
|
|
712
239
|
program.parse(process.argv);
|