@nimbuslab/cli 0.4.2 → 0.6.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/dist/index.js +128 -37
- package/package.json +3 -3
- package/src/commands/create.ts +173 -29
- package/src/index.ts +9 -13
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
985
|
-
const typeFromFlag = flags.turborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : null;
|
|
986
|
-
const monorepoFromFlag = flags.
|
|
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 ||
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
1570
|
+
var CURRENT_VERSION = "0.6.0";
|
|
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
|
|
1640
|
+
create [nome] Criar novo projeto
|
|
1546
1641
|
help Mostrar esta ajuda
|
|
1547
1642
|
version Mostrar versao
|
|
1548
1643
|
|
|
1549
|
-
${import_picocolors4.default.bold("
|
|
1550
|
-
--
|
|
1551
|
-
--
|
|
1552
|
-
--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
|
|
1563
|
-
${import_picocolors4.default.dim("$")} nimbus create meu-
|
|
1564
|
-
${import_picocolors4.default.dim("$")} nimbus create meu-
|
|
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.
|
|
3
|
+
"version": "0.6.0",
|
|
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/
|
|
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/
|
|
28
|
+
"url": "https://github.com/nimbuslab/cli/issues"
|
|
29
29
|
},
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=18"
|
package/src/commands/create.ts
CHANGED
|
@@ -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
|
|
8
|
-
const
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
208
|
-
const typeFromFlag
|
|
209
|
-
|
|
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 ||
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
8
|
+
const CURRENT_VERSION = "0.6.0"
|
|
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
|
|
93
|
+
create [nome] Criar novo projeto
|
|
94
94
|
help Mostrar esta ajuda
|
|
95
95
|
version Mostrar versao
|
|
96
96
|
|
|
97
|
-
${pc.bold("
|
|
98
|
-
--
|
|
99
|
-
--
|
|
100
|
-
--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
|
|
111
|
-
${pc.dim("$")} nimbus create meu-
|
|
112
|
-
${pc.dim("$")} nimbus create meu-
|
|
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
|
|