zerostart-cli 0.0.22 → 0.0.25
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 +122 -6
- package/out/managers/NetlifyManager.js +33 -7
- 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.25');
|
|
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,9 +225,61 @@ 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
|
+
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
|
+
}
|
|
215
280
|
const dSpinner = (0, ora_1.default)('Deploying to Netlify...').start();
|
|
216
|
-
dSpinner.stop();
|
|
217
|
-
const success = await netlifyManager.deploy(cwd);
|
|
281
|
+
dSpinner.stop();
|
|
282
|
+
const success = await netlifyManager.deploy(cwd, activeSiteId);
|
|
218
283
|
if (success) {
|
|
219
284
|
console.log();
|
|
220
285
|
console.log(chalk_1.default.green(' ✔ Deployed to Netlify!'));
|
|
@@ -596,8 +661,59 @@ program
|
|
|
596
661
|
console.log();
|
|
597
662
|
console.log(chalk_1.default.cyan(` Configuring Netlify site for "${config.name}"...`));
|
|
598
663
|
// 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
|
-
|
|
600
|
-
|
|
664
|
+
let siteName = config.name;
|
|
665
|
+
let siteCreated = false;
|
|
666
|
+
let activeSiteId = undefined;
|
|
667
|
+
while (!siteCreated) {
|
|
668
|
+
const result = await netlifyManager.createSite(siteName, config.path);
|
|
669
|
+
if (result.success) {
|
|
670
|
+
siteCreated = true;
|
|
671
|
+
activeSiteId = result.siteId;
|
|
672
|
+
}
|
|
673
|
+
else if (result.reason === 'taken') {
|
|
674
|
+
console.log(chalk_1.default.yellow(`\n The site name "${siteName}" is already taken.`));
|
|
675
|
+
const { newName } = await inquirer_1.default.prompt([{
|
|
676
|
+
type: 'input',
|
|
677
|
+
name: 'newName',
|
|
678
|
+
message: 'Enter a unique name for your Netlify site:',
|
|
679
|
+
validate: (input) => {
|
|
680
|
+
if (input.trim() === '')
|
|
681
|
+
return 'Name is required';
|
|
682
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(input))
|
|
683
|
+
return 'Use only letters, numbers, hyphens, and underscores';
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
}]);
|
|
687
|
+
siteName = newName;
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
console.log(chalk_1.default.red('\n Failed to create Netlify site. '));
|
|
691
|
+
// Allow user to try to deploy anyway (maybe manual link?) or abort
|
|
692
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
693
|
+
type: 'list',
|
|
694
|
+
name: 'action',
|
|
695
|
+
message: 'What would you like to do?',
|
|
696
|
+
choices: ['Try again with a different name', 'Continue deployment (might fail or link to wrong site)', 'Abort']
|
|
697
|
+
}]);
|
|
698
|
+
if (action === 'Abort')
|
|
699
|
+
return;
|
|
700
|
+
if (action === 'Continue deployment (might fail or link to wrong site)')
|
|
701
|
+
break;
|
|
702
|
+
// If try again, ask for name
|
|
703
|
+
const { retryName } = await inquirer_1.default.prompt([{
|
|
704
|
+
type: 'input',
|
|
705
|
+
name: 'retryName',
|
|
706
|
+
message: 'Enter a unique name:',
|
|
707
|
+
validate: (input) => {
|
|
708
|
+
if (input.trim() === '')
|
|
709
|
+
return 'Name is required';
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
}]);
|
|
713
|
+
siteName = retryName;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
const success = await netlifyManager.deploy(config.path, activeSiteId);
|
|
601
717
|
if (success) {
|
|
602
718
|
console.log();
|
|
603
719
|
console.log(chalk_1.default.green(' ✔ Deployed to Netlify!'));
|
|
@@ -66,25 +66,51 @@ class NetlifyManager {
|
|
|
66
66
|
try {
|
|
67
67
|
console.log(chalk_1.default.cyan(` Creating Netlify site "${name}"...`));
|
|
68
68
|
return new Promise((resolve) => {
|
|
69
|
-
// Using 'sites:create' might prompt if not authenticated, but we check auth before this.
|
|
70
69
|
const child = (0, child_process_1.spawn)('netlify', ['sites:create', '--name', name], {
|
|
71
70
|
cwd,
|
|
72
|
-
stdio: 'inherit'
|
|
71
|
+
stdio: ['inherit', 'pipe', 'pipe']
|
|
72
|
+
});
|
|
73
|
+
let output = '';
|
|
74
|
+
child.stdout?.on('data', (data) => {
|
|
75
|
+
const str = data.toString();
|
|
76
|
+
output += str;
|
|
77
|
+
process.stdout.write(data);
|
|
78
|
+
});
|
|
79
|
+
child.stderr?.on('data', (data) => {
|
|
80
|
+
output += data.toString();
|
|
81
|
+
process.stderr.write(data);
|
|
73
82
|
});
|
|
74
83
|
child.on('close', (code) => {
|
|
75
|
-
|
|
84
|
+
if (code === 0) {
|
|
85
|
+
// Extract Site ID/Project ID
|
|
86
|
+
// Format: "Site ID: 022..." or "Project ID: 022..."
|
|
87
|
+
const idMatch = output.match(/(?:Site|Project)\s+ID:\s+([a-zA-Z0-9-]+)/i);
|
|
88
|
+
const siteId = idMatch ? idMatch[1] : undefined;
|
|
89
|
+
resolve({ success: true, siteId });
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
if (output.toLowerCase().includes('already exists') || output.toLowerCase().includes('taken')) {
|
|
93
|
+
resolve({ success: false, reason: 'taken' });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
resolve({ success: false, reason: 'error' });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
76
99
|
});
|
|
77
100
|
});
|
|
78
101
|
}
|
|
79
102
|
catch (error) {
|
|
80
103
|
console.error('Failed to create Netlify site:', error);
|
|
81
|
-
return false;
|
|
104
|
+
return { success: false, reason: 'error' };
|
|
82
105
|
}
|
|
83
106
|
}
|
|
84
|
-
async deploy(cwd) {
|
|
107
|
+
async deploy(cwd, siteId) {
|
|
85
108
|
return new Promise((resolve) => {
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
const args = ['deploy', '--prod'];
|
|
110
|
+
if (siteId) {
|
|
111
|
+
args.push('--site', siteId);
|
|
112
|
+
}
|
|
113
|
+
const child = (0, child_process_1.spawn)('netlify', args, {
|
|
88
114
|
cwd,
|
|
89
115
|
stdio: 'inherit'
|
|
90
116
|
});
|