zerostart-cli 0.0.22 → 0.0.24
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 +116 -4
- package/out/managers/NetlifyManager.js +26 -4
- package/package.json +1 -1
package/out/cli.js
CHANGED
|
@@ -83,7 +83,7 @@ function showGitHubTokenHelp() {
|
|
|
83
83
|
program
|
|
84
84
|
.name('zerostart')
|
|
85
85
|
.description('Create and deploy a complete project with one command')
|
|
86
|
-
.version('0.0.
|
|
86
|
+
.version('0.0.24');
|
|
87
87
|
program
|
|
88
88
|
.command('deploy-vercel')
|
|
89
89
|
.description('Deploy the current project to Vercel')
|
|
@@ -142,8 +142,21 @@ program
|
|
|
142
142
|
else {
|
|
143
143
|
vSpinner.succeed(chalk_1.default.green('Authenticated'));
|
|
144
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
|
+
}]);
|
|
145
158
|
const dSpinner = (0, ora_1.default)('Deploying to Vercel...').start();
|
|
146
|
-
const url = await vercelManager.deploy(cwd);
|
|
159
|
+
const url = await vercelManager.deploy(cwd, vName);
|
|
147
160
|
if (url) {
|
|
148
161
|
dSpinner.succeed(chalk_1.default.green('Deployed to Vercel!'));
|
|
149
162
|
console.log(chalk_1.default.gray(' URL: ') + chalk_1.default.cyan(url));
|
|
@@ -212,8 +225,58 @@ program
|
|
|
212
225
|
else {
|
|
213
226
|
nSpinner.succeed(chalk_1.default.green('Authenticated'));
|
|
214
227
|
}
|
|
228
|
+
// Enforce name for standalone deploy
|
|
229
|
+
const defaultName = path.basename(cwd);
|
|
230
|
+
let siteName = defaultName;
|
|
231
|
+
let siteCreated = false;
|
|
232
|
+
while (!siteCreated) {
|
|
233
|
+
const result = await netlifyManager.createSite(siteName, cwd);
|
|
234
|
+
if (result.success) {
|
|
235
|
+
siteCreated = true;
|
|
236
|
+
}
|
|
237
|
+
else if (result.reason === 'taken') {
|
|
238
|
+
console.log(chalk_1.default.yellow(`\n The site name "${siteName}" is already taken.`));
|
|
239
|
+
const { newName } = await inquirer_1.default.prompt([{
|
|
240
|
+
type: 'input',
|
|
241
|
+
name: 'newName',
|
|
242
|
+
message: 'Enter a unique name for your Netlify site:',
|
|
243
|
+
validate: (input) => {
|
|
244
|
+
if (input.trim() === '')
|
|
245
|
+
return 'Name is required';
|
|
246
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(input))
|
|
247
|
+
return 'Use only letters, numbers, hyphens, and underscores';
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
}]);
|
|
251
|
+
siteName = newName;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log(chalk_1.default.red('\n Failed to configure Netlify site.'));
|
|
255
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
256
|
+
type: 'list',
|
|
257
|
+
name: 'action',
|
|
258
|
+
message: 'What would you like to do?',
|
|
259
|
+
choices: ['Try again with a different name', 'Continue deployment anyway', 'Abort']
|
|
260
|
+
}]);
|
|
261
|
+
if (action === 'Abort')
|
|
262
|
+
return;
|
|
263
|
+
if (action === 'Continue deployment anyway')
|
|
264
|
+
break;
|
|
265
|
+
const { retryName } = await inquirer_1.default.prompt([{
|
|
266
|
+
type: 'input',
|
|
267
|
+
name: 'retryName',
|
|
268
|
+
message: 'Enter a unique name:',
|
|
269
|
+
validate: (input) => {
|
|
270
|
+
if (input.trim() === '')
|
|
271
|
+
return 'Name is required';
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
}]);
|
|
275
|
+
siteName = retryName;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
215
278
|
const dSpinner = (0, ora_1.default)('Deploying to Netlify...').start();
|
|
216
|
-
dSpinner.stop();
|
|
279
|
+
dSpinner.stop();
|
|
217
280
|
const success = await netlifyManager.deploy(cwd);
|
|
218
281
|
if (success) {
|
|
219
282
|
console.log();
|
|
@@ -596,7 +659,56 @@ program
|
|
|
596
659
|
console.log();
|
|
597
660
|
console.log(chalk_1.default.cyan(` Configuring Netlify site for "${config.name}"...`));
|
|
598
661
|
// We do this interactively so if name is taken user can see error and handle it (or it just links if they own it)
|
|
599
|
-
|
|
662
|
+
let siteName = config.name;
|
|
663
|
+
let siteCreated = false;
|
|
664
|
+
while (!siteCreated) {
|
|
665
|
+
const result = await netlifyManager.createSite(siteName, config.path);
|
|
666
|
+
if (result.success) {
|
|
667
|
+
siteCreated = true;
|
|
668
|
+
}
|
|
669
|
+
else if (result.reason === 'taken') {
|
|
670
|
+
console.log(chalk_1.default.yellow(`\n The site name "${siteName}" is already taken.`));
|
|
671
|
+
const { newName } = await inquirer_1.default.prompt([{
|
|
672
|
+
type: 'input',
|
|
673
|
+
name: 'newName',
|
|
674
|
+
message: 'Enter a unique name for your Netlify site:',
|
|
675
|
+
validate: (input) => {
|
|
676
|
+
if (input.trim() === '')
|
|
677
|
+
return 'Name is required';
|
|
678
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(input))
|
|
679
|
+
return 'Use only letters, numbers, hyphens, and underscores';
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
}]);
|
|
683
|
+
siteName = newName;
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
console.log(chalk_1.default.red('\n Failed to create Netlify site. '));
|
|
687
|
+
// Allow user to try to deploy anyway (maybe manual link?) or abort
|
|
688
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
689
|
+
type: 'list',
|
|
690
|
+
name: 'action',
|
|
691
|
+
message: 'What would you like to do?',
|
|
692
|
+
choices: ['Try again with a different name', 'Continue deployment (might fail or link to wrong site)', 'Abort']
|
|
693
|
+
}]);
|
|
694
|
+
if (action === 'Abort')
|
|
695
|
+
return;
|
|
696
|
+
if (action === 'Continue deployment (might fail or link to wrong site)')
|
|
697
|
+
break;
|
|
698
|
+
// If try again, ask for name
|
|
699
|
+
const { retryName } = await inquirer_1.default.prompt([{
|
|
700
|
+
type: 'input',
|
|
701
|
+
name: 'retryName',
|
|
702
|
+
message: 'Enter a unique name:',
|
|
703
|
+
validate: (input) => {
|
|
704
|
+
if (input.trim() === '')
|
|
705
|
+
return 'Name is required';
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
}]);
|
|
709
|
+
siteName = retryName;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
600
712
|
const success = await netlifyManager.deploy(config.path);
|
|
601
713
|
if (success) {
|
|
602
714
|
console.log();
|
|
@@ -65,20 +65,42 @@ class NetlifyManager {
|
|
|
65
65
|
async createSite(name, cwd) {
|
|
66
66
|
try {
|
|
67
67
|
console.log(chalk_1.default.cyan(` Creating Netlify site "${name}"...`));
|
|
68
|
+
// We need to capture output to detect "already exists" error
|
|
69
|
+
// sites:create fails if name is taken.
|
|
68
70
|
return new Promise((resolve) => {
|
|
69
|
-
// Using 'sites:create' might prompt if not authenticated, but we check auth before this.
|
|
70
71
|
const child = (0, child_process_1.spawn)('netlify', ['sites:create', '--name', name], {
|
|
71
72
|
cwd,
|
|
72
|
-
stdio: 'inherit'
|
|
73
|
+
stdio: ['inherit', 'pipe', 'pipe'] // Pipe stdout/stderr to capture
|
|
74
|
+
});
|
|
75
|
+
let output = '';
|
|
76
|
+
child.stdout?.on('data', (data) => {
|
|
77
|
+
output += data.toString();
|
|
78
|
+
process.stdout.write(data); // Passthrough
|
|
79
|
+
});
|
|
80
|
+
child.stderr?.on('data', (data) => {
|
|
81
|
+
output += data.toString();
|
|
82
|
+
process.stderr.write(data); // Passthrough
|
|
73
83
|
});
|
|
74
84
|
child.on('close', (code) => {
|
|
75
|
-
|
|
85
|
+
if (code === 0) {
|
|
86
|
+
resolve({ success: true });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Check for common "name taken" indicators in Netlify CLI output
|
|
90
|
+
// "Already exists" or "name is already taken"
|
|
91
|
+
if (output.toLowerCase().includes('already exists') || output.toLowerCase().includes('taken')) {
|
|
92
|
+
resolve({ success: false, reason: 'taken' });
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
resolve({ success: false, reason: 'error' });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
76
98
|
});
|
|
77
99
|
});
|
|
78
100
|
}
|
|
79
101
|
catch (error) {
|
|
80
102
|
console.error('Failed to create Netlify site:', error);
|
|
81
|
-
return false;
|
|
103
|
+
return { success: false, reason: 'error' };
|
|
82
104
|
}
|
|
83
105
|
}
|
|
84
106
|
async deploy(cwd) {
|