@nimbuslab/cli 0.6.2 → 0.7.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/.github/workflows/publish.yml +2 -0
- package/dist/index.js +115 -115
- package/docs/CI-CD.md +172 -0
- package/package.json +1 -1
- package/src/commands/create.ts +95 -95
- package/src/index.ts +20 -20
package/src/commands/create.ts
CHANGED
|
@@ -143,7 +143,7 @@ async function ensureRailwayCli(): Promise<boolean> {
|
|
|
143
143
|
|
|
144
144
|
if (hasRailway) return true
|
|
145
145
|
|
|
146
|
-
console.log(pc.yellow("Railway CLI
|
|
146
|
+
console.log(pc.yellow("Railway CLI not found. Installing..."))
|
|
147
147
|
console.log()
|
|
148
148
|
|
|
149
149
|
try {
|
|
@@ -152,11 +152,11 @@ async function ensureRailwayCli(): Promise<boolean> {
|
|
|
152
152
|
} else {
|
|
153
153
|
await $`curl -fsSL https://railway.app/install.sh | sh`.quiet()
|
|
154
154
|
}
|
|
155
|
-
console.log(pc.green("Railway CLI
|
|
155
|
+
console.log(pc.green("Railway CLI installed successfully!"))
|
|
156
156
|
return true
|
|
157
157
|
} catch (error) {
|
|
158
|
-
console.log(pc.red("
|
|
159
|
-
console.log(pc.dim("
|
|
158
|
+
console.log(pc.red("Error installing Railway CLI."))
|
|
159
|
+
console.log(pc.dim("Install manually: https://docs.railway.app/guides/cli"))
|
|
160
160
|
return false
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -192,8 +192,8 @@ export async function create(args: string[]) {
|
|
|
192
192
|
const hasGh = await $`${checkCmd} gh`.quiet().then(() => true).catch(() => false)
|
|
193
193
|
|
|
194
194
|
if (!hasBun) {
|
|
195
|
-
console.log(pc.red("
|
|
196
|
-
console.log(pc.dim("
|
|
195
|
+
console.log(pc.red("Error: Bun not found."))
|
|
196
|
+
console.log(pc.dim("Install from: https://bun.sh"))
|
|
197
197
|
console.log()
|
|
198
198
|
if (process.platform === "win32") {
|
|
199
199
|
console.log(pc.cyan('powershell -c "irm bun.sh/install.ps1 | iex"'))
|
|
@@ -205,14 +205,14 @@ export async function create(args: string[]) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
if (!hasGit) {
|
|
208
|
-
console.log(pc.red("
|
|
209
|
-
console.log(pc.dim("
|
|
208
|
+
console.log(pc.red("Error: Git not found."))
|
|
209
|
+
console.log(pc.dim("Install git to continue."))
|
|
210
210
|
process.exit(1)
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
if (!hasGh) {
|
|
214
|
-
console.log(pc.red("
|
|
215
|
-
console.log(pc.dim("
|
|
214
|
+
console.log(pc.red("Error: GitHub CLI (gh) not found."))
|
|
215
|
+
console.log(pc.dim("Install from: https://cli.github.com"))
|
|
216
216
|
console.log()
|
|
217
217
|
if (process.platform === "win32") {
|
|
218
218
|
console.log(pc.cyan("winget install GitHub.cli"))
|
|
@@ -226,8 +226,8 @@ export async function create(args: string[]) {
|
|
|
226
226
|
// Verifica se gh esta autenticado
|
|
227
227
|
const ghAuth = await $`gh auth status`.quiet().then(() => true).catch(() => false)
|
|
228
228
|
if (!ghAuth) {
|
|
229
|
-
console.log(pc.red("
|
|
230
|
-
console.log(pc.dim("
|
|
229
|
+
console.log(pc.red("Error: GitHub CLI not authenticated."))
|
|
230
|
+
console.log(pc.dim("Run: gh auth login"))
|
|
231
231
|
process.exit(1)
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -236,15 +236,15 @@ export async function create(args: string[]) {
|
|
|
236
236
|
if (hasRailway) {
|
|
237
237
|
const railwayAuth = await isRailwayAuthenticated()
|
|
238
238
|
if (!railwayAuth) {
|
|
239
|
-
console.log(pc.yellow("Railway CLI
|
|
240
|
-
console.log(pc.dim("
|
|
239
|
+
console.log(pc.yellow("Railway CLI not authenticated."))
|
|
240
|
+
console.log(pc.dim("Run: railway login"))
|
|
241
241
|
console.log()
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
const { flags, projectName } = parseFlags(args)
|
|
246
246
|
|
|
247
|
-
p.intro(pc.bgCyan(pc.black("
|
|
247
|
+
p.intro(pc.bgCyan(pc.black(" New nimbuslab Project ")))
|
|
248
248
|
|
|
249
249
|
let config: ProjectConfig | symbol
|
|
250
250
|
|
|
@@ -284,10 +284,10 @@ export async function create(args: string[]) {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type
|
|
287
|
-
console.log(pc.dim(`
|
|
288
|
-
console.log(pc.dim(`
|
|
289
|
-
console.log(pc.dim(` Git: ${config.git ? "
|
|
290
|
-
console.log(pc.dim(`
|
|
287
|
+
console.log(pc.dim(` Project: ${projectName}`))
|
|
288
|
+
console.log(pc.dim(` Type: ${typeLabel}`))
|
|
289
|
+
console.log(pc.dim(` Git: ${config.git ? "yes" : "no"}`))
|
|
290
|
+
console.log(pc.dim(` Install: ${config.install ? "yes" : "no"}`))
|
|
291
291
|
if (flags.railway) console.log(pc.dim(` Railway: configurar`))
|
|
292
292
|
if (flags.template) console.log(pc.dim(` Template: ${flags.template}`))
|
|
293
293
|
console.log()
|
|
@@ -305,7 +305,7 @@ export async function create(args: string[]) {
|
|
|
305
305
|
}
|
|
306
306
|
} else {
|
|
307
307
|
// Fast+: cria projeto novo automaticamente
|
|
308
|
-
console.log(pc.dim(`
|
|
308
|
+
console.log(pc.dim(` Creating project Railway: ${projectName}...`))
|
|
309
309
|
try {
|
|
310
310
|
const result = await $`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text()
|
|
311
311
|
const newProject = JSON.parse(result)
|
|
@@ -316,7 +316,7 @@ export async function create(args: string[]) {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
} else {
|
|
319
|
-
console.log(pc.yellow(` Railway:
|
|
319
|
+
console.log(pc.yellow(` Railway: not authenticated (railway login)`))
|
|
320
320
|
}
|
|
321
321
|
console.log()
|
|
322
322
|
}
|
|
@@ -325,13 +325,13 @@ export async function create(args: string[]) {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
if (p.isCancel(config)) {
|
|
328
|
-
p.cancel("
|
|
328
|
+
p.cancel("Operation cancelled")
|
|
329
329
|
process.exit(0)
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
await createProject(config as ProjectConfig)
|
|
333
333
|
|
|
334
|
-
p.outro(pc.green("
|
|
334
|
+
p.outro(pc.green("Project created successfully!"))
|
|
335
335
|
|
|
336
336
|
showNextSteps(config as ProjectConfig)
|
|
337
337
|
}
|
|
@@ -341,18 +341,18 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
341
341
|
const { isMember, user } = await isNimbuslabMember()
|
|
342
342
|
|
|
343
343
|
// Saudacao
|
|
344
|
-
const greeting = user ? `
|
|
344
|
+
const greeting = user ? `Hello, ${user}!` : "Hello!"
|
|
345
345
|
console.log(pc.dim(` ${greeting}`))
|
|
346
346
|
console.log()
|
|
347
347
|
|
|
348
348
|
const name = await p.text({
|
|
349
|
-
message: "
|
|
349
|
+
message: "Project name:",
|
|
350
350
|
placeholder: "meu-projeto",
|
|
351
351
|
initialValue: initialName,
|
|
352
352
|
validate: (value) => {
|
|
353
|
-
if (!value) return "
|
|
353
|
+
if (!value) return "Name is required"
|
|
354
354
|
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
355
|
-
return "Use
|
|
355
|
+
return "Use only lowercase letters, numbers and hyphens"
|
|
356
356
|
}
|
|
357
357
|
return undefined
|
|
358
358
|
},
|
|
@@ -384,17 +384,17 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
384
384
|
{
|
|
385
385
|
value: "fast",
|
|
386
386
|
label: "fast",
|
|
387
|
-
hint: "Landing page
|
|
387
|
+
hint: "Landing page fast methodology",
|
|
388
388
|
},
|
|
389
389
|
{
|
|
390
390
|
value: "fast+",
|
|
391
391
|
label: "fast+",
|
|
392
|
-
hint: "SaaS
|
|
392
|
+
hint: "Complete SaaS",
|
|
393
393
|
},
|
|
394
394
|
] : []
|
|
395
395
|
|
|
396
396
|
const type = await p.select({
|
|
397
|
-
message: "
|
|
397
|
+
message: "Project type:",
|
|
398
398
|
options: [...publicOptions, ...privateOptions],
|
|
399
399
|
})
|
|
400
400
|
|
|
@@ -405,7 +405,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
405
405
|
|
|
406
406
|
// Se não é membro e tentou usar template privado (via flag), bloqueia
|
|
407
407
|
if (!isMember && !isPublicTemplate) {
|
|
408
|
-
console.log(pc.red("
|
|
408
|
+
console.log(pc.red("Error: Template available only for nimbuslab members"))
|
|
409
409
|
process.exit(1)
|
|
410
410
|
}
|
|
411
411
|
|
|
@@ -413,7 +413,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
413
413
|
let monorepo = false
|
|
414
414
|
if (type === "fast+") {
|
|
415
415
|
const useMonorepo = await p.confirm({
|
|
416
|
-
message: "
|
|
416
|
+
message: "Use monorepo (Turborepo)?",
|
|
417
417
|
initialValue: false,
|
|
418
418
|
})
|
|
419
419
|
if (p.isCancel(useMonorepo)) return useMonorepo
|
|
@@ -421,7 +421,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
const git = await p.confirm({
|
|
424
|
-
message: "
|
|
424
|
+
message: "Initialize Git repository?",
|
|
425
425
|
initialValue: true,
|
|
426
426
|
})
|
|
427
427
|
|
|
@@ -434,7 +434,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
434
434
|
|
|
435
435
|
if (git) {
|
|
436
436
|
const createGithub = await p.confirm({
|
|
437
|
-
message: "
|
|
437
|
+
message: "Create GitHub repository?",
|
|
438
438
|
initialValue: false,
|
|
439
439
|
})
|
|
440
440
|
|
|
@@ -445,12 +445,12 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
445
445
|
if (github) {
|
|
446
446
|
// M13: Selecao de organizacao GitHub
|
|
447
447
|
const org = await p.select({
|
|
448
|
-
message: "
|
|
448
|
+
message: "GitHub organization:",
|
|
449
449
|
options: [
|
|
450
|
-
{ value: "nimbuslab", label: "nimbuslab", hint: "
|
|
451
|
-
{ value: "fast-by-nimbuslab", label: "fast-by-nimbuslab", hint: "
|
|
450
|
+
{ value: "nimbuslab", label: "nimbuslab", hint: "Main org" },
|
|
451
|
+
{ value: "fast-by-nimbuslab", label: "fast-by-nimbuslab", hint: "Client projects" },
|
|
452
452
|
{ value: "nimbuslab-templates", label: "nimbuslab-templates", hint: "Templates" },
|
|
453
|
-
{ value: null, label: "Pessoal", hint: "
|
|
453
|
+
{ value: null, label: "Pessoal", hint: "Personal" },
|
|
454
454
|
],
|
|
455
455
|
})
|
|
456
456
|
|
|
@@ -459,7 +459,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
459
459
|
|
|
460
460
|
// M14: Descricao do repo
|
|
461
461
|
const description = await p.text({
|
|
462
|
-
message: "
|
|
462
|
+
message: "Repository description:",
|
|
463
463
|
placeholder: "Landing page para cliente X",
|
|
464
464
|
initialValue: type === "fast" ? "Landing page fast by nimbuslab" : "SaaS fast+ by nimbuslab",
|
|
465
465
|
})
|
|
@@ -473,9 +473,9 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
473
473
|
let contractNumber = ""
|
|
474
474
|
if (type === "fast") {
|
|
475
475
|
const contract = await p.text({
|
|
476
|
-
message: "
|
|
476
|
+
message: "Contract number (ex: 001):",
|
|
477
477
|
placeholder: "001",
|
|
478
|
-
validate: (v) => v ? undefined : "
|
|
478
|
+
validate: (v) => v ? undefined : "Contract number is required for fast",
|
|
479
479
|
})
|
|
480
480
|
if (p.isCancel(contract)) return contract
|
|
481
481
|
contractNumber = contract as string
|
|
@@ -484,7 +484,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
484
484
|
// Templates públicos têm fluxo simplificado
|
|
485
485
|
if (isPublicTemplate) {
|
|
486
486
|
const install = await p.confirm({
|
|
487
|
-
message: "
|
|
487
|
+
message: "Install dependencies?",
|
|
488
488
|
initialValue: true,
|
|
489
489
|
})
|
|
490
490
|
|
|
@@ -533,11 +533,11 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
533
533
|
|
|
534
534
|
// Menu de configuracoes opcionais
|
|
535
535
|
const infraOptions = await p.multiselect({
|
|
536
|
-
message: "
|
|
536
|
+
message: "What do you want to configure now?",
|
|
537
537
|
options: [
|
|
538
|
-
{ value: "urls", label: "URLs", hint: "staging
|
|
539
|
-
{ value: "resend", label: "Resend", hint: "emails
|
|
540
|
-
{ value: "railway", label: "Railway", hint: "deploy
|
|
538
|
+
{ value: "urls", label: "URLs", hint: "staging and production" },
|
|
539
|
+
{ value: "resend", label: "Resend", hint: "form emails" },
|
|
540
|
+
{ value: "railway", label: "Railway", hint: "deploy and hosting" },
|
|
541
541
|
],
|
|
542
542
|
required: false,
|
|
543
543
|
})
|
|
@@ -549,10 +549,10 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
549
549
|
// URLs
|
|
550
550
|
if (configItems.includes("urls")) {
|
|
551
551
|
console.log()
|
|
552
|
-
console.log(pc.dim(" URLs
|
|
552
|
+
console.log(pc.dim(" Project URLs"))
|
|
553
553
|
|
|
554
554
|
const staging = await p.text({
|
|
555
|
-
message: "URL
|
|
555
|
+
message: "Staging URL:",
|
|
556
556
|
placeholder: defaultStagingUrl,
|
|
557
557
|
initialValue: defaultStagingUrl,
|
|
558
558
|
})
|
|
@@ -560,7 +560,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
560
560
|
stagingUrl = staging as string
|
|
561
561
|
|
|
562
562
|
const production = await p.text({
|
|
563
|
-
message: "URL
|
|
563
|
+
message: "Production URL:",
|
|
564
564
|
placeholder: defaultStagingUrl.replace('.nimbuslab.net.br', '.com.br'),
|
|
565
565
|
initialValue: "",
|
|
566
566
|
})
|
|
@@ -581,7 +581,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
581
581
|
resendApiKey = resendKey as string
|
|
582
582
|
|
|
583
583
|
const fromEmail = await p.text({
|
|
584
|
-
message: "
|
|
584
|
+
message: "From email:",
|
|
585
585
|
placeholder: defaultFromEmail,
|
|
586
586
|
initialValue: defaultFromEmail,
|
|
587
587
|
})
|
|
@@ -589,7 +589,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
589
589
|
resendFromEmail = fromEmail as string
|
|
590
590
|
|
|
591
591
|
const contact = await p.text({
|
|
592
|
-
message: "
|
|
592
|
+
message: "Contact email (receives forms):",
|
|
593
593
|
placeholder: defaultContactEmail,
|
|
594
594
|
initialValue: defaultContactEmail,
|
|
595
595
|
})
|
|
@@ -613,21 +613,21 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
613
613
|
const fastProject = projects.find(p => p.toLowerCase().includes("fast by nimbuslab"))
|
|
614
614
|
if (fastProject) {
|
|
615
615
|
railwayProject = fastProject
|
|
616
|
-
console.log(pc.green(`
|
|
616
|
+
console.log(pc.green(` Project: ${fastProject} (automatico)`))
|
|
617
617
|
} else {
|
|
618
|
-
console.log(pc.yellow("
|
|
619
|
-
console.log(pc.dim(" Configure
|
|
618
|
+
console.log(pc.yellow(" Project 'Fast by nimbuslab' not found."))
|
|
619
|
+
console.log(pc.dim(" Configure manually in .env"))
|
|
620
620
|
}
|
|
621
621
|
} else {
|
|
622
622
|
// Fast+ pode escolher projeto existente ou criar novo
|
|
623
623
|
const projectOptions = [
|
|
624
624
|
...projects.map(proj => ({ value: proj, label: proj })),
|
|
625
|
-
{ value: "__new__", label: "
|
|
626
|
-
{ value: "__skip__", label: "
|
|
625
|
+
{ value: "__new__", label: "Create new project", hint: "via railway init" },
|
|
626
|
+
{ value: "__skip__", label: "Skip", hint: "Configure later" },
|
|
627
627
|
]
|
|
628
628
|
|
|
629
629
|
const selectedProject = await p.select({
|
|
630
|
-
message: "
|
|
630
|
+
message: "Railway project for this SaaS:",
|
|
631
631
|
options: projectOptions,
|
|
632
632
|
})
|
|
633
633
|
|
|
@@ -636,32 +636,32 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
636
636
|
if (selectedProject === "__new__") {
|
|
637
637
|
// Criar projeto via Railway CLI
|
|
638
638
|
const projectNameForRailway = name as string
|
|
639
|
-
console.log(pc.dim(`
|
|
639
|
+
console.log(pc.dim(` Creating project "${projectNameForRailway}" on Railway...`))
|
|
640
640
|
try {
|
|
641
641
|
// Usa echo para passar input vazio e aceitar defaults (workspace)
|
|
642
642
|
const result = await $`echo "" | railway init -n ${projectNameForRailway} -w nimbuslab --json`.text()
|
|
643
643
|
const newProject = JSON.parse(result)
|
|
644
644
|
railwayProject = newProject.name || projectNameForRailway
|
|
645
|
-
console.log(pc.green(` Projeto "${railwayProject}"
|
|
645
|
+
console.log(pc.green(` Projeto "${railwayProject}" created successfully!`))
|
|
646
646
|
console.log(pc.dim(` ID: ${newProject.id || "N/A"}`))
|
|
647
647
|
} catch (error) {
|
|
648
|
-
console.log(pc.yellow("
|
|
649
|
-
console.log(pc.dim("
|
|
648
|
+
console.log(pc.yellow(" Error creating project via CLI."))
|
|
649
|
+
console.log(pc.dim(" Create manually at: https://railway.app/new"))
|
|
650
650
|
}
|
|
651
651
|
} else if (selectedProject !== "__skip__") {
|
|
652
652
|
railwayProject = selectedProject as string
|
|
653
|
-
console.log(pc.green(`
|
|
653
|
+
console.log(pc.green(` Project selected: ${railwayProject}`))
|
|
654
654
|
}
|
|
655
655
|
}
|
|
656
656
|
} else {
|
|
657
657
|
console.log()
|
|
658
|
-
console.log(pc.yellow(" Railway:
|
|
659
|
-
console.log(pc.dim(" Configure
|
|
658
|
+
console.log(pc.yellow(" Railway: not authenticated (railway login)"))
|
|
659
|
+
console.log(pc.dim(" Configure manually in .env"))
|
|
660
660
|
}
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
const install = await p.confirm({
|
|
664
|
-
message: "
|
|
664
|
+
message: "Install dependencies?",
|
|
665
665
|
initialValue: true,
|
|
666
666
|
})
|
|
667
667
|
|
|
@@ -708,7 +708,7 @@ async function createProject(config: ProjectConfig) {
|
|
|
708
708
|
// Verifica se é template público
|
|
709
709
|
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type)
|
|
710
710
|
|
|
711
|
-
s.start(`
|
|
711
|
+
s.start(`Cloning template ${templateLabel}...`)
|
|
712
712
|
try {
|
|
713
713
|
if (isPublicTemplate) {
|
|
714
714
|
// Templates públicos: usa HTTPS (não precisa de auth)
|
|
@@ -719,22 +719,22 @@ async function createProject(config: ProjectConfig) {
|
|
|
719
719
|
await $`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet()
|
|
720
720
|
}
|
|
721
721
|
await rm(join(config.name, ".git"), { recursive: true, force: true })
|
|
722
|
-
s.stop(`Template
|
|
722
|
+
s.stop(`Template cloned`)
|
|
723
723
|
} catch (error) {
|
|
724
|
-
s.stop("
|
|
725
|
-
throw new Error(`
|
|
724
|
+
s.stop("Error cloning template")
|
|
725
|
+
throw new Error(`Failed to clone template ${templateRepo}. Check your connection or repository access.`)
|
|
726
726
|
}
|
|
727
727
|
|
|
728
728
|
// Update package.json
|
|
729
|
-
s.start("
|
|
729
|
+
s.start("Configuring project...")
|
|
730
730
|
try {
|
|
731
731
|
const pkgPath = `${config.name}/package.json`
|
|
732
732
|
const pkg = await Bun.file(pkgPath).json()
|
|
733
733
|
pkg.name = config.name
|
|
734
734
|
await Bun.write(pkgPath, JSON.stringify(pkg, null, 2))
|
|
735
|
-
s.stop("
|
|
735
|
+
s.stop("Project configured")
|
|
736
736
|
} catch (error) {
|
|
737
|
-
s.stop("
|
|
737
|
+
s.stop("Error configuring")
|
|
738
738
|
// Continue anyway
|
|
739
739
|
}
|
|
740
740
|
|
|
@@ -747,7 +747,7 @@ async function createProject(config: ProjectConfig) {
|
|
|
747
747
|
|
|
748
748
|
// Git init with full branch flow: main → staging → develop
|
|
749
749
|
if (config.git) {
|
|
750
|
-
s.start("
|
|
750
|
+
s.start("Initializing Git...")
|
|
751
751
|
try {
|
|
752
752
|
const cwd = config.name
|
|
753
753
|
// Init with main branch (not master)
|
|
@@ -759,14 +759,14 @@ async function createProject(config: ProjectConfig) {
|
|
|
759
759
|
await $`git checkout -b staging`.cwd(cwd).quiet()
|
|
760
760
|
await $`git checkout -b develop`.cwd(cwd).quiet()
|
|
761
761
|
|
|
762
|
-
s.stop("Git
|
|
762
|
+
s.stop("Git initialized (main -> staging -> develop)")
|
|
763
763
|
} catch (error) {
|
|
764
|
-
s.stop("
|
|
764
|
+
s.stop("Error initializing Git")
|
|
765
765
|
}
|
|
766
766
|
|
|
767
767
|
// Create GitHub repo if requested (M13 + M14)
|
|
768
768
|
if (config.github) {
|
|
769
|
-
s.start("
|
|
769
|
+
s.start("Creating GitHub repository...")
|
|
770
770
|
try {
|
|
771
771
|
const cwd = config.name
|
|
772
772
|
const repoName = config.githubOrg
|
|
@@ -789,8 +789,8 @@ async function createProject(config: ProjectConfig) {
|
|
|
789
789
|
|
|
790
790
|
s.stop(`GitHub: ${repoName} criado`)
|
|
791
791
|
} catch (error) {
|
|
792
|
-
s.stop("
|
|
793
|
-
console.log(pc.dim("
|
|
792
|
+
s.stop("Error creating GitHub repository")
|
|
793
|
+
console.log(pc.dim(" You can create manually with: gh repo create"))
|
|
794
794
|
}
|
|
795
795
|
}
|
|
796
796
|
}
|
|
@@ -802,8 +802,8 @@ async function createProject(config: ProjectConfig) {
|
|
|
802
802
|
await $`railway link -p ${config.railwayProject}`.cwd(config.name).quiet()
|
|
803
803
|
s.stop(`Railway linkado: ${config.railwayProject}`)
|
|
804
804
|
} catch (error) {
|
|
805
|
-
s.stop("
|
|
806
|
-
console.log(pc.dim("
|
|
805
|
+
s.stop("Error linking Railway")
|
|
806
|
+
console.log(pc.dim(" Run manually: railway link"))
|
|
807
807
|
}
|
|
808
808
|
}
|
|
809
809
|
|
|
@@ -815,18 +815,18 @@ async function createProject(config: ProjectConfig) {
|
|
|
815
815
|
await Bun.write(`${config.name}/.env`, envContent)
|
|
816
816
|
s.stop("Arquivo .env criado")
|
|
817
817
|
} catch (error) {
|
|
818
|
-
s.stop("
|
|
818
|
+
s.stop("Error creating .env")
|
|
819
819
|
}
|
|
820
820
|
}
|
|
821
821
|
|
|
822
822
|
// Install deps
|
|
823
823
|
if (config.install) {
|
|
824
|
-
s.start("
|
|
824
|
+
s.start("Installing dependencies (pode demorar)...")
|
|
825
825
|
try {
|
|
826
826
|
await $`bun install`.cwd(config.name).quiet()
|
|
827
|
-
s.stop("
|
|
827
|
+
s.stop("Dependencies installed")
|
|
828
828
|
} catch (error) {
|
|
829
|
-
s.stop("
|
|
829
|
+
s.stop("Error installing dependencies")
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
832
|
}
|
|
@@ -856,7 +856,7 @@ function generateEnvFile(config: ProjectConfig): string {
|
|
|
856
856
|
lines.push("")
|
|
857
857
|
lines.push("# Railway")
|
|
858
858
|
if (config.railwayProject) {
|
|
859
|
-
lines.push(`#
|
|
859
|
+
lines.push(`# Project: ${config.railwayProject}`)
|
|
860
860
|
}
|
|
861
861
|
lines.push(`RAILWAY_TOKEN=${config.railwayToken || "# Configure com: railway link"}`)
|
|
862
862
|
}
|
|
@@ -879,7 +879,7 @@ function showNextSteps(config: ProjectConfig) {
|
|
|
879
879
|
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type)
|
|
880
880
|
|
|
881
881
|
console.log()
|
|
882
|
-
console.log(pc.bold("
|
|
882
|
+
console.log(pc.bold("Next steps:"))
|
|
883
883
|
console.log()
|
|
884
884
|
console.log(` ${pc.cyan("cd")} ${config.name}`)
|
|
885
885
|
|
|
@@ -896,7 +896,7 @@ function showNextSteps(config: ProjectConfig) {
|
|
|
896
896
|
|
|
897
897
|
// Git flow info
|
|
898
898
|
if (config.git) {
|
|
899
|
-
console.log(pc.dim(" Git flow: main -> staging -> develop (branch
|
|
899
|
+
console.log(pc.dim(" Git flow: main -> staging -> develop (current branch)"))
|
|
900
900
|
console.log()
|
|
901
901
|
|
|
902
902
|
// GitHub info
|
|
@@ -907,34 +907,34 @@ function showNextSteps(config: ProjectConfig) {
|
|
|
907
907
|
console.log(pc.green(` GitHub: ${repoUrl}`))
|
|
908
908
|
console.log()
|
|
909
909
|
} else {
|
|
910
|
-
console.log(pc.yellow("
|
|
910
|
+
console.log(pc.yellow(" Tip: To create GitHub repo, use 'gh repo create' ou 'bun setup'."))
|
|
911
911
|
console.log()
|
|
912
912
|
}
|
|
913
913
|
}
|
|
914
914
|
|
|
915
915
|
if (config.type === "fast+") {
|
|
916
|
-
console.log(pc.dim("
|
|
916
|
+
console.log(pc.dim(" Tip: For fast+, configure DATABASE_URL e BETTER_AUTH_SECRET no .env"))
|
|
917
917
|
if (!config.railwayToken) {
|
|
918
|
-
console.log(pc.dim(" Railway:
|
|
918
|
+
console.log(pc.dim(" Railway: Create a project at https://railway.app/new"))
|
|
919
919
|
}
|
|
920
920
|
console.log()
|
|
921
921
|
}
|
|
922
922
|
|
|
923
923
|
// Info sobre .env
|
|
924
924
|
if (config.resendApiKey || config.stagingUrl) {
|
|
925
|
-
console.log(pc.green(" .env
|
|
925
|
+
console.log(pc.green(" .env configured successfully!"))
|
|
926
926
|
console.log()
|
|
927
927
|
} else {
|
|
928
|
-
console.log(pc.yellow("
|
|
928
|
+
console.log(pc.yellow(" Tip: Configure .env manually or use 'bun setup'."))
|
|
929
929
|
console.log()
|
|
930
930
|
}
|
|
931
931
|
|
|
932
932
|
// Info sobre templates públicos
|
|
933
933
|
if (isPublicTemplate) {
|
|
934
|
-
console.log(pc.dim("
|
|
935
|
-
console.log(pc.dim(`
|
|
934
|
+
console.log(pc.dim(" Open source template (MIT) by nimbuslab"))
|
|
935
|
+
console.log(pc.dim(` Documentation: https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`))
|
|
936
936
|
} else {
|
|
937
|
-
console.log(pc.dim("
|
|
937
|
+
console.log(pc.dim(" Documentation: https://github.com/nimbuslab-templates"))
|
|
938
938
|
}
|
|
939
939
|
console.log()
|
|
940
940
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import pc from "picocolors"
|
|
|
5
5
|
import { create } from "./commands/create"
|
|
6
6
|
|
|
7
7
|
const PACKAGE_NAME = "@nimbuslab/cli"
|
|
8
|
-
const CURRENT_VERSION = "0.
|
|
8
|
+
const CURRENT_VERSION = "0.7.0"
|
|
9
9
|
|
|
10
10
|
const LOGO = `
|
|
11
11
|
███╗ ██╗██╗███╗ ███╗██████╗ ██╗ ██╗███████╗
|
|
@@ -44,8 +44,8 @@ function showUpdateNotice(latestVersion: string) {
|
|
|
44
44
|
const latest = latestVersion
|
|
45
45
|
const command = `bun add -g ${PACKAGE_NAME}`
|
|
46
46
|
|
|
47
|
-
const line1 = `
|
|
48
|
-
const line2 = `
|
|
47
|
+
const line1 = ` New version available: ${current} → ${latest}`
|
|
48
|
+
const line2 = ` Update with: ${command}`
|
|
49
49
|
|
|
50
50
|
const maxLen = Math.max(line1.length, line2.length)
|
|
51
51
|
const border = "─".repeat(maxLen + 2)
|
|
@@ -62,8 +62,8 @@ async function main() {
|
|
|
62
62
|
const command = args[0]
|
|
63
63
|
|
|
64
64
|
console.log(pc.cyan(LOGO))
|
|
65
|
-
console.log(pc.white(" CLI
|
|
66
|
-
console.log(pc.dim("
|
|
65
|
+
console.log(pc.white(" nimbuslab CLI"))
|
|
66
|
+
console.log(pc.dim(" Create awesome projects"))
|
|
67
67
|
console.log()
|
|
68
68
|
|
|
69
69
|
// Check for updates (non-blocking)
|
|
@@ -79,7 +79,7 @@ async function main() {
|
|
|
79
79
|
} else if (command === "version" || command === "--version" || command === "-v") {
|
|
80
80
|
showVersion()
|
|
81
81
|
} else {
|
|
82
|
-
console.log(pc.red(`
|
|
82
|
+
console.log(pc.red(`Unknown command: ${command}`))
|
|
83
83
|
showHelp()
|
|
84
84
|
process.exit(1)
|
|
85
85
|
}
|
|
@@ -87,28 +87,28 @@ async function main() {
|
|
|
87
87
|
|
|
88
88
|
function showHelp() {
|
|
89
89
|
console.log(`
|
|
90
|
-
${pc.bold("
|
|
90
|
+
${pc.bold("Usage:")} nimbus [command] [options]
|
|
91
91
|
|
|
92
|
-
${pc.bold("
|
|
93
|
-
create [
|
|
94
|
-
help
|
|
95
|
-
version
|
|
92
|
+
${pc.bold("Commands:")}
|
|
93
|
+
create [name] Create a new project
|
|
94
|
+
help Show this help
|
|
95
|
+
version Show version
|
|
96
96
|
|
|
97
97
|
${pc.bold("Templates:")}
|
|
98
98
|
--landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
|
|
99
99
|
--app Web app (Landing + Better Auth + Prisma)
|
|
100
100
|
--turborepo Monorepo (Turborepo + apps/packages)
|
|
101
101
|
|
|
102
|
-
${pc.bold("
|
|
103
|
-
-y, --yes
|
|
104
|
-
--no-git
|
|
105
|
-
--no-install
|
|
106
|
-
--template <url>
|
|
102
|
+
${pc.bold("Options:")}
|
|
103
|
+
-y, --yes Accept defaults
|
|
104
|
+
--no-git Don't initialize Git
|
|
105
|
+
--no-install Don't install dependencies
|
|
106
|
+
--template <url> Use custom template
|
|
107
107
|
|
|
108
|
-
${pc.bold("
|
|
109
|
-
${pc.dim("$")} nimbus create
|
|
110
|
-
${pc.dim("$")} nimbus create
|
|
111
|
-
${pc.dim("$")} nimbus create
|
|
108
|
+
${pc.bold("Examples:")}
|
|
109
|
+
${pc.dim("$")} nimbus create my-landing --landing
|
|
110
|
+
${pc.dim("$")} nimbus create my-app --app
|
|
111
|
+
${pc.dim("$")} nimbus create my-monorepo --turborepo
|
|
112
112
|
`)
|
|
113
113
|
}
|
|
114
114
|
|