@nimbuslab/cli 0.3.5 → 0.4.2

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/README.md CHANGED
@@ -37,12 +37,49 @@ nimbus help
37
37
  | `help` | Mostrar ajuda |
38
38
  | `version` | Mostrar versao |
39
39
 
40
+ ## Flags
41
+
42
+ ### Tipo de projeto
43
+
44
+ | Flag | Descricao |
45
+ |------|-----------|
46
+ | `--fast` | Landing page (template fast) |
47
+ | `--fast-plus` | SaaS single-repo (template fast+) |
48
+ | `--turborepo` | SaaS monorepo (template fast+ turborepo) |
49
+
50
+ ### Opcoes
51
+
52
+ | Flag | Descricao |
53
+ |------|-----------|
54
+ | `-y, --yes` | Aceitar defaults |
55
+ | `--no-git` | Nao inicializar Git |
56
+ | `--no-install` | Nao instalar dependencias |
57
+ | `--railway` | Configurar Railway automaticamente |
58
+ | `--template <url>` | Usar template customizado |
59
+
60
+ ### Exemplos
61
+
62
+ ```bash
63
+ # Landing page rapida
64
+ nimbus create meu-site --fast
65
+
66
+ # SaaS com Railway
67
+ nimbus create meu-saas --fast-plus --railway
68
+
69
+ # Monorepo sem instalar deps
70
+ nimbus create meu-app --turborepo --no-install
71
+
72
+ # Template customizado
73
+ nimbus create projeto --template usuario/repositorio
74
+ ```
75
+
40
76
  ## Tipos de Projeto
41
77
 
42
78
  | Tipo | Descricao |
43
79
  |------|-----------|
44
80
  | `fast` | Landing page em 6 dias |
45
81
  | `fast+` | SaaS completo com backend |
82
+ | `fast+ (monorepo)` | SaaS com Turborepo |
46
83
 
47
84
  ## Requisitos
48
85
 
package/dist/index.js CHANGED
@@ -851,6 +851,45 @@ var TEMPLATES = {
851
851
  "fast+": "nimbuslab-templates/fastplus-template",
852
852
  "fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template"
853
853
  };
854
+ function parseFlags(args) {
855
+ const flags = {
856
+ yes: false,
857
+ fast: false,
858
+ fastPlus: false,
859
+ turborepo: false,
860
+ noGit: false,
861
+ noInstall: false,
862
+ railway: false,
863
+ template: null
864
+ };
865
+ let projectName;
866
+ let i = 0;
867
+ while (i < args.length) {
868
+ const arg = args[i];
869
+ if (arg === "-y" || arg === "--yes") {
870
+ flags.yes = true;
871
+ } else if (arg === "--fast") {
872
+ flags.fast = true;
873
+ } else if (arg === "--fast-plus") {
874
+ flags.fastPlus = true;
875
+ } else if (arg === "--turborepo") {
876
+ flags.turborepo = true;
877
+ } else if (arg === "--no-git") {
878
+ flags.noGit = true;
879
+ } else if (arg === "--no-install") {
880
+ flags.noInstall = true;
881
+ } else if (arg === "--railway") {
882
+ flags.railway = true;
883
+ } else if (arg === "--template") {
884
+ i++;
885
+ flags.template = args[i] ?? null;
886
+ } else if (!arg.startsWith("-")) {
887
+ projectName = arg;
888
+ }
889
+ i++;
890
+ }
891
+ return { flags, projectName };
892
+ }
854
893
  async function ensureRailwayCli() {
855
894
  const checkCmd = process.platform === "win32" ? "where" : "which";
856
895
  const hasRailway = await $2`${checkCmd} railway`.quiet().then(() => true).catch(() => false);
@@ -939,17 +978,19 @@ async function create(args) {
939
978
  console.log();
940
979
  }
941
980
  }
942
- const hasYes = args.includes("-y") || args.includes("--yes");
943
- const projectName = args.find((a) => !a.startsWith("-"));
981
+ const { flags, projectName } = parseFlags(args);
944
982
  Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" Novo Projeto nimbuslab ")));
945
983
  let config;
