@nimbuslab/cli 0.6.3 → 0.8.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 +473 -150
- package/docs/CI-CD.md +181 -0
- package/package.json +1 -1
- package/src/commands/create.ts +513 -140
- package/src/index.ts +20 -20
package/dist/index.js
CHANGED
|
@@ -844,12 +844,133 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
844
844
|
// src/commands/create.ts
|
|
845
845
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
846
846
|
var {$: $2 } = globalThis.Bun;
|
|
847
|
-
import { rm } from "fs/promises";
|
|
847
|
+
import { rm, mkdir } from "fs/promises";
|
|
848
848
|
import { join } from "path";
|
|
849
|
+
var AI_CONFIGS = {
|
|
850
|
+
claude: {
|
|
851
|
+
filename: "CLAUDE.md",
|
|
852
|
+
content: (type) => `# ${type === "landing" ? "Landing Page" : type === "app" ? "Web App" : "Monorepo"}
|
|
853
|
+
|
|
854
|
+
## Stack
|
|
855
|
+
- Next.js 16 (App Router, Turbopack)
|
|
856
|
+
- React 19 (Server Components)
|
|
857
|
+
- TypeScript (strict)
|
|
858
|
+
- Tailwind CSS 4
|
|
859
|
+
- shadcn/ui
|
|
860
|
+
- Bun
|
|
861
|
+
${type === "app" ? `- Better Auth
|
|
862
|
+
- Drizzle + PostgreSQL` : ""}
|
|
863
|
+
|
|
864
|
+
## Commands
|
|
865
|
+
\`\`\`bash
|
|
866
|
+
bun dev # Start development
|
|
867
|
+
bun build # Production build
|
|
868
|
+
bun lint # Run ESLint
|
|
869
|
+
${type === "app" ? "bun setup # Setup database" : ""}
|
|
870
|
+
\`\`\`
|
|
871
|
+
|
|
872
|
+
## Conventions
|
|
873
|
+
- Use \`bun\` for all package operations
|
|
874
|
+
- Server Components by default
|
|
875
|
+
- Dark mode first design
|
|
876
|
+
- Use \`cn()\` for conditional classes
|
|
877
|
+
- Add components: \`bunx --bun shadcn@latest add [component]\`
|
|
878
|
+
`
|
|
879
|
+
},
|
|
880
|
+
cursor: {
|
|
881
|
+
filename: ".cursorrules",
|
|
882
|
+
content: (type) => `# Cursor Rules
|
|
883
|
+
|
|
884
|
+
Stack: Next.js 16, React 19, TypeScript, Tailwind CSS 4, shadcn/ui, Bun
|
|
885
|
+
${type === "app" ? "Auth: Better Auth | DB: Drizzle + PostgreSQL" : ""}
|
|
886
|
+
|
|
887
|
+
- Server Components by default
|
|
888
|
+
- "use client" only when needed
|
|
889
|
+
- Tailwind utility classes
|
|
890
|
+
- cn() for conditional classes
|
|
891
|
+
- Dark mode first
|
|
892
|
+
`
|
|
893
|
+
},
|
|
894
|
+
gemini: {
|
|
895
|
+
filename: ".gemini/GEMINI.md",
|
|
896
|
+
content: (type) => `# ${type === "landing" ? "Landing Page" : type === "app" ? "Web App" : "Monorepo"}
|
|
897
|
+
|
|
898
|
+
## Stack
|
|
899
|
+
- Next.js 16 (App Router, Turbopack)
|
|
900
|
+
- React 19 (Server Components)
|
|
901
|
+
- TypeScript (strict)
|
|
902
|
+
- Tailwind CSS 4
|
|
903
|
+
- shadcn/ui
|
|
904
|
+
- Bun
|
|
905
|
+
${type === "app" ? `- Better Auth
|
|
906
|
+
- Drizzle + PostgreSQL` : ""}
|
|
907
|
+
|
|
908
|
+
## Conventions
|
|
909
|
+
- Use \`bun\` for all package operations
|
|
910
|
+
- Server Components by default
|
|
911
|
+
- Dark mode first design
|
|
912
|
+
- Use \`cn()\` for conditional classes
|
|
913
|
+
`
|
|
914
|
+
},
|
|
915
|
+
copilot: {
|
|
916
|
+
filename: ".github/copilot-instructions.md",
|
|
917
|
+
content: (type) => `# GitHub Copilot Instructions
|
|
918
|
+
|
|
919
|
+
Stack: Next.js 16, React 19, TypeScript, Tailwind CSS 4, shadcn/ui, Bun
|
|
920
|
+
${type === "app" ? "Auth: Better Auth | DB: Drizzle + PostgreSQL" : ""}
|
|
921
|
+
|
|
922
|
+
## Do
|
|
923
|
+
- Use TypeScript strict mode
|
|
924
|
+
- Prefer Server Components
|
|
925
|
+
- Use Tailwind for styling
|
|
926
|
+
- Use cn() for class merging
|
|
927
|
+
|
|
928
|
+
## Don't
|
|
929
|
+
- Use CSS modules or styled-components
|
|
930
|
+
- Use class components
|
|
931
|
+
- Add unnecessary dependencies
|
|
932
|
+
`
|
|
933
|
+
},
|
|
934
|
+
windsurf: {
|
|
935
|
+
filename: ".windsurfrules",
|
|
936
|
+
content: (type) => `# Windsurf Rules
|
|
937
|
+
|
|
938
|
+
Stack: Next.js 16, React 19, TypeScript, Tailwind CSS 4, shadcn/ui, Bun
|
|
939
|
+
${type === "app" ? "Auth: Better Auth | DB: Drizzle + PostgreSQL" : ""}
|
|
940
|
+
|
|
941
|
+
- Server Components by default
|
|
942
|
+
- "use client" only when needed
|
|
943
|
+
- Tailwind utility classes
|
|
944
|
+
- cn() for conditional classes
|
|
945
|
+
- Dark mode first
|
|
946
|
+
`
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
async function checkGitHubCli() {
|
|
950
|
+
const checkCmd = process.platform === "win32" ? "where" : "which";
|
|
951
|
+
try {
|
|
952
|
+
const hasGh = await $2`${checkCmd} gh`.quiet().nothrow();
|
|
953
|
+
if (hasGh.exitCode !== 0) {
|
|
954
|
+
return { installed: false, authenticated: false, username: null, orgs: [] };
|
|
955
|
+
}
|
|
956
|
+
const authStatus = await $2`gh auth status`.quiet().nothrow();
|
|
957
|
+
if (authStatus.exitCode !== 0) {
|
|
958
|
+
return { installed: true, authenticated: false, username: null, orgs: [] };
|
|
959
|
+
}
|
|
960
|
+
const username = (await $2`gh api user --jq '.login'`.quiet().text()).trim();
|
|
961
|
+
const orgsJson = await $2`gh api user/orgs --jq '.[].login'`.quiet().text();
|
|
962
|
+
const orgs = orgsJson.trim().split(`
|
|
963
|
+
`).filter(Boolean);
|
|
964
|
+
return { installed: true, authenticated: true, username, orgs };
|
|
965
|
+
} catch {
|
|
966
|
+
return { installed: false, authenticated: false, username: null, orgs: [] };
|
|
967
|
+
}
|
|
968
|
+
}
|
|
849
969
|
var PRIVATE_TEMPLATES = {
|
|
850
970
|
fast: "nimbuslab-templates/fast-template",
|
|
851
971
|
"fast+": "nimbuslab-templates/fastplus-template",
|
|
852
|
-
"fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template"
|
|
972
|
+
"fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template",
|
|
973
|
+
"nimbus-core": "nimbuslab/nimbus-core"
|
|
853
974
|
};
|
|
854
975
|
var PUBLIC_TEMPLATES = {
|
|
855
976
|
landing: "nimbuslab/create-next-landing",
|
|
@@ -877,6 +998,7 @@ function parseFlags(args) {
|
|
|
877
998
|
fast: false,
|
|
878
999
|
fastPlus: false,
|
|
879
1000
|
fastTurborepo: false,
|
|
1001
|
+
core: false,
|
|
880
1002
|
noGit: false,
|
|
881
1003
|
noInstall: false,
|
|
882
1004
|
railway: false,
|
|
@@ -900,6 +1022,8 @@ function parseFlags(args) {
|
|
|
900
1022
|
flags.fastPlus = true;
|
|
901
1023
|
} else if (arg === "--fast-turborepo") {
|
|
902
1024
|
flags.fastTurborepo = true;
|
|
1025
|
+
} else if (arg === "--core") {
|
|
1026
|
+
flags.core = true;
|
|
903
1027
|
} else if (arg === "--no-git") {
|
|
904
1028
|
flags.noGit = true;
|
|
905
1029
|
} else if (arg === "--no-install") {
|
|
@@ -921,7 +1045,7 @@ async function ensureRailwayCli() {
|
|
|
921
1045
|
const hasRailway = await $2`${checkCmd} railway`.quiet().then(() => true).catch(() => false);
|
|
922
1046
|
if (hasRailway)
|
|
923
1047
|
return true;
|
|
924
|
-
console.log(import_picocolors3.default.yellow("Railway CLI
|
|
1048
|
+
console.log(import_picocolors3.default.yellow("Railway CLI not found. Installing..."));
|
|
925
1049
|
console.log();
|
|
926
1050
|
try {
|
|
927
1051
|
if (process.platform === "win32") {
|
|
@@ -929,11 +1053,11 @@ async function ensureRailwayCli() {
|
|
|
929
1053
|
} else {
|
|
930
1054
|
await $2`curl -fsSL https://railway.app/install.sh | sh`.quiet();
|
|
931
1055
|
}
|
|
932
|
-
console.log(import_picocolors3.default.green("Railway CLI
|
|
1056
|
+
console.log(import_picocolors3.default.green("Railway CLI installed successfully!"));
|
|
933
1057
|
return true;
|
|
934
1058
|
} catch (error) {
|
|
935
|
-
console.log(import_picocolors3.default.red("
|
|
936
|
-
console.log(import_picocolors3.default.dim("
|
|
1059
|
+
console.log(import_picocolors3.default.red("Error installing Railway CLI."));
|
|
1060
|
+
console.log(import_picocolors3.default.dim("Install manually: https://docs.railway.app/guides/cli"));
|
|
937
1061
|
return false;
|
|
938
1062
|
}
|
|
939
1063
|
}
|
|
@@ -961,8 +1085,8 @@ async function create(args) {
|
|
|
961
1085
|
const hasGit = await $2`${checkCmd} git`.quiet().then(() => true).catch(() => false);
|
|
962
1086
|
const hasGh = await $2`${checkCmd} gh`.quiet().then(() => true).catch(() => false);
|
|
963
1087
|
if (!hasBun) {
|
|
964
|
-
console.log(import_picocolors3.default.red("
|
|
965
|
-
console.log(import_picocolors3.default.dim("
|
|
1088
|
+
console.log(import_picocolors3.default.red("Error: Bun not found."));
|
|
1089
|
+
console.log(import_picocolors3.default.dim("Install from: https://bun.sh"));
|
|
966
1090
|
console.log();
|
|
967
1091
|
if (process.platform === "win32") {
|
|
968
1092
|
console.log(import_picocolors3.default.cyan('powershell -c "irm bun.sh/install.ps1 | iex"'));
|
|
@@ -973,42 +1097,29 @@ async function create(args) {
|
|
|
973
1097
|
process.exit(1);
|
|
974
1098
|
}
|
|
975
1099
|
if (!hasGit) {
|
|
976
|
-
console.log(import_picocolors3.default.red("
|
|
977
|
-
console.log(import_picocolors3.default.dim("
|
|
1100
|
+
console.log(import_picocolors3.default.red("Error: Git not found."));
|
|
1101
|
+
console.log(import_picocolors3.default.dim("Install git to continue."));
|
|
978
1102
|
process.exit(1);
|
|
979
1103
|
}
|
|
980
1104
|
if (!hasGh) {
|
|
981
|
-
console.log(import_picocolors3.default.
|
|
982
|
-
console.log(import_picocolors3.default.dim("
|
|
1105
|
+
console.log(import_picocolors3.default.dim(" GitHub CLI not found (repo creation will be skipped)"));
|
|
1106
|
+
console.log(import_picocolors3.default.dim(" Install from: https://cli.github.com"));
|
|
983
1107
|
console.log();
|
|
984
|
-
if (process.platform === "win32") {
|
|
985
|
-
console.log(import_picocolors3.default.cyan("winget install GitHub.cli"));
|
|
986
|
-
} else {
|
|
987
|
-
console.log(import_picocolors3.default.cyan("sudo apt install gh # ou brew install gh"));
|
|
988
|
-
}
|
|
989
|
-
console.log();
|
|
990
|
-
process.exit(1);
|
|
991
|
-
}
|
|
992
|
-
const ghAuth = await $2`gh auth status`.quiet().then(() => true).catch(() => false);
|
|
993
|
-
if (!ghAuth) {
|
|
994
|
-
console.log(import_picocolors3.default.red("Erro: GitHub CLI nao autenticado."));
|
|
995
|
-
console.log(import_picocolors3.default.dim("Execute: gh auth login"));
|
|
996
|
-
process.exit(1);
|
|
997
1108
|
}
|
|
998
1109
|
const hasRailway = await ensureRailwayCli();
|
|
999
1110
|
if (hasRailway) {
|
|
1000
1111
|
const railwayAuth = await isRailwayAuthenticated();
|
|
1001
1112
|
if (!railwayAuth) {
|
|
1002
|
-
console.log(import_picocolors3.default.yellow("Railway CLI
|
|
1003
|
-
console.log(import_picocolors3.default.dim("
|
|
1113
|
+
console.log(import_picocolors3.default.yellow("Railway CLI not authenticated."));
|
|
1114
|
+
console.log(import_picocolors3.default.dim("Run: railway login"));
|
|
1004
1115
|
console.log();
|
|
1005
1116
|
}
|
|
1006
1117
|
}
|
|
1007
1118
|
const { flags, projectName } = parseFlags(args);
|
|
1008
|
-
Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black("
|
|
1119
|
+
Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" New nimbuslab Project ")));
|
|
1009
1120
|
let config;
|
|
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;
|
|
1121
|
+
const hasTypeFlag = flags.landing || flags.app || flags.turborepo || flags.fast || flags.fastPlus || flags.fastTurborepo || flags.core;
|
|
1122
|
+
const typeFromFlag = flags.landing ? "landing" : flags.app ? "app" : flags.turborepo ? "turborepo" : flags.fastTurborepo ? "fast+" : flags.fastPlus ? "fast+" : flags.fast ? "fast" : flags.core ? "nimbus-core" : null;
|
|
1012
1123
|
const monorepoFromFlag = flags.fastTurborepo;
|
|
1013
1124
|
if ((flags.yes || hasTypeFlag) && projectName) {
|
|
1014
1125
|
const defaultType = flags.landing || flags.app || flags.turborepo ? "landing" : "fast";
|
|
@@ -1021,6 +1132,8 @@ async function create(args) {
|
|
|
1021
1132
|
github: false,
|
|
1022
1133
|
githubOrg: null,
|
|
1023
1134
|
githubDescription: "",
|
|
1135
|
+
theme: "dark",
|
|
1136
|
+
aiAssistant: null,
|
|
1024
1137
|
contractNumber: "",
|
|
1025
1138
|
resendApiKey: "",
|
|
1026
1139
|
resendFromEmail: "",
|
|
@@ -1032,10 +1145,10 @@ async function create(args) {
|
|
|
1032
1145
|
customTemplate: flags.template
|
|
1033
1146
|
};
|
|
1034
1147
|
const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type;
|
|
1035
|
-
console.log(import_picocolors3.default.dim(`
|
|
1036
|
-
console.log(import_picocolors3.default.dim(`
|
|
1037
|
-
console.log(import_picocolors3.default.dim(` Git: ${config.git ? "
|
|
1038
|
-
console.log(import_picocolors3.default.dim(`
|
|
1148
|
+
console.log(import_picocolors3.default.dim(` Project: ${projectName}`));
|
|
1149
|
+
console.log(import_picocolors3.default.dim(` Type: ${typeLabel}`));
|
|
1150
|
+
console.log(import_picocolors3.default.dim(` Git: ${config.git ? "yes" : "no"}`));
|
|
1151
|
+
console.log(import_picocolors3.default.dim(` Install: ${config.install ? "yes" : "no"}`));
|
|
1039
1152
|
if (flags.railway)
|
|
1040
1153
|
console.log(import_picocolors3.default.dim(` Railway: configurar`));
|
|
1041
1154
|
if (flags.template)
|
|
@@ -1052,7 +1165,7 @@ async function create(args) {
|
|
|
1052
1165
|
console.log(import_picocolors3.default.green(` Railway: ${fastProject}`));
|
|
1053
1166
|
}
|
|
1054
1167
|
} else {
|
|
1055
|
-
console.log(import_picocolors3.default.dim(`
|
|
1168
|
+
console.log(import_picocolors3.default.dim(` Creating project Railway: ${projectName}...`));
|
|
1056
1169
|
try {
|
|
1057
1170
|
const result = await $2`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text();
|
|
1058
1171
|
const newProject = JSON.parse(result);
|
|
@@ -1063,7 +1176,7 @@ async function create(args) {
|
|
|
1063
1176
|
}
|
|
1064
1177
|
}
|
|
1065
1178
|
} else {
|
|
1066
|
-
console.log(import_picocolors3.default.yellow(` Railway:
|
|
1179
|
+
console.log(import_picocolors3.default.yellow(` Railway: not authenticated (railway login)`));
|
|
1067
1180
|
}
|
|
1068
1181
|
console.log();
|
|
1069
1182
|
}
|
|
@@ -1071,27 +1184,27 @@ async function create(args) {
|
|
|
1071
1184
|
config = await promptConfig(projectName, flags);
|
|
1072
1185
|
}
|
|
1073
1186
|
if (pD(config)) {
|
|
1074
|
-
xe("
|
|
1187
|
+
xe("Operation cancelled");
|
|
1075
1188
|
process.exit(0);
|
|
1076
1189
|
}
|
|
1077
1190
|
await createProject(config);
|
|
1078
|
-
Se(import_picocolors3.default.green("
|
|
1191
|
+
Se(import_picocolors3.default.green("Project created successfully!"));
|
|
1079
1192
|
showNextSteps(config);
|
|
1080
1193
|
}
|
|
1081
1194
|
async function promptConfig(initialName, flags) {
|
|
1082
1195
|
const { isMember, user } = await isNimbuslabMember();
|
|
1083
|
-
const greeting = user ? `
|
|
1196
|
+
const greeting = user ? `Hello, ${user}!` : "Hello!";
|
|
1084
1197
|
console.log(import_picocolors3.default.dim(` ${greeting}`));
|
|
1085
1198
|
console.log();
|
|
1086
1199
|
const name = await he({
|
|
1087
|
-
message: "
|
|
1200
|
+
message: "Project name:",
|
|
1088
1201
|
placeholder: "meu-projeto",
|
|
1089
1202
|
initialValue: initialName,
|
|
1090
1203
|
validate: (value) => {
|
|
1091
1204
|
if (!value)
|
|
1092
|
-
return "
|
|
1205
|
+
return "Name is required";
|
|
1093
1206
|
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
1094
|
-
return "Use
|
|
1207
|
+
return "Use only lowercase letters, numbers and hyphens";
|
|
1095
1208
|
}
|
|
1096
1209
|
return;
|
|
1097
1210
|
}
|
|
@@ -1107,7 +1220,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1107
1220
|
{
|
|
1108
1221
|
value: "app",
|
|
1109
1222
|
label: "Web App",
|
|
1110
|
-
hint: "Landing + Better Auth +
|
|
1223
|
+
hint: "Landing + Better Auth + Drizzle"
|
|
1111
1224
|
},
|
|
1112
1225
|
{
|
|
1113
1226
|
value: "turborepo",
|
|
@@ -1119,29 +1232,72 @@ async function promptConfig(initialName, flags) {
|
|
|
1119
1232
|
{
|
|
1120
1233
|
value: "fast",
|
|
1121
1234
|
label: "fast",
|
|
1122
|
-
hint: "Landing page
|
|
1235
|
+
hint: "Landing page fast methodology"
|
|
1123
1236
|
},
|
|
1124
1237
|
{
|
|
1125
1238
|
value: "fast+",
|
|
1126
1239
|
label: "fast+",
|
|
1127
|
-
hint: "SaaS
|
|
1240
|
+
hint: "Complete SaaS"
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
value: "nimbus-core",
|
|
1244
|
+
label: "nimbus-core",
|
|
1245
|
+
hint: "External projects (stealth mode)"
|
|
1128
1246
|
}
|
|
1129
1247
|
] : [];
|
|
1130
1248
|
const type = await ve({
|
|
1131
|
-
message: "
|
|
1249
|
+
message: "Project type:",
|
|
1132
1250
|
options: [...publicOptions, ...privateOptions]
|
|
1133
1251
|
});
|
|
1134
1252
|
if (pD(type))
|
|
1135
1253
|
return type;
|
|
1136
1254
|
const isPublicTemplate = ["landing", "app", "turborepo"].includes(type);
|
|
1137
1255
|
if (!isMember && !isPublicTemplate) {
|
|
1138
|
-
console.log(import_picocolors3.default.red("
|
|
1256
|
+
console.log(import_picocolors3.default.red("Error: Template available only for nimbuslab members"));
|
|
1139
1257
|
process.exit(1);
|
|
1140
1258
|
}
|
|
1259
|
+
if (type === "nimbus-core") {
|
|
1260
|
+
console.log();
|
|
1261
|
+
console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos (stealth mode)"));
|
|
1262
|
+
console.log();
|
|
1263
|
+
const createGithub = await ye({
|
|
1264
|
+
message: "Create GitHub repository? (nimbuslab, private)",
|
|
1265
|
+
initialValue: true
|
|
1266
|
+
});
|
|
1267
|
+
if (pD(createGithub))
|
|
1268
|
+
return createGithub;
|
|
1269
|
+
const clientRepo = await he({
|
|
1270
|
+
message: "Client repo URL (optional, to clone in workspace):",
|
|
1271
|
+
placeholder: "git@github.com:client/repo.git"
|
|
1272
|
+
});
|
|
1273
|
+
if (pD(clientRepo))
|
|
1274
|
+
return clientRepo;
|
|
1275
|
+
return {
|
|
1276
|
+
name,
|
|
1277
|
+
type: "nimbus-core",
|
|
1278
|
+
monorepo: false,
|
|
1279
|
+
git: true,
|
|
1280
|
+
install: false,
|
|
1281
|
+
github: createGithub,
|
|
1282
|
+
githubOrg: "nimbuslab",
|
|
1283
|
+
githubDescription: `nimbus-core for ${name} - external project`,
|
|
1284
|
+
theme: "dark",
|
|
1285
|
+
aiAssistant: null,
|
|
1286
|
+
contractNumber: "",
|
|
1287
|
+
resendApiKey: "",
|
|
1288
|
+
resendFromEmail: "",
|
|
1289
|
+
contactEmail: "",
|
|
1290
|
+
railwayProject: "",
|
|
1291
|
+
railwayToken: "",
|
|
1292
|
+
stagingUrl: "",
|
|
1293
|
+
productionUrl: "",
|
|
1294
|
+
customTemplate: clientRepo || null
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1141
1297
|
let monorepo = false;
|
|
1142
1298
|
if (type === "fast+") {
|
|
1143
1299
|
const useMonorepo = await ye({
|
|
1144
|
-
message: "
|
|
1300
|
+
message: "Use monorepo (Turborepo)?",
|
|
1145
1301
|
initialValue: false
|
|
1146
1302
|
});
|
|
1147
1303
|
if (pD(useMonorepo))
|
|
@@ -1149,7 +1305,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1149
1305
|
monorepo = useMonorepo;
|
|
1150
1306
|
}
|
|
1151
1307
|
const git = await ye({
|
|
1152
|
-
message: "
|
|
1308
|
+
message: "Initialize Git repository?",
|
|
1153
1309
|
initialValue: true
|
|
1154
1310
|
});
|
|
1155
1311
|
if (pD(git))
|
|
@@ -1159,7 +1315,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1159
1315
|
let githubDescription = "";
|
|
1160
1316
|
if (git) {
|
|
1161
1317
|
const createGithub = await ye({
|
|
1162
|
-
message: "
|
|
1318
|
+
message: "Create GitHub repository?",
|
|
1163
1319
|
initialValue: false
|
|
1164
1320
|
});
|
|
1165
1321
|
if (pD(createGithub))
|
|
@@ -1167,19 +1323,19 @@ async function promptConfig(initialName, flags) {
|
|
|
1167
1323
|
github = createGithub;
|
|
1168
1324
|
if (github) {
|
|
1169
1325
|
const org = await ve({
|
|
1170
|
-
message: "
|
|
1326
|
+
message: "GitHub organization:",
|
|
1171
1327
|
options: [
|
|
1172
|
-
{ value: "nimbuslab", label: "nimbuslab", hint: "
|
|
1173
|
-
{ value: "fast-by-nimbuslab", label: "fast-by-nimbuslab", hint: "
|
|
1328
|
+
{ value: "nimbuslab", label: "nimbuslab", hint: "Main org" },
|
|
1329
|
+
{ value: "fast-by-nimbuslab", label: "fast-by-nimbuslab", hint: "Client projects" },
|
|
1174
1330
|
{ value: "nimbuslab-templates", label: "nimbuslab-templates", hint: "Templates" },
|
|
1175
|
-
{ value: null, label: "Pessoal", hint: "
|
|
1331
|
+
{ value: null, label: "Pessoal", hint: "Personal" }
|
|
1176
1332
|
]
|
|
1177
1333
|
});
|
|
1178
1334
|
if (pD(org))
|
|
1179
1335
|
return org;
|
|
1180
1336
|
githubOrg = org;
|
|
1181
1337
|
const description = await he({
|
|
1182
|
-
message: "
|
|
1338
|
+
message: "Repository description:",
|
|
1183
1339
|
placeholder: "Landing page para cliente X",
|
|
1184
1340
|
initialValue: type === "fast" ? "Landing page fast by nimbuslab" : "SaaS fast+ by nimbuslab"
|
|
1185
1341
|
});
|
|
@@ -1191,17 +1347,77 @@ async function promptConfig(initialName, flags) {
|
|
|
1191
1347
|
let contractNumber = "";
|
|
1192
1348
|
if (type === "fast") {
|
|
1193
1349
|
const contract = await he({
|
|
1194
|
-
message: "
|
|
1350
|
+
message: "Contract number (ex: 001):",
|
|
1195
1351
|
placeholder: "001",
|
|
1196
|
-
validate: (v2) => v2 ? undefined : "
|
|
1352
|
+
validate: (v2) => v2 ? undefined : "Contract number is required for fast"
|
|
1197
1353
|
});
|
|
1198
1354
|
if (pD(contract))
|
|
1199
1355
|
return contract;
|
|
1200
1356
|
contractNumber = contract;
|
|
1201
1357
|
}
|
|
1202
1358
|
if (isPublicTemplate) {
|
|
1359
|
+
const theme = await ve({
|
|
1360
|
+
message: "Default theme:",
|
|
1361
|
+
options: [
|
|
1362
|
+
{ value: "dark", label: "Dark", hint: "recommended" },
|
|
1363
|
+
{ value: "light", label: "Light" },
|
|
1364
|
+
{ value: "system", label: "System", hint: "follows OS preference" }
|
|
1365
|
+
]
|
|
1366
|
+
});
|
|
1367
|
+
if (pD(theme))
|
|
1368
|
+
return theme;
|
|
1369
|
+
const aiAssistant = await ve({
|
|
1370
|
+
message: "Which AI assistant do you use?",
|
|
1371
|
+
options: [
|
|
1372
|
+
{ value: "claude", label: "Claude Code", hint: "Anthropic" },
|
|
1373
|
+
{ value: "cursor", label: "Cursor", hint: "AI-first editor" },
|
|
1374
|
+
{ value: "gemini", label: "Gemini CLI", hint: "Google" },
|
|
1375
|
+
{ value: "copilot", label: "GitHub Copilot" },
|
|
1376
|
+
{ value: "windsurf", label: "Windsurf", hint: "Codeium" },
|
|
1377
|
+
{ value: "none", label: "None", hint: "skip AI config" }
|
|
1378
|
+
]
|
|
1379
|
+
});
|
|
1380
|
+
if (pD(aiAssistant))
|
|
1381
|
+
return aiAssistant;
|
|
1382
|
+
let publicGithub = false;
|
|
1383
|
+
let publicGithubOrg = null;
|
|
1384
|
+
if (git) {
|
|
1385
|
+
const gh = await checkGitHubCli();
|
|
1386
|
+
if (gh.installed && gh.authenticated) {
|
|
1387
|
+
const createRepo = await ye({
|
|
1388
|
+
message: "Create GitHub repository?",
|
|
1389
|
+
initialValue: false
|
|
1390
|
+
});
|
|
1391
|
+
if (pD(createRepo))
|
|
1392
|
+
return createRepo;
|
|
1393
|
+
publicGithub = createRepo;
|
|
1394
|
+
if (publicGithub) {
|
|
1395
|
+
const repoOptions = [
|
|
1396
|
+
{ value: gh.username, label: gh.username, hint: "personal account" },
|
|
1397
|
+
...gh.orgs.map((org) => ({ value: org, label: org }))
|
|
1398
|
+
];
|
|
1399
|
+
const repoOwner = await ve({
|
|
1400
|
+
message: "Where to create the repository?",
|
|
1401
|
+
options: repoOptions
|
|
1402
|
+
});
|
|
1403
|
+
if (pD(repoOwner))
|
|
1404
|
+
return repoOwner;
|
|
1405
|
+
publicGithubOrg = repoOwner;
|
|
1406
|
+
const repoVisibility = await ve({
|
|
1407
|
+
message: "Repository visibility:",
|
|
1408
|
+
options: [
|
|
1409
|
+
{ value: "private", label: "Private", hint: "recommended" },
|
|
1410
|
+
{ value: "public", label: "Public" }
|
|
1411
|
+
]
|
|
1412
|
+
});
|
|
1413
|
+
if (pD(repoVisibility))
|
|
1414
|
+
return repoVisibility;
|
|
1415
|
+
githubDescription = repoVisibility;
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1203
1419
|
const install2 = await ye({
|
|
1204
|
-
message: "
|
|
1420
|
+
message: "Install dependencies?",
|
|
1205
1421
|
initialValue: true
|
|
1206
1422
|
});
|
|
1207
1423
|
if (pD(install2))
|
|
@@ -1212,9 +1428,11 @@ async function promptConfig(initialName, flags) {
|
|
|
1212
1428
|
monorepo: false,
|
|
1213
1429
|
git,
|
|
1214
1430
|
install: install2,
|
|
1215
|
-
github,
|
|
1216
|
-
githubOrg,
|
|
1431
|
+
github: publicGithub,
|
|
1432
|
+
githubOrg: publicGithubOrg,
|
|
1217
1433
|
githubDescription,
|
|
1434
|
+
theme,
|
|
1435
|
+
aiAssistant: aiAssistant === "none" ? null : aiAssistant,
|
|
1218
1436
|
contractNumber: "",
|
|
1219
1437
|
resendApiKey: "",
|
|
1220
1438
|
resendFromEmail: "",
|
|
@@ -1238,11 +1456,11 @@ async function promptConfig(initialName, flags) {
|
|
|
1238
1456
|
const defaultFromEmail = "no-reply@nimbuslab.com.br";
|
|
1239
1457
|
const defaultContactEmail = type === "fast" ? "fast@nimbuslab.com.br" : "suporte@nimbuslab.com.br";
|
|
1240
1458
|
const infraOptions = await fe({
|
|
1241
|
-
message: "
|
|
1459
|
+
message: "What do you want to configure now?",
|
|
1242
1460
|
options: [
|
|
1243
|
-
{ value: "urls", label: "URLs", hint: "staging
|
|
1244
|
-
{ value: "resend", label: "Resend", hint: "emails
|
|
1245
|
-
{ value: "railway", label: "Railway", hint: "deploy
|
|
1461
|
+
{ value: "urls", label: "URLs", hint: "staging and production" },
|
|
1462
|
+
{ value: "resend", label: "Resend", hint: "form emails" },
|
|
1463
|
+
{ value: "railway", label: "Railway", hint: "deploy and hosting" }
|
|
1246
1464
|
],
|
|
1247
1465
|
required: false
|
|
1248
1466
|
});
|
|
@@ -1251,9 +1469,9 @@ async function promptConfig(initialName, flags) {
|
|
|
1251
1469
|
const configItems = infraOptions;
|
|
1252
1470
|
if (configItems.includes("urls")) {
|
|
1253
1471
|
console.log();
|
|
1254
|
-
console.log(import_picocolors3.default.dim(" URLs
|
|
1472
|
+
console.log(import_picocolors3.default.dim(" Project URLs"));
|
|
1255
1473
|
const staging = await he({
|
|
1256
|
-
message: "URL
|
|
1474
|
+
message: "Staging URL:",
|
|
1257
1475
|
placeholder: defaultStagingUrl,
|
|
1258
1476
|
initialValue: defaultStagingUrl
|
|
1259
1477
|
});
|
|
@@ -1261,7 +1479,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1261
1479
|
return staging;
|
|
1262
1480
|
stagingUrl = staging;
|
|
1263
1481
|
const production = await he({
|
|
1264
|
-
message: "URL
|
|
1482
|
+
message: "Production URL:",
|
|
1265
1483
|
placeholder: defaultStagingUrl.replace(".nimbuslab.net.br", ".com.br"),
|
|
1266
1484
|
initialValue: ""
|
|
1267
1485
|
});
|
|
@@ -1280,7 +1498,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1280
1498
|
return resendKey;
|
|
1281
1499
|
resendApiKey = resendKey;
|
|
1282
1500
|
const fromEmail = await he({
|
|
1283
|
-
message: "
|
|
1501
|
+
message: "From email:",
|
|
1284
1502
|
placeholder: defaultFromEmail,
|
|
1285
1503
|
initialValue: defaultFromEmail
|
|
1286
1504
|
});
|
|
@@ -1288,7 +1506,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1288
1506
|
return fromEmail;
|
|
1289
1507
|
resendFromEmail = fromEmail;
|
|
1290
1508
|
const contact = await he({
|
|
1291
|
-
message: "
|
|
1509
|
+
message: "Contact email (receives forms):",
|
|
1292
1510
|
placeholder: defaultContactEmail,
|
|
1293
1511
|
initialValue: defaultContactEmail
|
|
1294
1512
|
});
|
|
@@ -1306,49 +1524,49 @@ async function promptConfig(initialName, flags) {
|
|
|
1306
1524
|
const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
|
|
1307
1525
|
if (fastProject) {
|
|
1308
1526
|
railwayProject = fastProject;
|
|
1309
|
-
console.log(import_picocolors3.default.green(`
|
|
1527
|
+
console.log(import_picocolors3.default.green(` Project: ${fastProject} (automatico)`));
|
|
1310
1528
|
} else {
|
|
1311
|
-
console.log(import_picocolors3.default.yellow("
|
|
1312
|
-
console.log(import_picocolors3.default.dim(" Configure
|
|
1529
|
+
console.log(import_picocolors3.default.yellow(" Project 'Fast by nimbuslab' not found."));
|
|
1530
|
+
console.log(import_picocolors3.default.dim(" Configure manually in .env"));
|
|
1313
1531
|
}
|
|
1314
1532
|
} else {
|
|
1315
1533
|
const projectOptions = [
|
|
1316
1534
|
...projects.map((proj) => ({ value: proj, label: proj })),
|
|
1317
|
-
{ value: "__new__", label: "
|
|
1318
|
-
{ value: "__skip__", label: "
|
|
1535
|
+
{ value: "__new__", label: "Create new project", hint: "via railway init" },
|
|
1536
|
+
{ value: "__skip__", label: "Skip", hint: "Configure later" }
|
|
1319
1537
|
];
|
|
1320
1538
|
const selectedProject = await ve({
|
|
1321
|
-
message: "
|
|
1539
|
+
message: "Railway project for this SaaS:",
|
|
1322
1540
|
options: projectOptions
|
|
1323
1541
|
});
|
|
1324
1542
|
if (pD(selectedProject))
|
|
1325
1543
|
return selectedProject;
|
|
1326
1544
|
if (selectedProject === "__new__") {
|
|
1327
1545
|
const projectNameForRailway = name;
|
|
1328
|
-
console.log(import_picocolors3.default.dim(`
|
|
1546
|
+
console.log(import_picocolors3.default.dim(` Creating project "${projectNameForRailway}" on Railway...`));
|
|
1329
1547
|
try {
|
|
1330
1548
|
const result = await $2`echo "" | railway init -n ${projectNameForRailway} -w nimbuslab --json`.text();
|
|
1331
1549
|
const newProject = JSON.parse(result);
|
|
1332
1550
|
railwayProject = newProject.name || projectNameForRailway;
|
|
1333
|
-
console.log(import_picocolors3.default.green(` Projeto "${railwayProject}"
|
|
1551
|
+
console.log(import_picocolors3.default.green(` Projeto "${railwayProject}" created successfully!`));
|
|
1334
1552
|
console.log(import_picocolors3.default.dim(` ID: ${newProject.id || "N/A"}`));
|
|
1335
1553
|
} catch (error) {
|
|
1336
|
-
console.log(import_picocolors3.default.yellow("
|
|
1337
|
-
console.log(import_picocolors3.default.dim("
|
|
1554
|
+
console.log(import_picocolors3.default.yellow(" Error creating project via CLI."));
|
|
1555
|
+
console.log(import_picocolors3.default.dim(" Create manually at: https://railway.app/new"));
|
|
1338
1556
|
}
|
|
1339
1557
|
} else if (selectedProject !== "__skip__") {
|
|
1340
1558
|
railwayProject = selectedProject;
|
|
1341
|
-
console.log(import_picocolors3.default.green(`
|
|
1559
|
+
console.log(import_picocolors3.default.green(` Project selected: ${railwayProject}`));
|
|
1342
1560
|
}
|
|
1343
1561
|
}
|
|
1344
1562
|
} else {
|
|
1345
1563
|
console.log();
|
|
1346
|
-
console.log(import_picocolors3.default.yellow(" Railway:
|
|
1347
|
-
console.log(import_picocolors3.default.dim(" Configure
|
|
1564
|
+
console.log(import_picocolors3.default.yellow(" Railway: not authenticated (railway login)"));
|
|
1565
|
+
console.log(import_picocolors3.default.dim(" Configure manually in .env"));
|
|
1348
1566
|
}
|
|
1349
1567
|
}
|
|
1350
1568
|
const install = await ye({
|
|
1351
|
-
message: "
|
|
1569
|
+
message: "Install dependencies?",
|
|
1352
1570
|
initialValue: true
|
|
1353
1571
|
});
|
|
1354
1572
|
if (pD(install))
|
|
@@ -1362,6 +1580,8 @@ async function promptConfig(initialName, flags) {
|
|
|
1362
1580
|
github,
|
|
1363
1581
|
githubOrg,
|
|
1364
1582
|
githubDescription,
|
|
1583
|
+
theme: "dark",
|
|
1584
|
+
aiAssistant: null,
|
|
1365
1585
|
contractNumber,
|
|
1366
1586
|
resendApiKey,
|
|
1367
1587
|
resendFromEmail,
|
|
@@ -1386,7 +1606,7 @@ async function createProject(config) {
|
|
|
1386
1606
|
templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type;
|
|
1387
1607
|
}
|
|
1388
1608
|
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
|
|
1389
|
-
s.start(`
|
|
1609
|
+
s.start(`Cloning template ${templateLabel}...`);
|
|
1390
1610
|
try {
|
|
1391
1611
|
if (isPublicTemplate) {
|
|
1392
1612
|
const httpsUrl = `https://github.com/${templateRepo}.git`;
|
|
@@ -1395,27 +1615,71 @@ async function createProject(config) {
|
|
|
1395
1615
|
await $2`gh repo clone ${templateRepo} ${config.name} -- --depth 1`.quiet();
|
|
1396
1616
|
}
|
|
1397
1617
|
await rm(join(config.name, ".git"), { recursive: true, force: true });
|
|
1398
|
-
s.stop(`Template
|
|
1618
|
+
s.stop(`Template cloned`);
|
|
1399
1619
|
} catch (error) {
|
|
1400
|
-
s.stop("
|
|
1401
|
-
throw new Error(`
|
|
1620
|
+
s.stop("Error cloning template");
|
|
1621
|
+
throw new Error(`Failed to clone template ${templateRepo}. Check your connection or repository access.`);
|
|
1402
1622
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1623
|
+
if (config.type === "nimbus-core" && config.customTemplate) {
|
|
1624
|
+
const clientRepoUrl = config.customTemplate;
|
|
1625
|
+
s.start(`Cloning client repo in workspace...`);
|
|
1626
|
+
try {
|
|
1627
|
+
const projectName = clientRepoUrl.split("/").pop()?.replace(".git", "") || "client-project";
|
|
1628
|
+
await $2`git clone ${clientRepoUrl} ${config.name}/workspace/${projectName}`.quiet();
|
|
1629
|
+
s.stop(`Client repo cloned: workspace/${projectName}`);
|
|
1630
|
+
} catch (error) {
|
|
1631
|
+
s.stop("Error cloning client repo");
|
|
1632
|
+
console.log(import_picocolors3.default.dim(" You can clone manually: cd workspace && git clone <url>"));
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
if (config.type !== "nimbus-core") {
|
|
1636
|
+
s.start("Configuring project...");
|
|
1637
|
+
try {
|
|
1638
|
+
const pkgPath = `${config.name}/package.json`;
|
|
1639
|
+
const pkg = await Bun.file(pkgPath).json();
|
|
1640
|
+
pkg.name = config.name;
|
|
1641
|
+
await Bun.write(pkgPath, JSON.stringify(pkg, null, 2));
|
|
1642
|
+
s.stop("Project configured");
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
s.stop("Error configuring");
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
if (isPublicTemplate && config.theme) {
|
|
1648
|
+
s.start(`Setting theme to ${config.theme}...`);
|
|
1649
|
+
try {
|
|
1650
|
+
const layoutPath = `${config.name}/src/app/layout.tsx`;
|
|
1651
|
+
let layout = await Bun.file(layoutPath).text();
|
|
1652
|
+
layout = layout.replace(/defaultTheme="(dark|light|system)"/, `defaultTheme="${config.theme}"`);
|
|
1653
|
+
await Bun.write(layoutPath, layout);
|
|
1654
|
+
s.stop(`Theme set to ${config.theme}`);
|
|
1655
|
+
} catch {
|
|
1656
|
+
s.stop("Theme config skipped");
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
if (isPublicTemplate && config.aiAssistant) {
|
|
1660
|
+
const aiConfig = AI_CONFIGS[config.aiAssistant];
|
|
1661
|
+
if (aiConfig) {
|
|
1662
|
+
s.start(`Generating ${config.aiAssistant} config...`);
|
|
1663
|
+
try {
|
|
1664
|
+
const content = aiConfig.content(config.type);
|
|
1665
|
+
const filePath = `${config.name}/${aiConfig.filename}`;
|
|
1666
|
+
if (aiConfig.filename.includes("/")) {
|
|
1667
|
+
const dir = aiConfig.filename.split("/").slice(0, -1).join("/");
|
|
1668
|
+
await mkdir(`${config.name}/${dir}`, { recursive: true });
|
|
1669
|
+
}
|
|
1670
|
+
await Bun.write(filePath, content);
|
|
1671
|
+
s.stop(`${aiConfig.filename} created`);
|
|
1672
|
+
} catch {
|
|
1673
|
+
s.stop("AI config skipped");
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1412
1676
|
}
|
|
1413
1677
|
if (config.type === "fast+") {
|
|
1414
1678
|
s.start("Configurando fast+ (SaaS)...");
|
|
1415
1679
|
s.stop("Configuracao fast+ preparada");
|
|
1416
1680
|
}
|
|
1417
1681
|
if (config.git) {
|
|
1418
|
-
s.start("
|
|
1682
|
+
s.start("Initializing Git...");
|
|
1419
1683
|
try {
|
|
1420
1684
|
const cwd = config.name;
|
|
1421
1685
|
await $2`git init -b main`.cwd(cwd).quiet();
|
|
@@ -1423,27 +1687,38 @@ async function createProject(config) {
|
|
|
1423
1687
|
await $2`git commit -m "chore: setup inicial via nimbus create"`.cwd(cwd).quiet();
|
|
1424
1688
|
await $2`git checkout -b staging`.cwd(cwd).quiet();
|
|
1425
1689
|
await $2`git checkout -b develop`.cwd(cwd).quiet();
|
|
1426
|
-
s.stop("Git
|
|
1690
|
+
s.stop("Git initialized (main -> staging -> develop)");
|
|
1427
1691
|
} catch (error) {
|
|
1428
|
-
s.stop("
|
|
1692
|
+
s.stop("Error initializing Git");
|
|
1429
1693
|
}
|
|
1430
1694
|
if (config.github) {
|
|
1431
|
-
s.start("
|
|
1695
|
+
s.start("Creating GitHub repository...");
|
|
1432
1696
|
try {
|
|
1433
1697
|
const cwd = config.name;
|
|
1434
1698
|
const repoName = config.githubOrg ? `${config.githubOrg}/${config.name}` : config.name;
|
|
1435
|
-
|
|
1436
|
-
|
|
1699
|
+
let visibility;
|
|
1700
|
+
if (config.type === "nimbus-core") {
|
|
1701
|
+
visibility = "--private";
|
|
1702
|
+
} else if (isPublicTemplate) {
|
|
1703
|
+
visibility = config.githubDescription === "public" ? "--public" : "--private";
|
|
1704
|
+
} else {
|
|
1705
|
+
visibility = config.githubOrg === "fast-by-nimbuslab" ? "--private" : "--public";
|
|
1706
|
+
}
|
|
1707
|
+
if (isPublicTemplate) {
|
|
1708
|
+
await $2`gh repo create ${repoName} ${visibility} --source . --remote origin`.cwd(cwd).quiet();
|
|
1709
|
+
} else {
|
|
1710
|
+
await $2`gh repo create ${repoName} ${visibility} --description ${config.githubDescription} --source . --remote origin`.cwd(cwd).quiet();
|
|
1711
|
+
}
|
|
1437
1712
|
await $2`git checkout main`.cwd(cwd).quiet();
|
|
1438
1713
|
await $2`git push -u origin main`.cwd(cwd).quiet();
|
|
1439
1714
|
await $2`git checkout staging`.cwd(cwd).quiet();
|
|
1440
1715
|
await $2`git push -u origin staging`.cwd(cwd).quiet();
|
|
1441
1716
|
await $2`git checkout develop`.cwd(cwd).quiet();
|
|
1442
1717
|
await $2`git push -u origin develop`.cwd(cwd).quiet();
|
|
1443
|
-
s.stop(`GitHub: ${repoName}
|
|
1718
|
+
s.stop(`GitHub: ${repoName}`);
|
|
1444
1719
|
} catch (error) {
|
|
1445
|
-
s.stop("
|
|
1446
|
-
console.log(import_picocolors3.default.dim("
|
|
1720
|
+
s.stop("Error creating GitHub repository");
|
|
1721
|
+
console.log(import_picocolors3.default.dim(" You can create manually with: gh repo create"));
|
|
1447
1722
|
}
|
|
1448
1723
|
}
|
|
1449
1724
|
}
|
|
@@ -1453,8 +1728,8 @@ async function createProject(config) {
|
|
|
1453
1728
|
await $2`railway link -p ${config.railwayProject}`.cwd(config.name).quiet();
|
|
1454
1729
|
s.stop(`Railway linkado: ${config.railwayProject}`);
|
|
1455
1730
|
} catch (error) {
|
|
1456
|
-
s.stop("
|
|
1457
|
-
console.log(import_picocolors3.default.dim("
|
|
1731
|
+
s.stop("Error linking Railway");
|
|
1732
|
+
console.log(import_picocolors3.default.dim(" Run manually: railway link"));
|
|
1458
1733
|
}
|
|
1459
1734
|
}
|
|
1460
1735
|
if (config.resendApiKey || config.stagingUrl) {
|
|
@@ -1464,16 +1739,16 @@ async function createProject(config) {
|
|
|
1464
1739
|
await Bun.write(`${config.name}/.env`, envContent);
|
|
1465
1740
|
s.stop("Arquivo .env criado");
|
|
1466
1741
|
} catch (error) {
|
|
1467
|
-
s.stop("
|
|
1742
|
+
s.stop("Error creating .env");
|
|
1468
1743
|
}
|
|
1469
1744
|
}
|
|
1470
1745
|
if (config.install) {
|
|
1471
|
-
s.start("
|
|
1746
|
+
s.start("Installing dependencies (pode demorar)...");
|
|
1472
1747
|
try {
|
|
1473
1748
|
await $2`bun install`.cwd(config.name).quiet();
|
|
1474
|
-
s.stop("
|
|
1749
|
+
s.stop("Dependencies installed");
|
|
1475
1750
|
} catch (error) {
|
|
1476
|
-
s.stop("
|
|
1751
|
+
s.stop("Error installing dependencies");
|
|
1477
1752
|
}
|
|
1478
1753
|
}
|
|
1479
1754
|
}
|
|
@@ -1499,7 +1774,7 @@ function generateEnvFile(config) {
|
|
|
1499
1774
|
lines.push("");
|
|
1500
1775
|
lines.push("# Railway");
|
|
1501
1776
|
if (config.railwayProject) {
|
|
1502
|
-
lines.push(`#
|
|
1777
|
+
lines.push(`# Project: ${config.railwayProject}`);
|
|
1503
1778
|
}
|
|
1504
1779
|
lines.push(`RAILWAY_TOKEN=${config.railwayToken || "# Configure com: railway link"}`);
|
|
1505
1780
|
}
|
|
@@ -1518,56 +1793,104 @@ function generateEnvFile(config) {
|
|
|
1518
1793
|
}
|
|
1519
1794
|
function showNextSteps(config) {
|
|
1520
1795
|
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
|
|
1796
|
+
const needsSetup = config.type === "app";
|
|
1521
1797
|
console.log();
|
|
1522
|
-
console.log(import_picocolors3.default.bold("
|
|
1798
|
+
console.log(import_picocolors3.default.bold("Next steps:"));
|
|
1523
1799
|
console.log();
|
|
1524
1800
|
console.log(` ${import_picocolors3.default.cyan("cd")} ${config.name}`);
|
|
1801
|
+
if (config.type === "nimbus-core") {
|
|
1802
|
+
console.log();
|
|
1803
|
+
console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos"));
|
|
1804
|
+
console.log();
|
|
1805
|
+
console.log(import_picocolors3.default.dim(" Para clonar repo do cliente:"));
|
|
1806
|
+
console.log(` ${import_picocolors3.default.cyan("cd")} workspace`);
|
|
1807
|
+
console.log(` ${import_picocolors3.default.cyan("git clone")} <repo-do-cliente>`);
|
|
1808
|
+
console.log();
|
|
1809
|
+
console.log(import_picocolors3.default.dim(" Para usar a Lola:"));
|
|
1810
|
+
console.log(` ${import_picocolors3.default.cyan("gemini")} ${import_picocolors3.default.dim("# Gemini CLI")}`);
|
|
1811
|
+
console.log(` ${import_picocolors3.default.cyan("claude --append-system-prompt-file .claude/agents/lola.md")}`);
|
|
1812
|
+
console.log();
|
|
1813
|
+
console.log(import_picocolors3.default.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"));
|
|
1814
|
+
console.log();
|
|
1815
|
+
if (config.github) {
|
|
1816
|
+
const repoUrl = `https://github.com/nimbuslab/${config.name}`;
|
|
1817
|
+
console.log(import_picocolors3.default.green(` GitHub (private): ${repoUrl}`));
|
|
1818
|
+
console.log();
|
|
1819
|
+
}
|
|
1820
|
+
console.log(import_picocolors3.default.dim(" Docs: See README.md for full instructions"));
|
|
1821
|
+
console.log();
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1525
1824
|
if (!config.install) {
|
|
1526
1825
|
console.log(` ${import_picocolors3.default.cyan("bun")} install`);
|
|
1527
1826
|
}
|
|
1528
|
-
if (!isPublicTemplate) {
|
|
1827
|
+
if (!isPublicTemplate || needsSetup) {
|
|
1529
1828
|
console.log(` ${import_picocolors3.default.cyan("bun")} setup`);
|
|
1530
1829
|
}
|
|
1531
1830
|
console.log(` ${import_picocolors3.default.cyan("bun")} dev`);
|
|
1532
1831
|
console.log();
|
|
1533
|
-
if (
|
|
1534
|
-
console.log(import_picocolors3.default.dim("
|
|
1832
|
+
if (needsSetup && isPublicTemplate) {
|
|
1833
|
+
console.log(import_picocolors3.default.dim(" bun setup will:"));
|
|
1834
|
+
console.log(import_picocolors3.default.dim(" - Start PostgreSQL with Docker"));
|
|
1835
|
+
console.log(import_picocolors3.default.dim(" - Run database migrations"));
|
|
1836
|
+
console.log(import_picocolors3.default.dim(" - Create demo user (demo@example.com / demo1234)"));
|
|
1535
1837
|
console.log();
|
|
1838
|
+
}
|
|
1839
|
+
if (config.git) {
|
|
1840
|
+
console.log(import_picocolors3.default.dim(" Git: main -> staging -> develop (current branch)"));
|
|
1536
1841
|
if (config.github) {
|
|
1537
1842
|
const repoUrl = config.githubOrg ? `https://github.com/${config.githubOrg}/${config.name}` : `https://github.com/${config.name}`;
|
|
1538
1843
|
console.log(import_picocolors3.default.green(` GitHub: ${repoUrl}`));
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1844
|
+
}
|
|
1845
|
+
console.log();
|
|
1846
|
+
}
|
|
1847
|
+
if (isPublicTemplate) {
|
|
1848
|
+
if (config.theme !== "dark") {
|
|
1849
|
+
console.log(import_picocolors3.default.dim(` Theme: ${config.theme}`));
|
|
1850
|
+
}
|
|
1851
|
+
if (config.aiAssistant) {
|
|
1852
|
+
const aiConfig = AI_CONFIGS[config.aiAssistant];
|
|
1853
|
+
if (aiConfig) {
|
|
1854
|
+
console.log(import_picocolors3.default.dim(` AI config: ${aiConfig.filename}`));
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
if (config.theme !== "dark" || config.aiAssistant) {
|
|
1542
1858
|
console.log();
|
|
1543
1859
|
}
|
|
1544
1860
|
}
|
|
1545
1861
|
if (config.type === "fast+") {
|
|
1546
|
-
console.log(import_picocolors3.default.dim("
|
|
1862
|
+
console.log(import_picocolors3.default.dim(" bun setup will:"));
|
|
1863
|
+
console.log(import_picocolors3.default.dim(" - Start PostgreSQL with Docker"));
|
|
1864
|
+
console.log(import_picocolors3.default.dim(" - Run database migrations"));
|
|
1865
|
+
console.log(import_picocolors3.default.dim(" - Create demo user (demo@example.com / demo1234)"));
|
|
1866
|
+
console.log();
|
|
1867
|
+
console.log(import_picocolors3.default.dim(" Tip: Configure DATABASE_URL and BETTER_AUTH_SECRET in .env"));
|
|
1547
1868
|
if (!config.railwayToken) {
|
|
1548
|
-
console.log(import_picocolors3.default.dim(" Railway:
|
|
1869
|
+
console.log(import_picocolors3.default.dim(" Railway: Create a project at https://railway.app/new"));
|
|
1549
1870
|
}
|
|
1550
1871
|
console.log();
|
|
1551
1872
|
}
|
|
1552
|
-
if (
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1873
|
+
if (!isPublicTemplate) {
|
|
1874
|
+
if (config.resendApiKey || config.stagingUrl) {
|
|
1875
|
+
console.log(import_picocolors3.default.green(" .env configured!"));
|
|
1876
|
+
console.log();
|
|
1877
|
+
} else {
|
|
1878
|
+
console.log(import_picocolors3.default.yellow(" Tip: Configure .env manually or use 'bun setup'."));
|
|
1879
|
+
console.log();
|
|
1880
|
+
}
|
|
1558
1881
|
}
|
|
1559
1882
|
if (isPublicTemplate) {
|
|
1560
|
-
console.log(import_picocolors3.default.dim("
|
|
1561
|
-
console.log(import_picocolors3.default.dim(`
|
|
1883
|
+
console.log(import_picocolors3.default.dim(" Open source template (MIT) by nimbuslab"));
|
|
1884
|
+
console.log(import_picocolors3.default.dim(` https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`));
|
|
1562
1885
|
} else {
|
|
1563
|
-
console.log(import_picocolors3.default.dim("
|
|
1886
|
+
console.log(import_picocolors3.default.dim(" https://github.com/nimbuslab-templates"));
|
|
1564
1887
|
}
|
|
1565
1888
|
console.log();
|
|
1566
1889
|
}
|
|
1567
1890
|
|
|
1568
1891
|
// src/index.ts
|
|
1569
1892
|
var PACKAGE_NAME = "@nimbuslab/cli";
|
|
1570
|
-
var CURRENT_VERSION = "0.
|
|
1893
|
+
var CURRENT_VERSION = "0.8.0";
|
|
1571
1894
|
var LOGO = `
|
|
1572
1895
|
\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
|
|
1573
1896
|
\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
|
|
@@ -1599,8 +1922,8 @@ function showUpdateNotice(latestVersion) {
|
|
|
1599
1922
|
const current = CURRENT_VERSION;
|
|
1600
1923
|
const latest = latestVersion;
|
|
1601
1924
|
const command = `bun add -g ${PACKAGE_NAME}`;
|
|
1602
|
-
const line1 = `
|
|
1603
|
-
const line2 = `
|
|
1925
|
+
const line1 = ` New version available: ${current} \u2192 ${latest}`;
|
|
1926
|
+
const line2 = ` Update with: ${command}`;
|
|
1604
1927
|
const maxLen = Math.max(line1.length, line2.length);
|
|
1605
1928
|
const border = "\u2500".repeat(maxLen + 2);
|
|
1606
1929
|
console.log(import_picocolors4.default.yellow(` \u250C${border}\u2510`));
|
|
@@ -1613,8 +1936,8 @@ async function main() {
|
|
|
1613
1936
|
const args = process.argv.slice(2);
|
|
1614
1937
|
const command = args[0];
|
|
1615
1938
|
console.log(import_picocolors4.default.cyan(LOGO));
|
|
1616
|
-
console.log(import_picocolors4.default.white(" CLI
|
|
1617
|
-
console.log(import_picocolors4.default.dim("
|
|
1939
|
+
console.log(import_picocolors4.default.white(" nimbuslab CLI"));
|
|
1940
|
+
console.log(import_picocolors4.default.dim(" Create awesome projects"));
|
|
1618
1941
|
console.log();
|
|
1619
1942
|
const latestVersion = await checkForUpdates();
|
|
1620
1943
|
if (latestVersion) {
|
|
@@ -1627,35 +1950,35 @@ async function main() {
|
|
|
1627
1950
|
} else if (command === "version" || command === "--version" || command === "-v") {
|
|
1628
1951
|
showVersion();
|
|
1629
1952
|
} else {
|
|
1630
|
-
console.log(import_picocolors4.default.red(`
|
|
1953
|
+
console.log(import_picocolors4.default.red(`Unknown command: ${command}`));
|
|
1631
1954
|
showHelp();
|
|
1632
1955
|
process.exit(1);
|
|
1633
1956
|
}
|
|
1634
1957
|
}
|
|
1635
1958
|
function showHelp() {
|
|
1636
1959
|
console.log(`
|
|
1637
|
-
${import_picocolors4.default.bold("
|
|
1960
|
+
${import_picocolors4.default.bold("Usage:")} nimbus [command] [options]
|
|
1638
1961
|
|
|
1639
|
-
${import_picocolors4.default.bold("
|
|
1640
|
-
create [
|
|
1641
|
-
help
|
|
1642
|
-
version
|
|
1962
|
+
${import_picocolors4.default.bold("Commands:")}
|
|
1963
|
+
create [name] Create a new project
|
|
1964
|
+
help Show this help
|
|
1965
|
+
version Show version
|
|
1643
1966
|
|
|
1644
1967
|
${import_picocolors4.default.bold("Templates:")}
|
|
1645
1968
|
--landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
|
|
1646
1969
|
--app Web app (Landing + Better Auth + Prisma)
|
|
1647
1970
|
--turborepo Monorepo (Turborepo + apps/packages)
|
|
1648
1971
|
|
|
1649
|
-
${import_picocolors4.default.bold("
|
|
1650
|
-
-y, --yes
|
|
1651
|
-
--no-git
|
|
1652
|
-
--no-install
|
|
1653
|
-
--template <url>
|
|
1972
|
+
${import_picocolors4.default.bold("Options:")}
|
|
1973
|
+
-y, --yes Accept defaults
|
|
1974
|
+
--no-git Don't initialize Git
|
|
1975
|
+
--no-install Don't install dependencies
|
|
1976
|
+
--template <url> Use custom template
|
|
1654
1977
|
|
|
1655
|
-
${import_picocolors4.default.bold("
|
|
1656
|
-
${import_picocolors4.default.dim("$")} nimbus create
|
|
1657
|
-
${import_picocolors4.default.dim("$")} nimbus create
|
|
1658
|
-
${import_picocolors4.default.dim("$")} nimbus create
|
|
1978
|
+
${import_picocolors4.default.bold("Examples:")}
|
|
1979
|
+
${import_picocolors4.default.dim("$")} nimbus create my-landing --landing
|
|
1980
|
+
${import_picocolors4.default.dim("$")} nimbus create my-app --app
|
|
1981
|
+
${import_picocolors4.default.dim("$")} nimbus create my-monorepo --turborepo
|
|
1659
1982
|
`);
|
|
1660
1983
|
}
|
|
1661
1984
|
function showVersion() {
|