@nimbuslab/cli 0.4.2 → 0.6.1

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.
@@ -38,3 +38,5 @@ jobs:
38
38
 
39
39
  - name: Publish to npm
40
40
  run: npm publish --access public
41
+ env:
42
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/dist/index.js CHANGED
@@ -846,17 +846,37 @@ var import_picocolors3 = __toESM(require_picocolors(), 1);
846
846
  var {$: $2 } = globalThis.Bun;
847
847
  import { rm } from "fs/promises";
848
848
  import { join } from "path";
849
- var TEMPLATES = {
849
+ var PRIVATE_TEMPLATES = {
850
850
  fast: "nimbuslab-templates/fast-template",
851
851
  "fast+": "nimbuslab-templates/fastplus-template",
852
852
  "fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template"
853
853
  };
854
+ var PUBLIC_TEMPLATES = {
855
+ landing: "nimbuslab/create-next-landing",
856
+ app: "nimbuslab/create-next-app",
857
+ turborepo: "nimbuslab/create-turborepo"
858
+ };
859
+ var TEMPLATES = { ...PRIVATE_TEMPLATES, ...PUBLIC_TEMPLATES };
860
+ var NIMBUSLAB_DOMAINS = ["@nimbuslab.com.br", "@nimbuslab.net.br"];
861
+ async function isNimbuslabMember() {
862
+ try {
863
+ const user = (await $2`git config user.name`.text()).trim();
864
+ const email = (await $2`git config user.email`.text()).trim();
865
+ const isMember = NIMBUSLAB_DOMAINS.some((domain) => email.endsWith(domain));
866
+ return { isMember, user, email };
867
+ } catch {
868
+ return { isMember: false, user: null, email: null };
869
+ }
870
+ }
854
871
  function parseFlags(args) {
855
872
  const flags = {
856
873
  yes: false,
874
+ landing: false,
875
+ app: false,
876
+ turborepo: false,
857
877
  fast: false,
858
878
  fastPlus: false,
859
- turborepo: false,
879
+ fastTurborepo: false,
860
880
  noGit: false,
861
881
  noInstall: false,
862
882
  railway: false,
@@ -868,12 +888,18 @@ function parseFlags(args) {
868
888
  const arg = args[i];
869
889
  if (arg === "-y" || arg === "--yes") {
870
890
  flags.yes = true;
891
+ } else if (arg === "--landing") {
892
+ flags.landing = true;
893
+ } else if (arg === "--app") {
894
+ flags.app = true;
895
+ } else if (arg === "--turborepo") {
896
+ flags.turborepo = true;
871
897
  } else if (arg === "--fast") {
872
898
  flags.fast = true;
873
899
  } else if (arg === "--fast-plus") {
874
900
  flags.fastPlus = true;
875
- } else if (arg === "--turborepo") {
876
- flags.turborepo = true;
901
+ } else if (arg === "--fast-turborepo") {
902
+ flags.fastTurborepo = true;
877
903
  } else if (arg === "--no-git") {
878
904
  flags.noGit = true;
879
905
  } else if (arg === "--no-install") {
@@ -981,13 +1007,14 @@ async function create(args) {
981
1007
  const { flags, projectName } = parseFlags(args);
982
1008
  Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" Novo Projeto nimbuslab ")));
983
1009
  let config;
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;
1010
+ const hasTypeFlag = flags.landing || flags.app || flags.turborepo || flags.fast || flags.fastPlus || flags.fastTurborepo;
1011
+ const typeFromFlag = flags.landing ? "landing" : flags.app ? "app" : flags.turborepo ? "turborepo" : flags.fastTurborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : null;
1012
+ const monorepoFromFlag = flags.fastTurborepo;
987
1013
  if ((flags.yes || hasTypeFlag) && projectName) {
1014
+ const defaultType = flags.landing || flags.app || flags.turborepo ? "landing" : "fast";
988
1015
  config = {
989
1016
  name: projectName,
990
- type: typeFromFlag || "fast",
1017
+ type: typeFromFlag || defaultType,
991
1018
  monorepo: monorepoFromFlag,
992
1019
  git: !flags.noGit,
993
1020
  install: !flags.noInstall,
@@ -1052,6 +1079,10 @@ async function create(args) {
1052
1079
  showNextSteps(config);
1053
1080
  }
1054
1081
  async function promptConfig(initialName, flags) {
1082
+ const { isMember, user } = await isNimbuslabMember();
1083
+ const greeting = user ? `Ola, ${user}!` : "Ola!";
1084
+ console.log(import_picocolors3.default.dim(` ${greeting}`));
1085
+ console.log();
1055
1086
  const name = await he({
1056
1087
  message: "Nome do projeto:",
1057
1088
  placeholder: "meu-projeto",
@@ -1067,23 +1098,46 @@ async function promptConfig(initialName, flags) {
1067
1098
  });
1068
1099
  if (pD(name))
1069
1100
  return name;
1101
+ const publicOptions = [
1102
+ {
1103
+ value: "landing",
1104
+ label: "Landing Page",
1105
+ hint: "Next.js 16 + Tailwind 4 + shadcn"
1106
+ },
1107
+ {
1108
+ value: "app",
1109
+ label: "Web App",
1110
+ hint: "Landing + Better Auth + Prisma"
1111
+ },
1112
+ {
1113
+ value: "turborepo",
1114
+ label: "Monorepo",
1115
+ hint: "Turborepo + apps/packages"
1116
+ }
1117
+ ];
1118
+ const privateOptions = isMember ? [
1119
+ {
1120
+ value: "fast",
1121
+ label: "fast",
1122
+ hint: "Landing page metodologia fast"
1123
+ },
1124
+ {
1125
+ value: "fast+",
1126
+ label: "fast+",
1127
+ hint: "SaaS completo"
1128
+ }
1129
+ ] : [];
1070
1130
  const type = await ve({
1071
1131
  message: "Tipo de projeto:",
1072
- options: [
1073
- {
1074
- value: "fast",
1075
- label: "fast",
1076
- hint: "Landing page em 6 dias"
1077
- },
1078
- {
1079
- value: "fast+",
1080
- label: "fast+",
1081
- hint: "SaaS completo com backend"
1082
- }
1083
- ]
1132
+ options: [...publicOptions, ...privateOptions]
1084
1133
  });
1085
1134
  if (pD(type))
1086
1135
  return type;
1136
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(type);
1137
+ if (!isMember && !isPublicTemplate) {
1138
+ console.log(import_picocolors3.default.red("Erro: Template disponivel apenas para membros nimbuslab"));
1139
+ process.exit(1);
1140
+ }
1087
1141
  let monorepo = false;
1088
1142
  if (type === "fast+") {
1089
1143
  const useMonorepo = await ye({
@@ -1145,6 +1199,33 @@ async function promptConfig(initialName, flags) {
1145
1199
  return contract;
1146
1200
  contractNumber = contract;
1147
1201
  }
1202
+ if (isPublicTemplate) {
1203
+ const install2 = await ye({
1204
+ message: "Instalar dependencias?",
1205
+ initialValue: true
1206
+ });
1207
+ if (pD(install2))
1208
+ return install2;
1209
+ return {
1210
+ name,
1211
+ type,
1212
+ monorepo: false,
1213
+ git,
1214
+ install: install2,
1215
+ github,
1216
+ githubOrg,
1217
+ githubDescription,
1218
+ contractNumber: "",
1219
+ resendApiKey: "",
1220
+ resendFromEmail: "",
1221
+ contactEmail: "",
1222
+ railwayProject: "",
1223
+ railwayToken: "",
1224
+ stagingUrl: "",
1225
+ productionUrl: "",
1226
+ customTemplate: flags?.template || null
1227
+ };
1228
+ }
1148
1229
  let resendApiKey = "";
1149
1230
  let resendFromEmail = "";
1150
1231
  let contactEmail = "";
@@ -1304,14 +1385,20 @@ async function createProject(config) {
1304
1385
  templateRepo = TEMPLATES[templateKey];
1305
1386
  templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type;
1306
1387
  }
1388
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
1307
1389
  s.start(`Clonando template ${templateLabel}...`);
1308
1390
  try {
1309
- await $2`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet();
1391
+ if (isPublicTemplate) {
1392
+ const httpsUrl = `https://github.com/${templateRepo}.git`;
1393
+ await $2`git clone --depth 1 ${httpsUrl} ${config.name}`.quiet();
1394
+ } else {
1395
+ await $2`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet();
1396
+ }
1310
1397
  await rm(join(config.name, ".git"), { recursive: true, force: true });
1311
1398
  s.stop(`Template ${templateLabel} clonado`);
1312
1399
  } catch (error) {
1313
1400
  s.stop("Erro ao clonar template");
1314
- throw new Error(`Falha ao clonar template ${templateRepo}. Verifique se tem acesso ao repositorio.`);
1401
+ throw new Error(`Falha ao clonar template ${templateRepo}. Verifique sua conexao ou acesso ao repositorio.`);
1315
1402
  }
1316
1403
  s.start("Configurando projeto...");
1317
1404
  try {
@@ -1430,6 +1517,7 @@ function generateEnvFile(config) {
1430
1517
  `;
1431
1518
  }
1432
1519
  function showNextSteps(config) {
1520
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
1433
1521
  console.log();
1434
1522
  console.log(import_picocolors3.default.bold("Proximos passos:"));
1435
1523
  console.log();
@@ -1437,7 +1525,9 @@ function showNextSteps(config) {
1437
1525
  if (!config.install) {
1438
1526
  console.log(` ${import_picocolors3.default.cyan("bun")} install`);
1439
1527
  }
1440
- console.log(` ${import_picocolors3.default.cyan("bun")} setup`);
1528
+ if (!isPublicTemplate) {
1529
+ console.log(` ${import_picocolors3.default.cyan("bun")} setup`);
1530
+ }
1441
1531
  console.log(` ${import_picocolors3.default.cyan("bun")} dev`);
1442
1532
  console.log();
1443
1533
  if (config.git) {
@@ -1466,13 +1556,18 @@ function showNextSteps(config) {
1466
1556
  console.log(import_picocolors3.default.yellow(" Dica: Configure .env manualmente ou use 'bun setup'."));
1467
1557
  console.log();
1468
1558
  }
1469
- console.log(import_picocolors3.default.dim(" Documentacao: https://github.com/nimbuslab-templates"));
1559
+ if (isPublicTemplate) {
1560
+ console.log(import_picocolors3.default.dim(" Template open source (MIT) by nimbuslab"));
1561
+ console.log(import_picocolors3.default.dim(` Documentacao: https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`));
1562
+ } else {
1563
+ console.log(import_picocolors3.default.dim(" Documentacao: https://github.com/nimbuslab-templates"));
1564
+ }
1470
1565
  console.log();
1471
1566
  }
1472
1567
 
1473
1568
  // src/index.ts
1474
1569
  var PACKAGE_NAME = "@nimbuslab/cli";
1475
- var CURRENT_VERSION = "0.4.2";
1570
+ var CURRENT_VERSION = "0.6.1";
1476
1571
  var LOGO = `
1477
1572
  \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
1478
1573
  \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
@@ -1542,29 +1637,25 @@ function showHelp() {
1542
1637
  ${import_picocolors4.default.bold("Uso:")} nimbus [comando] [opcoes]
1543
1638
 
1544
1639
  ${import_picocolors4.default.bold("Comandos:")}
1545
- create [nome] Criar novo projeto nimbuslab
1640
+ create [nome] Criar novo projeto
1546
1641
  help Mostrar esta ajuda
1547
1642
  version Mostrar versao
1548
1643
 
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)
1644
+ ${import_picocolors4.default.bold("Templates:")}
1645
+ --landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
1646
+ --app Web app (Landing + Better Auth + Prisma)
1647
+ --turborepo Monorepo (Turborepo + apps/packages)
1553
1648
 
1554
1649
  ${import_picocolors4.default.bold("Opcoes:")}
1555
1650
  -y, --yes Aceitar defaults
1556
1651
  --no-git Nao inicializar Git
1557
1652
  --no-install Nao instalar dependencias
1558
- --railway Configurar Railway automaticamente
1559
1653
  --template <url> Usar template customizado
1560
1654
 
1561
1655
  ${import_picocolors4.default.bold("Exemplos:")}
1562
- ${import_picocolors4.default.dim("$")} nimbus create meu-projeto
1563
- ${import_picocolors4.default.dim("$")} nimbus create meu-projeto -y
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
1656
+ ${import_picocolors4.default.dim("$")} nimbus create minha-landing --landing
1657
+ ${import_picocolors4.default.dim("$")} nimbus create meu-app --app
1658
+ ${import_picocolors4.default.dim("$")} nimbus create meu-monorepo --turborepo
1568
1659
  `);
1569
1660
  }
1570
1661
  function showVersion() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbuslab/cli",
3
- "version": "0.4.2",
3
+ "version": "0.6.1",
4
4
  "description": "CLI para criar projetos nimbuslab",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,11 +21,11 @@
21
21
  "private": false,
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "git+https://github.com/nimbuslab/nimbus-cli.git"
24
+ "url": "git+https://github.com/nimbuslab/cli.git"
25
25
  },
26
26
  "homepage": "https://nimbuslab.com.br",
27
27
  "bugs": {
28
- "url": "https://github.com/nimbuslab/nimbus-cli/issues"
28
+ "url": "https://github.com/nimbuslab/cli/issues"
29
29
  },
30
30
  "engines": {
31
31
  "node": ">=18"
@@ -4,16 +4,46 @@ import { $} from "bun"
4
4
  import { rm } from "node:fs/promises"
5
5
  import { join } from "node:path"
6
6
 
7
- // Templates separados por tipo
8
- const TEMPLATES = {
7
+ // Templates privados (nimbuslab-templates) - uso interno
8
+ const PRIVATE_TEMPLATES = {
9
9
  "fast": "nimbuslab-templates/fast-template",
10
10
  "fast+": "nimbuslab-templates/fastplus-template",
11
11
  "fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template",
12
12
  }
13
13
 
14
+ // Templates públicos (nimbuslab)
15
+ const PUBLIC_TEMPLATES = {
16
+ "landing": "nimbuslab/create-next-landing",
17
+ "app": "nimbuslab/create-next-app",
18
+ "turborepo": "nimbuslab/create-turborepo",
19
+ }
20
+
21
+ // Todos os templates
22
+ const TEMPLATES = { ...PRIVATE_TEMPLATES, ...PUBLIC_TEMPLATES }
23
+
24
+ // Dominios nimbuslab para deteccao de membros
25
+ const NIMBUSLAB_DOMAINS = ["@nimbuslab.com.br", "@nimbuslab.net.br"]
26
+
27
+ // Detectar se é membro da nimbuslab (verifica apenas dominio do email)
28
+ async function isNimbuslabMember(): Promise<{ isMember: boolean; user: string | null; email: string | null }> {
29
+ try {
30
+ const user = (await $`git config user.name`.text()).trim()
31
+ const email = (await $`git config user.email`.text()).trim()
32
+
33
+ // Verifica se email termina com dominio nimbuslab
34
+ const isMember = NIMBUSLAB_DOMAINS.some(domain => email.endsWith(domain))
35
+
36
+ return { isMember, user, email }
37
+ } catch {
38
+ return { isMember: false, user: null, email: null }
39
+ }
40
+ }
41
+
42
+ type ProjectType = "fast" | "fast+" | "landing" | "app" | "turborepo"
43
+
14
44
  interface ProjectConfig {
15
45
  name: string
16
- type: "fast" | "fast+"
46
+ type: ProjectType
17
47
  monorepo: boolean
18
48
  git: boolean
19
49
  install: boolean
@@ -37,9 +67,15 @@ interface ProjectConfig {
37
67
 
38
68
  interface CreateFlags {
39
69
  yes: boolean
70
+ // Templates
71
+ landing: boolean
72
+ app: boolean
73
+ turborepo: boolean
74
+ // Templates internos nimbuslab
40
75
  fast: boolean
41
76
  fastPlus: boolean
42
- turborepo: boolean
77
+ fastTurborepo: boolean
78
+ // Outros
43
79
  noGit: boolean
44
80
  noInstall: boolean
45
81
  railway: boolean
@@ -49,9 +85,12 @@ interface CreateFlags {
49
85
  function parseFlags(args: string[]): { flags: CreateFlags; projectName: string | undefined } {
50
86
  const flags: CreateFlags = {
51
87
  yes: false,
88
+ landing: false,
89
+ app: false,
90
+ turborepo: false,
52
91
  fast: false,
53
92
  fastPlus: false,
54
- turborepo: false,
93
+ fastTurborepo: false,
55
94
  noGit: false,
56
95
  noInstall: false,
57
96
  railway: false,
@@ -66,12 +105,18 @@ function parseFlags(args: string[]): { flags: CreateFlags; projectName: string |
66
105
 
67
106
  if (arg === "-y" || arg === "--yes") {
68
107
  flags.yes = true
108
+ } else if (arg === "--landing") {
109
+ flags.landing = true
110
+ } else if (arg === "--app") {
111
+ flags.app = true
112
+ } else if (arg === "--turborepo") {
113
+ flags.turborepo = true
69
114
  } else if (arg === "--fast") {
70
115
  flags.fast = true
71
116
  } else if (arg === "--fast-plus") {
72
117
  flags.fastPlus = true
73
- } else if (arg === "--turborepo") {
74
- flags.turborepo = true
118
+ } else if (arg === "--fast-turborepo") {
119
+ flags.fastTurborepo = true
75
120
  } else if (arg === "--no-git") {
76
121
  flags.noGit = true
77
122
  } else if (arg === "--no-install") {
@@ -204,15 +249,23 @@ export async function create(args: string[]) {
204
249
  let config: ProjectConfig | symbol
205
250
 
206
251
  // 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
252
+ const hasTypeFlag = flags.landing || flags.app || flags.turborepo || flags.fast || flags.fastPlus || flags.fastTurborepo
253
+ const typeFromFlag: ProjectType | null = flags.landing ? "landing"
254
+ : flags.app ? "app"
255
+ : flags.turborepo ? "turborepo"
256
+ : flags.fastTurborepo ? "fast+"
257
+ : flags.fastPlus ? "fast+"
258
+ : flags.fast ? "fast"
259
+ : null
260
+ const monorepoFromFlag = flags.fastTurborepo
210
261
 
211
262
  // Modo automatico: -y com nome OU flags de tipo com nome
212
263
  if ((flags.yes || hasTypeFlag) && projectName) {
264
+ // Templates públicos usam "landing" como default
265
+ const defaultType: ProjectType = flags.landing || flags.app || flags.turborepo ? "landing" : "fast"
213
266
  config = {
214
267
  name: projectName,
215
- type: typeFromFlag || "fast",
268
+ type: typeFromFlag || defaultType,
216
269
  monorepo: monorepoFromFlag,
217
270
  git: !flags.noGit,
218
271
  install: !flags.noInstall,
@@ -284,6 +337,14 @@ export async function create(args: string[]) {
284
337
  }
285
338
 
286
339
  async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<ProjectConfig | symbol> {
340
+ // Detectar usuario git e se é membro da nimbuslab
341
+ const { isMember, user } = await isNimbuslabMember()
342
+
343
+ // Saudacao
344
+ const greeting = user ? `Ola, ${user}!` : "Ola!"
345
+ console.log(pc.dim(` ${greeting}`))
346
+ console.log()
347
+
287
348
  const name = await p.text({
288
349
  message: "Nome do projeto:",
289
350
  placeholder: "meu-projeto",
@@ -299,24 +360,55 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
299
360
 
300
361
  if (p.isCancel(name)) return name
301
362
 
363
+ // Opções públicas (todos veem)
364
+ const publicOptions = [
365
+ {
366
+ value: "landing",
367
+ label: "Landing Page",
368
+ hint: "Next.js 16 + Tailwind 4 + shadcn",
369
+ },
370
+ {
371
+ value: "app",
372
+ label: "Web App",
373
+ hint: "Landing + Better Auth + Prisma",
374
+ },
375
+ {
376
+ value: "turborepo",
377
+ label: "Monorepo",
378
+ hint: "Turborepo + apps/packages",
379
+ },
380
+ ]
381
+
382
+ // Opções privadas (só membros nimbuslab)
383
+ const privateOptions = isMember ? [
384
+ {
385
+ value: "fast",
386
+ label: "fast",
387
+ hint: "Landing page metodologia fast",
388
+ },
389
+ {
390
+ value: "fast+",
391
+ label: "fast+",
392
+ hint: "SaaS completo",
393
+ },
394
+ ] : []
395
+
302
396
  const type = await p.select({
303
397
  message: "Tipo de projeto:",
304
- options: [
305
- {
306
- value: "fast",
307
- label: "fast",
308
- hint: "Landing page em 6 dias",
309
- },
310
- {
311
- value: "fast+",
312
- label: "fast+",
313
- hint: "SaaS completo com backend",
314
- },
315
- ],
398
+ options: [...publicOptions, ...privateOptions],
316
399
  })
317
400
 
318
401
  if (p.isCancel(type)) return type
319
402
 
403
+ // Verifica se é template público (não precisa de auth nimbuslab)
404
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(type as string)
405
+
406
+ // Se não é membro e tentou usar template privado (via flag), bloqueia
407
+ if (!isMember && !isPublicTemplate) {
408
+ console.log(pc.red("Erro: Template disponivel apenas para membros nimbuslab"))
409
+ process.exit(1)
410
+ }
411
+
320
412
  // Pergunta sobre monorepo apenas para fast+
321
413
  let monorepo = false
322
414
  if (type === "fast+") {
@@ -377,7 +469,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
377
469
  }
378
470
  }
379
471
 
380
- // M26: Número do contrato (apenas para fast)
472
+ // M26: Número do contrato (apenas para fast - privado)
381
473
  let contractNumber = ""
382
474
  if (type === "fast") {
383
475
  const contract = await p.text({
@@ -389,6 +481,36 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
389
481
  contractNumber = contract as string
390
482
  }
391
483
 
484
+ // Templates públicos têm fluxo simplificado
485
+ if (isPublicTemplate) {
486
+ const install = await p.confirm({
487
+ message: "Instalar dependencias?",
488
+ initialValue: true,
489
+ })
490
+
491
+ if (p.isCancel(install)) return install
492
+
493
+ return {
494
+ name: name as string,
495
+ type: type as ProjectType,
496
+ monorepo: false,
497
+ git: git as boolean,
498
+ install: install as boolean,
499
+ github,
500
+ githubOrg,
501
+ githubDescription,
502
+ contractNumber: "",
503
+ resendApiKey: "",
504
+ resendFromEmail: "",
505
+ contactEmail: "",
506
+ railwayProject: "",
507
+ railwayToken: "",
508
+ stagingUrl: "",
509
+ productionUrl: "",
510
+ customTemplate: flags?.template || null,
511
+ }
512
+ }
513
+
392
514
  // Configuracoes de infra (separadas)
393
515
  let resendApiKey = ""
394
516
  let resendFromEmail = ""
@@ -577,19 +699,30 @@ async function createProject(config: ProjectConfig) {
577
699
  templateRepo = config.customTemplate
578
700
  templateLabel = `customizado (${config.customTemplate})`
579
701
  } else {
702
+ // fast+ com monorepo usa template específico
580
703
  const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type
581
- templateRepo = TEMPLATES[templateKey]
704
+ templateRepo = TEMPLATES[templateKey as keyof typeof TEMPLATES]
582
705
  templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type
583
706
  }
584
707
 
708
+ // Verifica se é template público
709
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type)
710
+
585
711
  s.start(`Clonando template ${templateLabel}...`)
586
712
  try {
587
- await $`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet()
713
+ if (isPublicTemplate) {
714
+ // Templates públicos: usa HTTPS (não precisa de auth)
715
+ const httpsUrl = `https://github.com/${templateRepo}.git`
716
+ await $`git clone --depth 1 ${httpsUrl} ${config.name}`.quiet()
717
+ } else {
718
+ // Templates privados: usa gh (precisa de auth)
719
+ await $`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet()
720
+ }
588
721
  await rm(join(config.name, ".git"), { recursive: true, force: true })
589
722
  s.stop(`Template ${templateLabel} clonado`)
590
723
  } catch (error) {
591
724
  s.stop("Erro ao clonar template")
592
- throw new Error(`Falha ao clonar template ${templateRepo}. Verifique se tem acesso ao repositorio.`)
725
+ throw new Error(`Falha ao clonar template ${templateRepo}. Verifique sua conexao ou acesso ao repositorio.`)
593
726
  }
594
727
 
595
728
  // Update package.json
@@ -743,6 +876,8 @@ function generateEnvFile(config: ProjectConfig): string {
743
876
  }
744
877
 
745
878
  function showNextSteps(config: ProjectConfig) {
879
+ const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type)
880
+
746
881
  console.log()
747
882
  console.log(pc.bold("Proximos passos:"))
748
883
  console.log()
@@ -752,7 +887,10 @@ function showNextSteps(config: ProjectConfig) {
752
887
  console.log(` ${pc.cyan("bun")} install`)
753
888
  }
754
889
 
755
- console.log(` ${pc.cyan("bun")} setup`)
890
+ // Templates públicos não têm bun setup
891
+ if (!isPublicTemplate) {
892
+ console.log(` ${pc.cyan("bun")} setup`)
893
+ }
756
894
  console.log(` ${pc.cyan("bun")} dev`)
757
895
  console.log()
758
896
 
@@ -791,6 +929,12 @@ function showNextSteps(config: ProjectConfig) {
791
929
  console.log()
792
930
  }
793
931
 
794
- console.log(pc.dim(" Documentacao: https://github.com/nimbuslab-templates"))
932
+ // Info sobre templates públicos
933
+ if (isPublicTemplate) {
934
+ console.log(pc.dim(" Template open source (MIT) by nimbuslab"))
935
+ console.log(pc.dim(` Documentacao: https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`))
936
+ } else {
937
+ console.log(pc.dim(" Documentacao: https://github.com/nimbuslab-templates"))
938
+ }
795
939
  console.log()
796
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.4.2"
8
+ const CURRENT_VERSION = "0.6.1"
9
9
 
10
10
  const LOGO = `
11
11
  ███╗ ██╗██╗███╗ ███╗██████╗ ██╗ ██╗███████╗
@@ -90,29 +90,25 @@ function showHelp() {
90
90
  ${pc.bold("Uso:")} nimbus [comando] [opcoes]
91
91
 
92
92
  ${pc.bold("Comandos:")}
93
- create [nome] Criar novo projeto nimbuslab
93
+ create [nome] Criar novo projeto
94
94
  help Mostrar esta ajuda
95
95
  version Mostrar versao
96
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)
97
+ ${pc.bold("Templates:")}
98
+ --landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
99
+ --app Web app (Landing + Better Auth + Prisma)
100
+ --turborepo Monorepo (Turborepo + apps/packages)
101
101
 
102
102
  ${pc.bold("Opcoes:")}
103
103
  -y, --yes Aceitar defaults
104
104
  --no-git Nao inicializar Git
105
105
  --no-install Nao instalar dependencias
106
- --railway Configurar Railway automaticamente
107
106
  --template <url> Usar template customizado
108
107
 
109
108
  ${pc.bold("Exemplos:")}
110
- ${pc.dim("$")} nimbus create meu-projeto
111
- ${pc.dim("$")} nimbus create meu-projeto -y
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
109
+ ${pc.dim("$")} nimbus create minha-landing --landing
110
+ ${pc.dim("$")} nimbus create meu-app --app
111
+ ${pc.dim("$")} nimbus create meu-monorepo --turborepo
116
112
  `)
117
113
  }
118
114