946
- if (hasYes && projectName) {
984
+ const hasTypeFlag = flags.fast || flags.fastPlus || flags.turborepo;
985
+ const typeFromFlag = flags.turborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : null;
986
+ const monorepoFromFlag = flags.turborepo;
987
+ if ((flags.yes || hasTypeFlag) && projectName) {
947
988
  config = {
948
989
  name: projectName,
949
- type: "fast",
950
- monorepo: false,
951
- git: true,
952
- install: true,
990
+ type: typeFromFlag || "fast",
991
+ monorepo: monorepoFromFlag,
992
+ git: !flags.noGit,
993
+ install: !flags.noInstall,
953
994
  github: false,
954
995
  githubOrg: null,
955
996
  githubDescription: "",
@@ -960,17 +1001,47 @@ async function create(args) {
960
1001
  railwayProject: "",
961
1002
  railwayToken: "",
962
1003
  stagingUrl: "",
963
- productionUrl: ""
1004
+ productionUrl: "",
1005
+ customTemplate: flags.template
964
1006
  };
1007
+ const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type;
965
1008
  console.log(import_picocolors3.default.dim(` Projeto: ${projectName}`));
966
- console.log(import_picocolors3.default.dim(` Tipo: fast`));
967
- console.log(import_picocolors3.default.dim(` Git: sim`));
968
- console.log(import_picocolors3.default.dim(` GitHub: nao`));
969
- console.log(import_picocolors3.default.dim(` Infra: configurar depois`));
970
- console.log(import_picocolors3.default.dim(` Instalar: sim`));
1009
+ console.log(import_picocolors3.default.dim(` Tipo: ${typeLabel}`));
1010
+ console.log(import_picocolors3.default.dim(` Git: ${config.git ? "sim" : "nao"}`));
1011
+ console.log(import_picocolors3.default.dim(` Instalar: ${config.install ? "sim" : "nao"}`));
1012
+ if (flags.railway)
1013
+ console.log(import_picocolors3.default.dim(` Railway: configurar`));
1014
+ if (flags.template)
1015
+ console.log(import_picocolors3.default.dim(` Template: ${flags.template}`));
971
1016
  console.log();
1017
+ if (flags.railway) {
1018
+ const railwayAuthenticated = await isRailwayAuthenticated();
1019
+ if (railwayAuthenticated) {
1020
+ if (config.type === "fast") {
1021
+ const projects = await listRailwayProjects();
1022
+ const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
1023
+ if (fastProject) {
1024
+ config.railwayProject = fastProject;
1025
+ console.log(import_picocolors3.default.green(` Railway: ${fastProject}`));
1026
+ }
1027
+ } else {
1028
+ console.log(import_picocolors3.default.dim(` Criando projeto Railway: ${projectName}...`));
1029
+ try {
1030
+ const result = await $2`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text();
1031
+ const newProject = JSON.parse(result);
1032
+ config.railwayProject = newProject.name || projectName;
1033
+ console.log(import_picocolors3.default.green(` Railway: ${config.railwayProject} criado`));
1034
+ } catch {
1035
+ console.log(import_picocolors3.default.yellow(` Railway: erro ao criar projeto`));
1036
+ }
1037
+ }
1038
+ } else {
1039
+ console.log(import_picocolors3.default.yellow(` Railway: nao autenticado (railway login)`));
1040
+ }
1041
+ console.log();
1042
+ }
972
1043
  } else {
973
- config = await promptConfig(projectName);
1044
+ config = await promptConfig(projectName, flags);
974
1045
  }
975
1046
  if (pD(config)) {
976
1047
  xe("Operacao cancelada");
@@ -980,7 +1051,7 @@ async function create(args) {
980
1051
  Se(import_picocolors3.default.green("Projeto criado com sucesso!"));
981
1052
  showNextSteps(config);
982
1053
  }
983
- async function promptConfig(initialName) {
1054
+ async function promptConfig(initialName, flags) {
984
1055
  const name = await he({
985
1056
  message: "Nome do projeto:",
986
1057
  placeholder: "meu-projeto",
@@ -1217,14 +1288,22 @@ async function promptConfig(initialName) {
1217
1288
  railwayProject,
1218
1289
  railwayToken,
1219
1290
  stagingUrl,
1220
- productionUrl
1291
+ productionUrl,
1292
+ customTemplate: flags?.template || null
1221
1293
  };
1222
1294
  }
1223
1295
  async function createProject(config) {
1224
1296
  const s = Y2();
1225
- const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type;
1226
- const templateRepo = TEMPLATES[templateKey];
1227
- const templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type;
1297
+ let templateRepo;
1298
+ let templateLabel;
1299
+ if (config.customTemplate) {
1300
+ templateRepo = config.customTemplate;
1301
+ templateLabel = `customizado (${config.customTemplate})`;
1302
+ } else {
1303
+ const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type;
1304
+ templateRepo = TEMPLATES[templateKey];
1305
+ templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type;
1306
+ }
1228
1307
  s.start(`Clonando template ${templateLabel}...`);
1229
1308
  try {
1230
1309
  await $2`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet();
@@ -1392,6 +1471,8 @@ function showNextSteps(config) {
1392
1471
  }
1393
1472
 
1394
1473
  // src/index.ts
1474
+ var PACKAGE_NAME = "@nimbuslab/cli";
1475
+ var CURRENT_VERSION = "0.4.2";
1395
1476
  var LOGO = `
1396
1477
  \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
1397
1478
  \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
@@ -1399,6 +1480,40 @@ var LOGO = `
1399
1480
  \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551
1400
1481
  \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551
1401
1482
  \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D`;
1483
+ async function checkForUpdates() {
1484
+ try {
1485
+ const controller = new AbortController;
1486
+ const timeout = setTimeout(() => controller.abort(), 3000);
1487
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
1488
+ signal: controller.signal
1489
+ });
1490
+ clearTimeout(timeout);
1491
+ if (!res.ok)
1492
+ return null;
1493
+ const data = await res.json();
1494
+ const latestVersion = data.version;
1495
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
1496
+ return latestVersion;
1497
+ }
1498
+ return null;
1499
+ } catch {
1500
+ return null;
1501
+ }
1502
+ }
1503
+ function showUpdateNotice(latestVersion) {
1504
+ const current = CURRENT_VERSION;
1505
+ const latest = latestVersion;
1506
+ const command = `bun add -g ${PACKAGE_NAME}`;
1507
+ const line1 = ` Nova versao disponivel: ${current} \u2192 ${latest}`;
1508
+ const line2 = ` Atualize com: ${command}`;
1509
+ const maxLen = Math.max(line1.length, line2.length);
1510
+ const border = "\u2500".repeat(maxLen + 2);
1511
+ console.log(import_picocolors4.default.yellow(` \u250C${border}\u2510`));
1512
+ console.log(import_picocolors4.default.yellow(` \u2502`) + import_picocolors4.default.white(line1.padEnd(maxLen + 1)) + import_picocolors4.default.yellow(`\u2502`));
1513
+ console.log(import_picocolors4.default.yellow(` \u2502`) + import_picocolors4.default.cyan(line2.padEnd(maxLen + 1)) + import_picocolors4.default.yellow(`\u2502`));
1514
+ console.log(import_picocolors4.default.yellow(` \u2514${border}\u2518`));
1515
+ console.log();
1516
+ }
1402
1517
  async function main() {
1403
1518
  const args = process.argv.slice(2);
1404
1519
  const command = args[0];
@@ -1406,6 +1521,10 @@ async function main() {
1406
1521
  console.log(import_picocolors4.default.white(" CLI da nimbuslab"));
1407
1522
  console.log(import_picocolors4.default.dim(" Crie projetos incriveis"));
1408
1523
  console.log();
1524
+ const latestVersion = await checkForUpdates();
1525
+ if (latestVersion) {
1526
+ showUpdateNotice(latestVersion);
1527
+ }
1409
1528
  if (!command || command === "create") {
1410
1529
  await create(args.slice(1));
1411
1530
  } else if (command === "help" || command === "--help" || command === "-h") {
@@ -1427,17 +1546,29 @@ ${import_picocolors4.default.bold("Comandos:")}
1427
1546
  help Mostrar esta ajuda
1428
1547
  version Mostrar versao
1429
1548
 
1549
+ ${import_picocolors4.default.bold("Tipo de projeto:")}
1550
+ --fast Landing page (template fast)
1551
+ --fast-plus SaaS single-repo (template fast+)
1552
+ --turborepo SaaS monorepo (template fast+ turborepo)
1553
+
1430
1554
  ${import_picocolors4.default.bold("Opcoes:")}
1431
- -y, --yes Aceitar defaults (fast, git, install)
1555
+ -y, --yes Aceitar defaults
1556
+ --no-git Nao inicializar Git
1557
+ --no-install Nao instalar dependencias
1558
+ --railway Configurar Railway automaticamente
1559
+ --template <url> Usar template customizado
1432
1560
 
1433
1561
  ${import_picocolors4.default.bold("Exemplos:")}
1434
1562
  ${import_picocolors4.default.dim("$")} nimbus create meu-projeto
1435
1563
  ${import_picocolors4.default.dim("$")} nimbus create meu-projeto -y
1436
- ${import_picocolors4.default.dim("$")} nimbus create
1564
+ ${import_picocolors4.default.dim("$")} nimbus create meu-projeto --fast
1565
+ ${import_picocolors4.default.dim("$")} nimbus create meu-saas --fast-plus --railway
1566
+ ${import_picocolors4.default.dim("$")} nimbus create meu-app --turborepo --no-install
1567
+ ${import_picocolors4.default.dim("$")} nimbus create custom --template user/repo
1437
1568
  `);
1438
1569
  }
1439
1570
  function showVersion() {
1440
- console.log(`@nimbuslab/cli v0.1.0`);
1571
+ console.log(`${PACKAGE_NAME} v${CURRENT_VERSION}`);
1441
1572
  }
1442
1573
  main().catch((err) => {
1443
1574
  console.error(import_picocolors4.default.red("Erro:"), err.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbuslab/cli",
3
- "version": "0.3.5",
3
+ "version": "0.4.2",
4
4
  "description": "CLI para criar projetos nimbuslab",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,6 +31,64 @@ interface ProjectConfig {
31
31
  railwayToken: string
32
32
  stagingUrl: string
33
33
  productionUrl: string
34
+ // Template customizado
35
+ customTemplate: string | null
36
+ }
37
+
38
+ interface CreateFlags {
39
+ yes: boolean
40
+ fast: boolean
41
+ fastPlus: boolean
42
+ turborepo: boolean
43
+ noGit: boolean
44
+ noInstall: boolean
45
+ railway: boolean
46
+ template: string | null
47
+ }
48
+
49
+ function parseFlags(args: string[]): { flags: CreateFlags; projectName: string | undefined } {
50
+ const flags: CreateFlags = {
51
+ yes: false,
52
+ fast: false,
53
+ fastPlus: false,
54
+ turborepo: false,
55
+ noGit: false,
56
+ noInstall: false,
57
+ railway: false,
58
+ template: null,
59
+ }
60
+
61
+ let projectName: string | undefined
62
+ let i = 0
63
+
64
+ while (i < args.length) {
65
+ const arg = args[i]!
66
+
67
+ if (arg === "-y" || arg === "--yes") {
68
+ flags.yes = true
69
+ } else if (arg === "--fast") {
70
+ flags.fast = true
71
+ } else if (arg === "--fast-plus") {
72
+ flags.fastPlus = true
73
+ } else if (arg === "--turborepo") {
74
+ flags.turborepo = true
75
+ } else if (arg === "--no-git") {
76
+ flags.noGit = true
77
+ } else if (arg === "--no-install") {
78
+ flags.noInstall = true
79
+ } else if (arg === "--railway") {
80
+ flags.railway = true
81
+ } else if (arg === "--template") {
82
+ i++
83
+ flags.template = args[i] ?? null
84
+ } else if (!arg.startsWith("-")) {
85
+ projectName = arg
86
+ }
87
+
88
+ i++
89
+ }
90
+
91
+ return { flags, projectName }
34
92
  }
35
93
 
36
94
  // M30: Verificar e instalar Railway CLI
@@ -139,21 +197,25 @@ export async function create(args: string[]) {
139
197
  }
140
198
  }
141
199
 
142
- const hasYes = args.includes("-y") || args.includes("--yes")
143
- const projectName = args.find(a => !a.startsWith("-"))
200
+ const { flags, projectName } = parseFlags(args)
144
201
 
145
202
  p.intro(pc.bgCyan(pc.black(" Novo Projeto nimbuslab ")))
146
203
 
147
204
  let config: ProjectConfig | symbol
148
205
 
149
- if (hasYes && projectName) {
150
- // Modo automatico com defaults (sem configs de infra)
206
+ // Determina tipo baseado nas flags
207
+ const hasTypeFlag = flags.fast || flags.fastPlus || flags.turborepo
208
+ const typeFromFlag = flags.turborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : null
209
+ const monorepoFromFlag = flags.turborepo
210
+
211
+ // Modo automatico: -y com nome OU flags de tipo com nome
212
+ if ((flags.yes || hasTypeFlag) && projectName) {
151
213
  config = {
152
214
  name: projectName,
153
- type: "fast",
154
- monorepo: false,
155
- git: true,
156
- install: true,
215
+ type: typeFromFlag || "fast",
216
+ monorepo: monorepoFromFlag,
217
+ git: !flags.noGit,
218
+ install: !flags.noInstall,
157
219
  github: false,
158
220
  githubOrg: null,
159
221
  githubDescription: "",
@@ -165,16 +227,48 @@ export async function create(args: string[]) {
165
227
  railwayToken: "",
166
228
  stagingUrl: "",
167
229
  productionUrl: "",
230
+ customTemplate: flags.template,
168
231
  }
232
+
233
+ const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type
169
234
  console.log(pc.dim(` Projeto: ${projectName}`))
170
- console.log(pc.dim(` Tipo: fast`))
171
- console.log(pc.dim(` Git: sim`))
172
- console.log(pc.dim(` GitHub: nao`))
173
- console.log(pc.dim(` Infra: configurar depois`))
174
- console.log(pc.dim(` Instalar: sim`))
235
+ console.log(pc.dim(` Tipo: ${typeLabel}`))
236
+ console.log(pc.dim(` Git: ${config.git ? "sim" : "nao"}`))
237
+ console.log(pc.dim(` Instalar: ${config.install ? "sim" : "nao"}`))
238
+ if (flags.railway) console.log(pc.dim(` Railway: configurar`))
239
+ if (flags.template) console.log(pc.dim(` Template: ${flags.template}`))
175
240
  console.log()
241
+
242
+ // Railway automatico se flag --railway
243
+ if (flags.railway) {
244
+ const railwayAuthenticated = await isRailwayAuthenticated()
245
+ if (railwayAuthenticated) {
246
+ if (config.type === "fast") {
247
+ const projects = await listRailwayProjects()
248
+ const fastProject = projects.find(p => p.toLowerCase().includes("fast by nimbuslab"))
249
+ if (fastProject) {
250
+ config.railwayProject = fastProject
251
+ console.log(pc.green(` Railway: ${fastProject}`))
252
+ }
253
+ } else {
254
+ // Fast+: cria projeto novo automaticamente
255
+ console.log(pc.dim(` Criando projeto Railway: ${projectName}...`))
256
+ try {
257
+ const result = await $`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text()
258
+ const newProject = JSON.parse(result)
259
+ config.railwayProject = newProject.name || projectName
260
+ console.log(pc.green(` Railway: ${config.railwayProject} criado`))
261
+ } catch {
262
+ console.log(pc.yellow(` Railway: erro ao criar projeto`))
263
+ }
264
+ }
265
+ } else {
266
+ console.log(pc.yellow(` Railway: nao autenticado (railway login)`))
267
+ }
268
+ console.log()
269
+ }
176
270
  } else {
177
- config = await promptConfig(projectName)
271
+ config = await promptConfig(projectName, flags)
178
272
  }
179
273
 
180
274
  if (p.isCancel(config)) {
@@ -189,7 +283,7 @@ export async function create(args: string[]) {
189
283
  showNextSteps(config as ProjectConfig)
190
284
  }
191
285
 
192
- async function promptConfig(initialName?: string): Promise<ProjectConfig | symbol> {
286
+ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<ProjectConfig | symbol> {
193
287
  const name = await p.text({
194
288
  message: "Nome do projeto:",
195
289
  placeholder: "meu-projeto",
@@ -468,16 +562,26 @@ async function promptConfig(initialName?: string): Promise<ProjectConfig | symbo
468
562
  railwayToken,
469
563
  stagingUrl,
470
564
  productionUrl,
565
+ customTemplate: flags?.template || null,
471
566
  }
472
567
  }
473
568
 
474
569
  async function createProject(config: ProjectConfig) {
475
570
  const s = p.spinner()
476
571
 
477
- // Clone template baseado no tipo (fast ou fast+) e monorepo
478
- const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type
479
- const templateRepo = TEMPLATES[templateKey]
480
- const templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type
572
+ // Determina template: customizado ou padrao
573
+ let templateRepo: string
574
+ let templateLabel: string
575
+
576
+ if (config.customTemplate) {
577
+ templateRepo = config.customTemplate
578
+ templateLabel = `customizado (${config.customTemplate})`
579
+ } else {
580
+ const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type
581
+ templateRepo = TEMPLATES[templateKey]
582
+ templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type
583
+ }
584
+
481
585
  s.start(`Clonando template ${templateLabel}...`)
482
586
  try {
483
587
  await $`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet()
package/src/index.ts CHANGED
@@ -4,6 +4,9 @@ import * as p from "@clack/prompts"
4
4
  import pc from "picocolors"
5
5
  import { create } from "./commands/create"
6
6
 
7
+ const PACKAGE_NAME = "@nimbuslab/cli"
8
+ const CURRENT_VERSION = "0.4.2"
9
+
7
10
  const LOGO = `
8
11
  ███╗ ██╗██╗███╗ ███╗██████╗ ██╗ ██╗███████╗
9
12
  ████╗ ██║██║████╗ ████║██╔══██╗██║ ██║██╔════╝
@@ -12,6 +15,48 @@ const LOGO = `
12
15
  ██║ ╚████║██║██║ ╚═╝ ██║██████╔╝╚██████╔╝███████║
13
16
  ╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚══════╝`
14
17
 
18
+ async function checkForUpdates(): Promise<string | null> {
19
+ try {
20
+ const controller = new AbortController()
21
+ const timeout = setTimeout(() => controller.abort(), 3000)
22
+
23
+ const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
24
+ signal: controller.signal,
25
+ })
26
+ clearTimeout(timeout)
27
+
28
+ if (!res.ok) return null
29
+
30
+ const data = await res.json() as { version?: string }
31
+ const latestVersion = data.version
32
+
33
+ if (latestVersion && latestVersion !== CURRENT_VERSION) {
34
+ return latestVersion
35
+ }
36
+ return null
37
+ } catch {
38
+ return null
39
+ }
40
+ }
41
+
42
+ function showUpdateNotice(latestVersion: string) {
43
+ const current = CURRENT_VERSION
44
+ const latest = latestVersion
45
+ const command = `bun add -g ${PACKAGE_NAME}`
46
+
47
+ const line1 = ` Nova versao disponivel: ${current} → ${latest}`
48
+ const line2 = ` Atualize com: ${command}`
49
+
50
+ const maxLen = Math.max(line1.length, line2.length)
51
+ const border = "─".repeat(maxLen + 2)
52
+
53
+ console.log(pc.yellow(` ┌${border}┐`))
54
+ console.log(pc.yellow(` │`) + pc.white(line1.padEnd(maxLen + 1)) + pc.yellow(`│`))
55
+ console.log(pc.yellow(` │`) + pc.cyan(line2.padEnd(maxLen + 1)) + pc.yellow(`│`))
56
+ console.log(pc.yellow(` └${border}┘`))
57
+ console.log()
58
+ }
59
+
15
60
  async function main() {
16
61
  const args = process.argv.slice(2)
17
62
  const command = args[0]
@@ -21,6 +66,12 @@ async function main() {
21
66
  console.log(pc.dim(" Crie projetos incriveis"))
22
67
  console.log()
23
68
 
69
+ // Check for updates (non-blocking)
70
+ const latestVersion = await checkForUpdates()
71
+ if (latestVersion) {
72
+ showUpdateNotice(latestVersion)
73
+ }
74
+
24
75
  if (!command || command === "create") {
25
76
  await create(args.slice(1))
26
77
  } else if (command === "help" || command === "--help" || command === "-h") {
@@ -43,18 +94,30 @@ ${pc.bold("Comandos:")}
43
94
  help Mostrar esta ajuda
44
95
  version Mostrar versao
45
96
 
97
+ ${pc.bold("Tipo de projeto:")}
98
+ --fast Landing page (template fast)
99
+ --fast-plus SaaS single-repo (template fast+)
100
+ --turborepo SaaS monorepo (template fast+ turborepo)
101
+
46
102
  ${pc.bold("Opcoes:")}
47
- -y, --yes Aceitar defaults (fast, git, install)
103
+ -y, --yes Aceitar defaults
104
+ --no-git Nao inicializar Git
105
+ --no-install Nao instalar dependencias
106
+ --railway Configurar Railway automaticamente
107
+ --template <url> Usar template customizado
48
108
 
49
109
  ${pc.bold("Exemplos:")}
50
110
  ${pc.dim("$")} nimbus create meu-projeto
51
111
  ${pc.dim("$")} nimbus create meu-projeto -y
52
- ${pc.dim("$")} nimbus create
112
+ ${pc.dim("$")} nimbus create meu-projeto --fast
113
+ ${pc.dim("$")} nimbus create meu-saas --fast-plus --railway
114
+ ${pc.dim("$")} nimbus create meu-app --turborepo --no-install
115
+ ${pc.dim("$")} nimbus create custom --template user/repo
53
116
  `)
54
117
  }
55
118
 
56
119
  function showVersion() {
57
- console.log(`@nimbuslab/cli v0.1.0`)
120
+ console.log(`${PACKAGE_NAME} v${CURRENT_VERSION}`)
58
121
  }
59
122
 
60
123
  main().catch((err) => {