@nimbuslab/cli 1.1.0 → 1.2.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.
- package/README.md +167 -75
- package/dist/index.js +745 -1301
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -147,7 +147,7 @@ var require_src = __commonJS((exports, module) => {
|
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
// src/index.ts
|
|
150
|
-
var
|
|
150
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
151
151
|
|
|
152
152
|
// node_modules/@clack/core/dist/index.mjs
|
|
153
153
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
@@ -526,41 +526,6 @@ class dD extends x {
|
|
|
526
526
|
}
|
|
527
527
|
var A;
|
|
528
528
|
A = new WeakMap;
|
|
529
|
-
var kD = Object.defineProperty;
|
|
530
|
-
var $D = (e, u, t) => (u in e) ? kD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
|
|
531
|
-
var H = (e, u, t) => ($D(e, typeof u != "symbol" ? u + "" : u, t), t);
|
|
532
|
-
var SD = class extends x {
|
|
533
|
-
constructor(u) {
|
|
534
|
-
super(u, false), H(this, "options"), H(this, "cursor", 0), this.options = u.options, this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: t }) => t === u.cursorAt), 0), this.on("key", (t) => {
|
|
535
|
-
t === "a" && this.toggleAll();
|
|
536
|
-
}), this.on("cursor", (t) => {
|
|
537
|
-
switch (t) {
|
|
538
|
-
case "left":
|
|
539
|
-
case "up":
|
|
540
|
-
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
541
|
-
break;
|
|
542
|
-
case "down":
|
|
543
|
-
case "right":
|
|
544
|
-
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
545
|
-
break;
|
|
546
|
-
case "space":
|
|
547
|
-
this.toggleValue();
|
|
548
|
-
break;
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
get _value() {
|
|
553
|
-
return this.options[this.cursor].value;
|
|
554
|
-
}
|
|
555
|
-
toggleAll() {
|
|
556
|
-
const u = this.value.length === this.options.length;
|
|
557
|
-
this.value = u ? [] : this.options.map((t) => t.value);
|
|
558
|
-
}
|
|
559
|
-
toggleValue() {
|
|
560
|
-
const u = this.value.includes(this._value);
|
|
561
|
-
this.value = u ? this.value.filter((t) => t !== this._value) : [...this.value, this._value];
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
529
|
var OD = Object.defineProperty;
|
|
565
530
|
var PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
|
|
566
531
|
var J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t);
|
|
@@ -732,47 +697,6 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
732
697
|
}
|
|
733
698
|
} }).prompt();
|
|
734
699
|
};
|
|
735
|
-
var fe = (t) => {
|
|
736
|
-
const n = (r2, i) => {
|
|
737
|
-
const s = r2.label ?? String(r2.value);
|
|
738
|
-
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
|
|
739
|
-
};
|
|
740
|
-
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(r2) {
|
|
741
|
-
if (this.required && r2.length === 0)
|
|
742
|
-
return `Please select at least one option.
|
|
743
|
-
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
744
|
-
}, render() {
|
|
745
|
-
const r2 = `${import_picocolors2.default.gray(o)}
|
|
746
|
-
${b2(this.state)} ${t.message}
|
|
747
|
-
`, i = (s, c) => {
|
|
748
|
-
const a = this.value.includes(s.value);
|
|
749
|
-
return c && a ? n(s, "active-selected") : a ? n(s, "selected") : n(s, c ? "active" : "inactive");
|
|
750
|
-
};
|
|
751
|
-
switch (this.state) {
|
|
752
|
-
case "submit":
|
|
753
|
-
return `${r2}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
|
|
754
|
-
case "cancel": {
|
|
755
|
-
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
756
|
-
return `${r2}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
|
|
757
|
-
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
758
|
-
}
|
|
759
|
-
case "error": {
|
|
760
|
-
const s = this.error.split(`
|
|
761
|
-
`).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
|
|
762
|
-
`);
|
|
763
|
-
return `${r2 + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
764
|
-
${import_picocolors2.default.yellow(o)} `)}
|
|
765
|
-
${s}
|
|
766
|
-
`;
|
|
767
|
-
}
|
|
768
|
-
default:
|
|
769
|
-
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
770
|
-
${import_picocolors2.default.cyan(o)} `)}
|
|
771
|
-
${import_picocolors2.default.cyan(d2)}
|
|
772
|
-
`;
|
|
773
|
-
}
|
|
774
|
-
} }).prompt();
|
|
775
|
-
};
|
|
776
700
|
var xe = (t = "") => {
|
|
777
701
|
process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(t)}
|
|
778
702
|
|
|
@@ -833,7 +757,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
833
757
|
}, R2 = (m2) => m2.replace(/\.+$/, ""), O2 = (m2) => {
|
|
834
758
|
const h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
|
|
835
759
|
return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
|
|
836
|
-
},
|
|
760
|
+
}, H = (m2 = "") => {
|
|
837
761
|
a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
838
762
|
`);
|
|
839
763
|
let h2 = 0, w2 = 0;
|
|
@@ -859,13 +783,13 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
859
783
|
`) : process.stdout.write(`${w2} ${l2}
|
|
860
784
|
`), E(), s();
|
|
861
785
|
};
|
|
862
|
-
return { start:
|
|
786
|
+
return { start: H, stop: N2, message: (m2 = "") => {
|
|
863
787
|
l2 = R2(m2 ?? l2);
|
|
864
788
|
} };
|
|
865
789
|
};
|
|
866
790
|
|
|
867
791
|
// src/commands/create.ts
|
|
868
|
-
var
|
|
792
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
869
793
|
var {$: $2 } = globalThis.Bun;
|
|
870
794
|
import { rm, mkdir } from "fs/promises";
|
|
871
795
|
import { join as join2 } from "path";
|
|
@@ -877,6 +801,7 @@ async function generateAIFriendlyDocs(projectPath, config) {
|
|
|
877
801
|
await generateLLMsFile(projectPath, config);
|
|
878
802
|
await generateArchitectureDoc(projectPath, config);
|
|
879
803
|
await generateExamplesDoc(projectPath, config);
|
|
804
|
+
await generateModificationsDoc(projectPath, config);
|
|
880
805
|
await createCompatibilitySymlinks(projectPath);
|
|
881
806
|
}
|
|
882
807
|
async function generateAgentsFile(projectPath, config) {
|
|
@@ -982,6 +907,14 @@ import type { User } from '@/types'
|
|
|
982
907
|
- Use arrow functions for components
|
|
983
908
|
- Explicit return types for exported functions
|
|
984
909
|
|
|
910
|
+
## Project Inventory
|
|
911
|
+
|
|
912
|
+
${generateProjectInventory(config)}
|
|
913
|
+
|
|
914
|
+
## Feature Dependencies
|
|
915
|
+
|
|
916
|
+
${generateFeatureDependencies(config)}
|
|
917
|
+
|
|
985
918
|
## Common Tasks
|
|
986
919
|
|
|
987
920
|
### Add a new section
|
|
@@ -998,8 +931,8 @@ ${config.features.contactForm ? `### Add form validation
|
|
|
998
931
|
\`\`\`typescript
|
|
999
932
|
// lib/validations.ts
|
|
1000
933
|
export const contactSchema = z.object({
|
|
1001
|
-
email: z.string().email('
|
|
1002
|
-
message: z.string().min(10, '
|
|
934
|
+
email: z.string().email('Invalid email'),
|
|
935
|
+
message: z.string().min(10, 'Minimum 10 characters'),
|
|
1003
936
|
})
|
|
1004
937
|
|
|
1005
938
|
// components/forms/contact-form.tsx
|
|
@@ -1094,6 +1027,7 @@ async function generateLLMsFile(projectPath, config) {
|
|
|
1094
1027
|
- [Project Overview](./AGENTS.md)
|
|
1095
1028
|
- [Architecture](./ARCHITECTURE.md)
|
|
1096
1029
|
- [Examples](./EXAMPLES.md)
|
|
1030
|
+
- [How to Modify](./MODIFICATIONS.md)
|
|
1097
1031
|
- [Contributing](./CONTRIBUTING.md)
|
|
1098
1032
|
|
|
1099
1033
|
## Quick Context
|
|
@@ -1160,7 +1094,20 @@ async function generateArchitectureDoc(projectPath, config) {
|
|
|
1160
1094
|
- Smaller bundle size
|
|
1161
1095
|
- Familiar DX
|
|
1162
1096
|
|
|
1163
|
-
${config.
|
|
1097
|
+
### 3. ${config.stack.components}
|
|
1098
|
+
|
|
1099
|
+
**Why:**
|
|
1100
|
+
- Copy-paste workflow (no lock-in)
|
|
1101
|
+
- Full control over components
|
|
1102
|
+
- Customizable without ejecting
|
|
1103
|
+
- Built on Radix UI (accessibility)
|
|
1104
|
+
|
|
1105
|
+
**Trade-offs:**
|
|
1106
|
+
- Manual updates (not auto-updated via npm)
|
|
1107
|
+
- More files in your repo
|
|
1108
|
+
- Worth it for flexibility
|
|
1109
|
+
|
|
1110
|
+
${config.type === "landing" ? `### 4. Landing Page Structure
|
|
1164
1111
|
|
|
1165
1112
|
\`\`\`
|
|
1166
1113
|
Hero
|
|
@@ -1178,7 +1125,17 @@ CTA
|
|
|
1178
1125
|
Footer
|
|
1179
1126
|
\`\`\`
|
|
1180
1127
|
|
|
1181
|
-
|
|
1128
|
+
**Why this order:**
|
|
1129
|
+
- Hero grabs attention first
|
|
1130
|
+
- Features build interest
|
|
1131
|
+
- FAQ reduces friction
|
|
1132
|
+
- CTA when ready to convert
|
|
1133
|
+
|
|
1134
|
+
` : ""}## This Project's Specific Decisions
|
|
1135
|
+
|
|
1136
|
+
${generateProjectDecisions(config)}
|
|
1137
|
+
|
|
1138
|
+
## Data Flow
|
|
1182
1139
|
|
|
1183
1140
|
\`\`\`
|
|
1184
1141
|
User Action
|
|
@@ -1260,7 +1217,7 @@ ${config.features.contactForm ? `## Form with Validation
|
|
|
1260
1217
|
// lib/validations.ts
|
|
1261
1218
|
export const contactSchema = z.object({
|
|
1262
1219
|
name: z.string().min(2, 'Nome muito curto'),
|
|
1263
|
-
email: z.string().email('
|
|
1220
|
+
email: z.string().email('Invalid email'),
|
|
1264
1221
|
message: z.string().min(10, 'Mensagem muito curta'),
|
|
1265
1222
|
})
|
|
1266
1223
|
|
|
@@ -1327,204 +1284,361 @@ export const env = envSchema.parse(process.env)
|
|
|
1327
1284
|
`;
|
|
1328
1285
|
await Bun.write(join(projectPath, "EXAMPLES.md"), content);
|
|
1329
1286
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
pricing: "Gr\xE1tis",
|
|
1352
|
-
setupUrl: "https://analytics.google.com",
|
|
1353
|
-
keyFormat: "G-XXXXXXXXXX"
|
|
1287
|
+
function generateProjectDecisions(config) {
|
|
1288
|
+
let decisions = "";
|
|
1289
|
+
if (config.stack.email) {
|
|
1290
|
+
decisions += `### Email Provider: ${config.stack.email}
|
|
1291
|
+
|
|
1292
|
+
**Why chosen:**
|
|
1293
|
+
- 3,000 emails/month free tier
|
|
1294
|
+
- React Email support (type-safe templates)
|
|
1295
|
+
- Simple API, great DX
|
|
1296
|
+
|
|
1297
|
+
**Alternatives considered:**
|
|
1298
|
+
- SendGrid: More complex, steeper pricing
|
|
1299
|
+
- Postmark: Great but no free tier
|
|
1300
|
+
- AWS SES: Requires more setup
|
|
1301
|
+
|
|
1302
|
+
**If you need to change:**
|
|
1303
|
+
1. Update \`lib/email.ts\` client
|
|
1304
|
+
2. Update env vars (\`.env\`)
|
|
1305
|
+
3. Update API route implementation
|
|
1306
|
+
|
|
1307
|
+
`;
|
|
1354
1308
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
skipSetup: true
|
|
1374
|
-
};
|
|
1309
|
+
if (config.stack.forms) {
|
|
1310
|
+
decisions += `### Form Library: ${config.stack.forms}
|
|
1311
|
+
|
|
1312
|
+
**Why chosen:**
|
|
1313
|
+
- Better performance than Formik
|
|
1314
|
+
- Smaller bundle size
|
|
1315
|
+
- Native TypeScript support
|
|
1316
|
+
- Works great with Zod
|
|
1317
|
+
|
|
1318
|
+
**Trade-off:**
|
|
1319
|
+
- More verbose than simple useState
|
|
1320
|
+
- Worth it for complex forms with validation
|
|
1321
|
+
|
|
1322
|
+
**If you need simpler forms:**
|
|
1323
|
+
- Use plain \`<form>\` + \`useState\`
|
|
1324
|
+
- Good for 1-2 field forms
|
|
1325
|
+
|
|
1326
|
+
`;
|
|
1375
1327
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
if (contactFormSetup.apiKey) {
|
|
1390
|
-
result.apiKeys.resend = contactFormSetup.apiKey;
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1328
|
+
if (config.features.contactForm) {
|
|
1329
|
+
decisions += `### Contact Form Implementation
|
|
1330
|
+
|
|
1331
|
+
**Current setup:**
|
|
1332
|
+
- Client-side validation (instant feedback)
|
|
1333
|
+
- Server-side validation (security)
|
|
1334
|
+
- Rate limiting (spam prevention)
|
|
1335
|
+
|
|
1336
|
+
**Why both validations:**
|
|
1337
|
+
- Client: Better UX (immediate feedback)
|
|
1338
|
+
- Server: Security (never trust client)
|
|
1339
|
+
|
|
1340
|
+
`;
|
|
1393
1341
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
if (analyticsSetup.trackingId) {
|
|
1398
|
-
result.apiKeys.ga = analyticsSetup.trackingId;
|
|
1399
|
-
}
|
|
1342
|
+
if (!decisions) {
|
|
1343
|
+
decisions = `No specific architectural decisions documented yet. As you make choices, document them here.
|
|
1344
|
+
`;
|
|
1400
1345
|
}
|
|
1401
|
-
return
|
|
1346
|
+
return decisions;
|
|
1402
1347
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
if (pD(needsForm) || needsForm === "no") {
|
|
1416
|
-
return { enabled: false };
|
|
1348
|
+
function generateProjectInventory(config) {
|
|
1349
|
+
let inventory = `**Implemented Components:**
|
|
1350
|
+
`;
|
|
1351
|
+
if (config.type === "landing") {
|
|
1352
|
+
inventory += `- Hero (\`components/sections/hero.tsx\`) - Main value proposition and CTA
|
|
1353
|
+
- Features (\`components/sections/features.tsx\`) - Product features grid
|
|
1354
|
+
- FAQ (\`components/sections/faq.tsx\`) - Frequently asked questions
|
|
1355
|
+
`;
|
|
1356
|
+
if (config.features.contactForm) {
|
|
1357
|
+
inventory += `- Contact Form (\`components/forms/contact-form.tsx\`) - Email contact with validation
|
|
1358
|
+
`;
|
|
1359
|
+
}
|
|
1417
1360
|
}
|
|
1418
|
-
if (
|
|
1419
|
-
|
|
1361
|
+
if (config.type === "app") {
|
|
1362
|
+
inventory += `- Dashboard Layout (\`components/dashboard/layout.tsx\`) - Main app layout
|
|
1363
|
+
- Auth Forms (\`components/auth/\`) - Login/signup components
|
|
1364
|
+
`;
|
|
1420
1365
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
return;
|
|
1428
|
-
if (!v2.startsWith(SERVICE_INFO.resend.keyPrefix)) {
|
|
1429
|
-
return `Key inv\xE1lida (deve come\xE7ar com ${SERVICE_INFO.resend.keyPrefix})`;
|
|
1430
|
-
}
|
|
1431
|
-
return;
|
|
1432
|
-
}
|
|
1433
|
-
});
|
|
1434
|
-
if (pD(apiKey)) {
|
|
1435
|
-
return { enabled: true };
|
|
1366
|
+
inventory += `
|
|
1367
|
+
**API Routes:**
|
|
1368
|
+
`;
|
|
1369
|
+
if (config.features.contactForm) {
|
|
1370
|
+
inventory += `- \`/api/contact\` - Form submission handler (rate-limited, ${config.stack.email || "email"} integration)
|
|
1371
|
+
`;
|
|
1436
1372
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1442
|
-
async function setupAnalytics() {
|
|
1443
|
-
console.log();
|
|
1444
|
-
console.log(import_picocolors3.default.cyan(" \uD83D\uDCCA Analytics"));
|
|
1445
|
-
console.log();
|
|
1446
|
-
const needsAnalytics = await ye({
|
|
1447
|
-
message: "Incluir Google Analytics?",
|
|
1448
|
-
initialValue: false
|
|
1449
|
-
});
|
|
1450
|
-
if (pD(needsAnalytics) || !needsAnalytics) {
|
|
1451
|
-
return { enabled: false };
|
|
1373
|
+
if (config.features.auth) {
|
|
1374
|
+
inventory += `- \`/api/auth/[...nextauth]\` - Authentication endpoints
|
|
1375
|
+
`;
|
|
1452
1376
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
placeholder: "G-XXXXXXXXXX",
|
|
1457
|
-
validate: (v2) => {
|
|
1458
|
-
if (!v2)
|
|
1459
|
-
return;
|
|
1460
|
-
if (!v2.startsWith("G-")) {
|
|
1461
|
-
return "ID inv\xE1lido (deve come\xE7ar com G-)";
|
|
1462
|
-
}
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
});
|
|
1466
|
-
if (pD(trackingId)) {
|
|
1467
|
-
return { enabled: false };
|
|
1377
|
+
if (!config.features.contactForm && !config.features.auth) {
|
|
1378
|
+
inventory += `- None yet (add API routes in \`app/api/\`)
|
|
1379
|
+
`;
|
|
1468
1380
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1381
|
+
inventory += `
|
|
1382
|
+
**Utilities:**
|
|
1383
|
+
`;
|
|
1384
|
+
if (config.stack.email) {
|
|
1385
|
+
inventory += `- \`lib/email.ts\` - ${config.stack.email} client configuration
|
|
1386
|
+
`;
|
|
1387
|
+
}
|
|
1388
|
+
if (config.features.contactForm) {
|
|
1389
|
+
inventory += `- \`lib/validations.ts\` - Zod schemas (contactSchema: name, email, message)
|
|
1390
|
+
`;
|
|
1391
|
+
}
|
|
1392
|
+
inventory += `- \`lib/utils.ts\` - Helper functions (cn, formatters)
|
|
1393
|
+
`;
|
|
1394
|
+
return inventory;
|
|
1473
1395
|
}
|
|
1474
|
-
function
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1396
|
+
function generateFeatureDependencies(config) {
|
|
1397
|
+
let deps = "";
|
|
1398
|
+
if (config.features.contactForm) {
|
|
1399
|
+
deps += `**Contact Form** depends on:
|
|
1400
|
+
\`\`\`
|
|
1401
|
+
\u251C\u2500 React Hook Form (form state management)
|
|
1402
|
+
\u251C\u2500 Zod (validation schemas)
|
|
1403
|
+
${config.stack.email ? `\u251C\u2500 ${config.stack.email} (email sending)
|
|
1404
|
+
` : ""}\u2514\u2500 /api/contact (server endpoint)
|
|
1405
|
+
\`\`\`
|
|
1406
|
+
|
|
1407
|
+
**To modify contact form:**
|
|
1408
|
+
1. Update validation: \`lib/validations.ts\` (contactSchema)
|
|
1409
|
+
2. Update UI: \`components/forms/contact-form.tsx\`
|
|
1410
|
+
3. Update API: \`app/api/contact/route.ts\`
|
|
1411
|
+
4. Update email template: \`emails/contact-email.tsx\` (if exists)
|
|
1412
|
+
|
|
1413
|
+
`;
|
|
1484
1414
|
}
|
|
1485
|
-
|
|
1415
|
+
if (config.features.auth) {
|
|
1416
|
+
deps += `**Authentication** depends on:
|
|
1417
|
+
\`\`\`
|
|
1418
|
+
\u251C\u2500 ${config.stack.auth} (auth provider)
|
|
1419
|
+
\u251C\u2500 Database (user storage)
|
|
1420
|
+
\u2514\u2500 /api/auth/[...nextauth] (auth endpoints)
|
|
1421
|
+
\`\`\`
|
|
1422
|
+
|
|
1423
|
+
**To modify auth:**
|
|
1424
|
+
1. Update config: \`lib/auth.ts\`
|
|
1425
|
+
2. Update providers: Add/remove in auth config
|
|
1426
|
+
3. Update callbacks: Customize JWT/session
|
|
1427
|
+
|
|
1428
|
+
`;
|
|
1429
|
+
}
|
|
1430
|
+
if (!deps) {
|
|
1431
|
+
deps = `No complex feature dependencies yet. Add features and their dependency maps will appear here.
|
|
1432
|
+
`;
|
|
1433
|
+
}
|
|
1434
|
+
return deps;
|
|
1486
1435
|
}
|
|
1487
|
-
async function
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1436
|
+
async function generateModificationsDoc(projectPath, config) {
|
|
1437
|
+
let content = `# Modification Guide
|
|
1438
|
+
|
|
1439
|
+
This file shows you exactly how to modify existing features in this project.
|
|
1440
|
+
|
|
1441
|
+
> **Context-aware:** These are the actual files in YOUR project, not generic examples.
|
|
1442
|
+
|
|
1443
|
+
`;
|
|
1444
|
+
if (config.type === "landing") {
|
|
1445
|
+
content += `## Landing Page Sections
|
|
1446
|
+
|
|
1447
|
+
### Change Hero Text
|
|
1448
|
+
|
|
1449
|
+
**File:** \`components/sections/hero.tsx\`
|
|
1450
|
+
**What to edit:** Lines with \`<h1>\` and \`<p>\` tags
|
|
1451
|
+
**Current pattern:** Value proposition + subheading + CTA
|
|
1452
|
+
**Example change:**
|
|
1453
|
+
\`\`\`tsx
|
|
1454
|
+
<h1 className="text-4xl font-bold">
|
|
1455
|
+
Your New Headline Here
|
|
1456
|
+
</h1>
|
|
1457
|
+
<p className="text-xl text-muted-foreground">
|
|
1458
|
+
Your new subheading
|
|
1459
|
+
</p>
|
|
1460
|
+
\`\`\`
|
|
1461
|
+
|
|
1462
|
+
### Add/Remove Feature Cards
|
|
1463
|
+
|
|
1464
|
+
**File:** \`components/sections/features.tsx\`
|
|
1465
|
+
**What to edit:** \`features\` array (usually lines 10-25)
|
|
1466
|
+
**Current:** 3 feature cards
|
|
1467
|
+
**To add:** Push new object to array: \`{ icon: Icon, title: "", description: "" }\`
|
|
1468
|
+
**To remove:** Delete object from array or filter it out
|
|
1469
|
+
|
|
1470
|
+
### Modify FAQ Questions
|
|
1471
|
+
|
|
1472
|
+
**File:** \`components/sections/faq.tsx\`
|
|
1473
|
+
**What to edit:** \`questions\` array
|
|
1474
|
+
**Current:** Pre-populated with common questions
|
|
1475
|
+
**Pattern:** Keep answers concise (< 100 chars) for better UX
|
|
1476
|
+
**To add:** \`{ question: "...", answer: "..." }\`
|
|
1477
|
+
|
|
1478
|
+
`;
|
|
1502
1479
|
}
|
|
1503
|
-
if (features.
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1480
|
+
if (config.features.contactForm) {
|
|
1481
|
+
content += `## Contact Form
|
|
1482
|
+
|
|
1483
|
+
### Change Form Fields
|
|
1484
|
+
|
|
1485
|
+
**Files to modify:**
|
|
1486
|
+
1. \`lib/validations.ts\` - Add field to schema
|
|
1487
|
+
2. \`components/forms/contact-form.tsx\` - Add UI input
|
|
1488
|
+
3. \`app/api/contact/route.ts\` - Handle new field
|
|
1489
|
+
|
|
1490
|
+
**Example: Add phone field**
|
|
1491
|
+
\`\`\`typescript
|
|
1492
|
+
// 1. lib/validations.ts
|
|
1493
|
+
export const contactSchema = z.object({
|
|
1494
|
+
name: z.string().min(2),
|
|
1495
|
+
email: z.string().email(),
|
|
1496
|
+
phone: z.string().min(10), // NEW
|
|
1497
|
+
message: z.string().min(10),
|
|
1498
|
+
})
|
|
1499
|
+
|
|
1500
|
+
// 2. components/forms/contact-form.tsx
|
|
1501
|
+
<FormField
|
|
1502
|
+
name="phone"
|
|
1503
|
+
control={form.control}
|
|
1504
|
+
render={({ field }) => (
|
|
1505
|
+
<Input placeholder="Phone" {...field} />
|
|
1506
|
+
)}
|
|
1507
|
+
/>
|
|
1508
|
+
|
|
1509
|
+
// 3. app/api/contact/route.ts
|
|
1510
|
+
// Phone is now available in validated data
|
|
1511
|
+
const { name, email, phone, message } = validated.data
|
|
1512
|
+
\`\`\`
|
|
1513
|
+
|
|
1514
|
+
### Change Email Template
|
|
1515
|
+
|
|
1516
|
+
**File:** \`emails/contact-email.tsx\` (if using React Email)
|
|
1517
|
+
**Alternative:** Inline in \`app/api/contact/route.ts\`
|
|
1518
|
+
**What to edit:** Subject, body content, styling
|
|
1519
|
+
**Test locally:** \`bun run email:dev\` (if available)
|
|
1520
|
+
|
|
1521
|
+
### Change Email Recipient
|
|
1522
|
+
|
|
1523
|
+
**File:** \`app/api/contact/route.ts\`
|
|
1524
|
+
**What to edit:** The \`to:\` field in email send
|
|
1525
|
+
\`\`\`typescript
|
|
1526
|
+
await resend.emails.send({
|
|
1527
|
+
to: 'your-new-email@example.com', // CHANGE THIS
|
|
1528
|
+
// ...
|
|
1529
|
+
})
|
|
1530
|
+
\`\`\`
|
|
1531
|
+
|
|
1532
|
+
`;
|
|
1508
1533
|
}
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1534
|
+
content += `## Styling Changes
|
|
1535
|
+
|
|
1536
|
+
### Update Colors
|
|
1537
|
+
|
|
1538
|
+
**File:** \`app/globals.css\`
|
|
1539
|
+
**What to edit:** CSS variables in \`:root\` and \`.dark\`
|
|
1540
|
+
\`\`\`css
|
|
1541
|
+
:root {
|
|
1542
|
+
--primary: 220 90% 56%; /* Change this */
|
|
1543
|
+
}
|
|
1544
|
+
\`\`\`
|
|
1545
|
+
**Tip:** Use [shadcn theme editor](https://ui.shadcn.com/themes) to generate new colors
|
|
1546
|
+
|
|
1547
|
+
### Change Fonts
|
|
1548
|
+
|
|
1549
|
+
**File:** \`app/layout.tsx\`
|
|
1550
|
+
**What to edit:** Font imports and \`className\` on \`<body>\`
|
|
1551
|
+
\`\`\`tsx
|
|
1552
|
+
import { Inter } from 'next/font/google'
|
|
1553
|
+
|
|
1554
|
+
const font = Inter({ subsets: ['latin'] })
|
|
1555
|
+
|
|
1556
|
+
<body className={font.className}>
|
|
1557
|
+
\`\`\`
|
|
1558
|
+
|
|
1559
|
+
## Adding New Features
|
|
1560
|
+
|
|
1561
|
+
### Add a New Page
|
|
1562
|
+
|
|
1563
|
+
\`\`\`bash
|
|
1564
|
+
# 1. Create route
|
|
1565
|
+
touch app/about/page.tsx
|
|
1566
|
+
|
|
1567
|
+
# 2. Add navigation link
|
|
1568
|
+
# Edit: components/layout/header.tsx or footer.tsx
|
|
1569
|
+
\`\`\`
|
|
1570
|
+
|
|
1571
|
+
### Add shadcn/ui Component
|
|
1572
|
+
|
|
1573
|
+
\`\`\`bash
|
|
1574
|
+
bunx --bun shadcn@latest add [component-name]
|
|
1575
|
+
# Example: bunx --bun shadcn@latest add dialog
|
|
1576
|
+
\`\`\`
|
|
1577
|
+
|
|
1578
|
+
## Environment Variables
|
|
1579
|
+
|
|
1580
|
+
**File:** \`.env\` (create from \`.env.example\`)
|
|
1581
|
+
|
|
1582
|
+
${config.stack.email ? `### ${config.stack.email} API Key
|
|
1583
|
+
\`\`\`env
|
|
1584
|
+
RESEND_API_KEY=re_xxxxxxxxxxxx
|
|
1585
|
+
\`\`\`
|
|
1586
|
+
**Get key:** [${config.stack.email} Dashboard](https://resend.com/api-keys)
|
|
1587
|
+
|
|
1588
|
+
` : ""}${config.features.analytics ? `### Google Analytics
|
|
1589
|
+
\`\`\`env
|
|
1590
|
+
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
|
|
1591
|
+
\`\`\`
|
|
1592
|
+
**Get ID:** [Google Analytics](https://analytics.google.com)
|
|
1593
|
+
|
|
1594
|
+
` : ""}## Common Modifications
|
|
1595
|
+
|
|
1596
|
+
### Change Site Metadata (SEO)
|
|
1597
|
+
|
|
1598
|
+
**File:** \`app/layout.tsx\`
|
|
1599
|
+
**What to edit:** \`metadata\` export
|
|
1600
|
+
\`\`\`tsx
|
|
1601
|
+
export const metadata = {
|
|
1602
|
+
title: 'Your New Title',
|
|
1603
|
+
description: 'Your new description',
|
|
1604
|
+
// ...
|
|
1605
|
+
}
|
|
1606
|
+
\`\`\`
|
|
1607
|
+
|
|
1608
|
+
### Add Custom Font from File
|
|
1609
|
+
|
|
1610
|
+
\`\`\`tsx
|
|
1611
|
+
// app/layout.tsx
|
|
1612
|
+
import localFont from 'next/font/local'
|
|
1613
|
+
|
|
1614
|
+
const customFont = localFont({
|
|
1615
|
+
src: './fonts/CustomFont.woff2',
|
|
1616
|
+
variable: '--font-custom',
|
|
1617
|
+
})
|
|
1618
|
+
\`\`\`
|
|
1619
|
+
|
|
1620
|
+
---
|
|
1621
|
+
|
|
1622
|
+
**Pro tip:** Before modifying, search the codebase for the text/component you want to change:
|
|
1623
|
+
\`\`\`bash
|
|
1624
|
+
grep -r "text to find" .
|
|
1625
|
+
\`\`\`
|
|
1626
|
+
`;
|
|
1627
|
+
await Bun.write(join(projectPath, "MODIFICATIONS.md"), content);
|
|
1628
|
+
}
|
|
1629
|
+
async function createCompatibilitySymlinks(projectPath) {
|
|
1630
|
+
const agentsContent = await Bun.file(join(projectPath, "AGENTS.md")).text();
|
|
1631
|
+
await Bun.write(join(projectPath, ".cursorrules"), agentsContent);
|
|
1632
|
+
const githubDir = join(projectPath, ".github");
|
|
1633
|
+
await Bun.$`mkdir -p ${githubDir}`.quiet();
|
|
1634
|
+
await Bun.write(join(githubDir, "copilot-instructions.md"), agentsContent);
|
|
1526
1635
|
}
|
|
1527
1636
|
// src/commands/create.ts
|
|
1637
|
+
var TEMPLATES = {
|
|
1638
|
+
landing: "nimbuslab/create-next-landing",
|
|
1639
|
+
app: "nimbuslab/create-next-app",
|
|
1640
|
+
turborepo: "nimbuslab/create-turborepo"
|
|
1641
|
+
};
|
|
1528
1642
|
var AI_CONFIGS = {
|
|
1529
1643
|
claude: {
|
|
1530
1644
|
filename: "CLAUDE.md",
|
|
@@ -1645,42 +1759,14 @@ async function checkGitHubCli() {
|
|
|
1645
1759
|
return { installed: false, authenticated: false, username: null, orgs: [] };
|
|
1646
1760
|
}
|
|
1647
1761
|
}
|
|
1648
|
-
var PRIVATE_TEMPLATES = {
|
|
1649
|
-
fast: "nimbuslab-templates/fast-template",
|
|
1650
|
-
"fast+": "nimbuslab-templates/fastplus-template",
|
|
1651
|
-
"fast+-monorepo": "nimbuslab-templates/fastplus-monorepo-template",
|
|
1652
|
-
"nimbus-core": "nimbuslab/nimbus-core"
|
|
1653
|
-
};
|
|
1654
|
-
var PUBLIC_TEMPLATES = {
|
|
1655
|
-
landing: "nimbuslab/create-next-landing",
|
|
1656
|
-
app: "nimbuslab/create-next-app",
|
|
1657
|
-
turborepo: "nimbuslab/create-turborepo"
|
|
1658
|
-
};
|
|
1659
|
-
var TEMPLATES = { ...PRIVATE_TEMPLATES, ...PUBLIC_TEMPLATES };
|
|
1660
|
-
var NIMBUSLAB_DOMAINS = ["@nimbuslab.com.br", "@nimbuslab.net.br"];
|
|
1661
|
-
async function isNimbuslabMember() {
|
|
1662
|
-
try {
|
|
1663
|
-
const user = (await $2`git config user.name`.text()).trim();
|
|
1664
|
-
const email = (await $2`git config user.email`.text()).trim();
|
|
1665
|
-
const isMember = NIMBUSLAB_DOMAINS.some((domain) => email.endsWith(domain));
|
|
1666
|
-
return { isMember, user, email };
|
|
1667
|
-
} catch {
|
|
1668
|
-
return { isMember: false, user: null, email: null };
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
1762
|
function parseFlags(args) {
|
|
1672
1763
|
const flags = {
|
|
1673
1764
|
yes: false,
|
|
1674
1765
|
landing: false,
|
|
1675
1766
|
app: false,
|
|
1676
1767
|
turborepo: false,
|
|
1677
|
-
fast: false,
|
|
1678
|
-
fastPlus: false,
|
|
1679
|
-
fastTurborepo: false,
|
|
1680
|
-
core: false,
|
|
1681
1768
|
noGit: false,
|
|
1682
1769
|
noInstall: false,
|
|
1683
|
-
railway: false,
|
|
1684
1770
|
template: null
|
|
1685
1771
|
};
|
|
1686
1772
|
let projectName;
|
|
@@ -1695,20 +1781,10 @@ function parseFlags(args) {
|
|
|
1695
1781
|
flags.app = true;
|
|
1696
1782
|
} else if (arg === "--turborepo") {
|
|
1697
1783
|
flags.turborepo = true;
|
|
1698
|
-
} else if (arg === "--fast") {
|
|
1699
|
-
flags.fast = true;
|
|
1700
|
-
} else if (arg === "--fast-plus") {
|
|
1701
|
-
flags.fastPlus = true;
|
|
1702
|
-
} else if (arg === "--fast-turborepo") {
|
|
1703
|
-
flags.fastTurborepo = true;
|
|
1704
|
-
} else if (arg === "--core") {
|
|
1705
|
-
flags.core = true;
|
|
1706
1784
|
} else if (arg === "--no-git") {
|
|
1707
1785
|
flags.noGit = true;
|
|
1708
1786
|
} else if (arg === "--no-install") {
|
|
1709
1787
|
flags.noInstall = true;
|
|
1710
|
-
} else if (arg === "--railway") {
|
|
1711
|
-
flags.railway = true;
|
|
1712
1788
|
} else if (arg === "--template") {
|
|
1713
1789
|
i++;
|
|
1714
1790
|
flags.template = args[i] ?? null;
|
|
@@ -1719,320 +1795,56 @@ function parseFlags(args) {
|
|
|
1719
1795
|
}
|
|
1720
1796
|
return { flags, projectName };
|
|
1721
1797
|
}
|
|
1722
|
-
async function ensureRailwayCli() {
|
|
1723
|
-
const checkCmd = process.platform === "win32" ? "where" : "which";
|
|
1724
|
-
const hasRailway = await $2`${checkCmd} railway`.quiet().then(() => true).catch(() => false);
|
|
1725
|
-
if (hasRailway)
|
|
1726
|
-
return true;
|
|
1727
|
-
console.log(import_picocolors4.default.yellow("Railway CLI not found. Installing..."));
|
|
1728
|
-
console.log();
|
|
1729
|
-
try {
|
|
1730
|
-
if (process.platform === "win32") {
|
|
1731
|
-
await $2`powershell -c "iwr https://railway.app/install.ps1 -useb | iex"`.quiet();
|
|
1732
|
-
} else {
|
|
1733
|
-
await $2`curl -fsSL https://railway.app/install.sh | sh`.quiet();
|
|
1734
|
-
}
|
|
1735
|
-
console.log(import_picocolors4.default.green("Railway CLI installed successfully!"));
|
|
1736
|
-
return true;
|
|
1737
|
-
} catch (error) {
|
|
1738
|
-
console.log(import_picocolors4.default.red("Error installing Railway CLI."));
|
|
1739
|
-
console.log(import_picocolors4.default.dim("Install manually: https://docs.railway.app/guides/cli"));
|
|
1740
|
-
return false;
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
async function listRailwayProjects() {
|
|
1744
|
-
try {
|
|
1745
|
-
const result = await $2`railway list`.text();
|
|
1746
|
-
const lines = result.trim().split(`
|
|
1747
|
-
`).filter((l2) => l2.trim());
|
|
1748
|
-
return lines.slice(1).map((l2) => l2.trim());
|
|
1749
|
-
} catch {
|
|
1750
|
-
return [];
|
|
1751
|
-
}
|
|
1752
|
-
}
|
|
1753
|
-
async function isRailwayAuthenticated() {
|
|
1754
|
-
try {
|
|
1755
|
-
await $2`railway whoami`.quiet();
|
|
1756
|
-
return true;
|
|
1757
|
-
} catch {
|
|
1758
|
-
return false;
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1761
|
-
async function create(args) {
|
|
1762
|
-
const checkCmd = process.platform === "win32" ? "where" : "which";
|
|
1763
|
-
const hasBun = await $2`${checkCmd} bun`.quiet().then(() => true).catch(() => false);
|
|
1764
|
-
const hasGit = await $2`${checkCmd} git`.quiet().then(() => true).catch(() => false);
|
|
1765
|
-
const hasGh = await $2`${checkCmd} gh`.quiet().then(() => true).catch(() => false);
|
|
1766
|
-
if (!hasBun) {
|
|
1767
|
-
console.log(import_picocolors4.default.red("Error: Bun not found."));
|
|
1768
|
-
console.log(import_picocolors4.default.dim("Install from: https://bun.sh"));
|
|
1769
|
-
console.log();
|
|
1770
|
-
if (process.platform === "win32") {
|
|
1771
|
-
console.log(import_picocolors4.default.cyan('powershell -c "irm bun.sh/install.ps1 | iex"'));
|
|
1772
|
-
} else {
|
|
1773
|
-
console.log(import_picocolors4.default.cyan("curl -fsSL https://bun.sh/install | bash"));
|
|
1774
|
-
}
|
|
1775
|
-
console.log();
|
|
1776
|
-
process.exit(1);
|
|
1777
|
-
}
|
|
1778
|
-
if (!hasGit) {
|
|
1779
|
-
console.log(import_picocolors4.default.red("Error: Git not found."));
|
|
1780
|
-
console.log(import_picocolors4.default.dim("Install git to continue."));
|
|
1781
|
-
process.exit(1);
|
|
1782
|
-
}
|
|
1783
|
-
if (!hasGh) {
|
|
1784
|
-
console.log(import_picocolors4.default.dim(" GitHub CLI not found (repo creation will be skipped)"));
|
|
1785
|
-
console.log(import_picocolors4.default.dim(" Install from: https://cli.github.com"));
|
|
1786
|
-
console.log();
|
|
1787
|
-
}
|
|
1788
|
-
const hasRailway = await ensureRailwayCli();
|
|
1789
|
-
if (hasRailway) {
|
|
1790
|
-
const railwayAuth = await isRailwayAuthenticated();
|
|
1791
|
-
if (!railwayAuth) {
|
|
1792
|
-
console.log(import_picocolors4.default.yellow("Railway CLI not authenticated."));
|
|
1793
|
-
console.log(import_picocolors4.default.dim("Run: railway login"));
|
|
1794
|
-
console.log();
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
const { flags, projectName } = parseFlags(args);
|
|
1798
|
-
Ie(import_picocolors4.default.bgCyan(import_picocolors4.default.black(" New nimbuslab Project ")));
|
|
1799
|
-
let config;
|
|
1800
|
-
const hasTypeFlag = flags.landing || flags.app || flags.turborepo || flags.fast || flags.fastPlus || flags.fastTurborepo || flags.core;
|
|
1801
|
-
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;
|
|
1802
|
-
const monorepoFromFlag = flags.fastTurborepo;
|
|
1803
|
-
if ((flags.yes || hasTypeFlag) && projectName) {
|
|
1804
|
-
const defaultType = flags.landing || flags.app || flags.turborepo ? "landing" : "fast";
|
|
1805
|
-
config = {
|
|
1806
|
-
name: projectName,
|
|
1807
|
-
type: typeFromFlag || defaultType,
|
|
1808
|
-
monorepo: monorepoFromFlag,
|
|
1809
|
-
git: !flags.noGit,
|
|
1810
|
-
install: !flags.noInstall,
|
|
1811
|
-
github: false,
|
|
1812
|
-
githubOrg: null,
|
|
1813
|
-
githubDescription: "",
|
|
1814
|
-
theme: "dark",
|
|
1815
|
-
aiAssistant: null,
|
|
1816
|
-
contractNumber: "",
|
|
1817
|
-
resendApiKey: "",
|
|
1818
|
-
resendFromEmail: "",
|
|
1819
|
-
contactEmail: "",
|
|
1820
|
-
railwayProject: "",
|
|
1821
|
-
railwayToken: "",
|
|
1822
|
-
stagingUrl: "",
|
|
1823
|
-
productionUrl: "",
|
|
1824
|
-
customTemplate: flags.template
|
|
1825
|
-
};
|
|
1826
|
-
const typeLabel = flags.turborepo ? "fast+ (monorepo)" : config.type;
|
|
1827
|
-
console.log(import_picocolors4.default.dim(` Project: ${projectName}`));
|
|
1828
|
-
console.log(import_picocolors4.default.dim(` Type: ${typeLabel}`));
|
|
1829
|
-
console.log(import_picocolors4.default.dim(` Git: ${config.git ? "yes" : "no"}`));
|
|
1830
|
-
console.log(import_picocolors4.default.dim(` Install: ${config.install ? "yes" : "no"}`));
|
|
1831
|
-
if (flags.railway)
|
|
1832
|
-
console.log(import_picocolors4.default.dim(` Railway: configurar`));
|
|
1833
|
-
if (flags.template)
|
|
1834
|
-
console.log(import_picocolors4.default.dim(` Template: ${flags.template}`));
|
|
1835
|
-
console.log();
|
|
1836
|
-
if (flags.railway) {
|
|
1837
|
-
const railwayAuthenticated = await isRailwayAuthenticated();
|
|
1838
|
-
if (railwayAuthenticated) {
|
|
1839
|
-
if (config.type === "fast") {
|
|
1840
|
-
const projects = await listRailwayProjects();
|
|
1841
|
-
const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
|
|
1842
|
-
if (fastProject) {
|
|
1843
|
-
config.railwayProject = fastProject;
|
|
1844
|
-
console.log(import_picocolors4.default.green(` Railway: ${fastProject}`));
|
|
1845
|
-
}
|
|
1846
|
-
} else {
|
|
1847
|
-
console.log(import_picocolors4.default.dim(` Creating project Railway: ${projectName}...`));
|
|
1848
|
-
try {
|
|
1849
|
-
const result = await $2`echo "" | railway init -n ${projectName} -w nimbuslab --json`.text();
|
|
1850
|
-
const newProject = JSON.parse(result);
|
|
1851
|
-
config.railwayProject = newProject.name || projectName;
|
|
1852
|
-
console.log(import_picocolors4.default.green(` Railway: ${config.railwayProject} criado`));
|
|
1853
|
-
} catch {
|
|
1854
|
-
console.log(import_picocolors4.default.yellow(` Railway: erro ao criar projeto`));
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
} else {
|
|
1858
|
-
console.log(import_picocolors4.default.yellow(` Railway: not authenticated (railway login)`));
|
|
1859
|
-
}
|
|
1860
|
-
console.log();
|
|
1861
|
-
}
|
|
1862
|
-
} else {
|
|
1863
|
-
config = await promptConfig(projectName, flags);
|
|
1864
|
-
}
|
|
1865
|
-
if (pD(config)) {
|
|
1866
|
-
xe("Operation cancelled");
|
|
1867
|
-
process.exit(0);
|
|
1868
|
-
}
|
|
1869
|
-
await createProject(config);
|
|
1870
|
-
const finalConfig = config;
|
|
1871
|
-
const isPublicTemplate = ["landing", "app", "turborepo"].includes(finalConfig.type);
|
|
1872
|
-
if (isPublicTemplate) {
|
|
1873
|
-
const s = Y2();
|
|
1874
|
-
s.start("Configura\xE7\xE3o de servi\xE7os...");
|
|
1875
|
-
const setupResult = await interactiveSetup(finalConfig.type);
|
|
1876
|
-
s.stop("Configura\xE7\xE3o conclu\xEDda");
|
|
1877
|
-
s.start("Gerando documenta\xE7\xE3o AI-friendly...");
|
|
1878
|
-
try {
|
|
1879
|
-
const generatorConfig = {
|
|
1880
|
-
name: finalConfig.name,
|
|
1881
|
-
type: finalConfig.type,
|
|
1882
|
-
description: finalConfig.githubDescription || `${finalConfig.type} criado com nimbus-cli`,
|
|
1883
|
-
stack: {
|
|
1884
|
-
framework: "Next.js 16 (App Router)",
|
|
1885
|
-
styling: "Tailwind CSS 4",
|
|
1886
|
-
components: "shadcn/ui (default)",
|
|
1887
|
-
forms: setupResult.features.contactForm ? "React Hook Form + Zod" : undefined,
|
|
1888
|
-
email: setupResult.features.contactForm ? "Resend" : undefined,
|
|
1889
|
-
auth: finalConfig.type === "app" ? "Better Auth" : undefined
|
|
1890
|
-
},
|
|
1891
|
-
features: {
|
|
1892
|
-
contactForm: setupResult.features.contactForm,
|
|
1893
|
-
newsletter: setupResult.features.newsletter,
|
|
1894
|
-
analytics: setupResult.features.analytics,
|
|
1895
|
-
auth: finalConfig.type === "app"
|
|
1896
|
-
}
|
|
1897
|
-
};
|
|
1898
|
-
await generateAIFriendlyDocs(finalConfig.name, generatorConfig);
|
|
1899
|
-
s.stop("Documenta\xE7\xE3o AI-friendly gerada");
|
|
1900
|
-
} catch (error) {
|
|
1901
|
-
s.stop("Erro ao gerar documenta\xE7\xE3o AI-friendly");
|
|
1902
|
-
console.log(import_picocolors4.default.dim(" Voc\xEA pode gerar manualmente depois"));
|
|
1903
|
-
}
|
|
1904
|
-
if (!setupResult.skipSetup && (setupResult.apiKeys.resend || setupResult.apiKeys.ga)) {
|
|
1905
|
-
s.start("Gerando arquivos .env...");
|
|
1906
|
-
try {
|
|
1907
|
-
await generateEnvFile(finalConfig.name, setupResult.apiKeys, setupResult.features);
|
|
1908
|
-
s.stop("Arquivos .env gerados (.env e .env.example)");
|
|
1909
|
-
} catch (error) {
|
|
1910
|
-
s.stop("Erro ao gerar .env");
|
|
1911
|
-
console.log(import_picocolors4.default.dim(" Voc\xEA pode criar manualmente depois"));
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
Se(import_picocolors4.default.green("Project created successfully!"));
|
|
1916
|
-
showNextSteps(config);
|
|
1917
|
-
}
|
|
1918
1798
|
async function promptConfig(initialName, flags) {
|
|
1919
|
-
const { isMember, user } = await isNimbuslabMember();
|
|
1920
|
-
const greeting = user ? `Hello, ${user}!` : "Hello!";
|
|
1921
|
-
console.log(import_picocolors4.default.dim(` ${greeting}`));
|
|
1922
|
-
console.log();
|
|
1923
1799
|
const name = await he({
|
|
1924
1800
|
message: "Project name:",
|
|
1925
|
-
placeholder: "
|
|
1926
|
-
initialValue: initialName,
|
|
1801
|
+
placeholder: initialName || "my-project",
|
|
1802
|
+
initialValue: initialName || "",
|
|
1927
1803
|
validate: (value) => {
|
|
1928
1804
|
if (!value)
|
|
1929
|
-
return "
|
|
1805
|
+
return "Project name is required";
|
|
1930
1806
|
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
1931
|
-
return "Use
|
|
1807
|
+
return "Use lowercase letters, numbers, and hyphens only";
|
|
1932
1808
|
}
|
|
1933
|
-
return;
|
|
1934
1809
|
}
|
|
1935
1810
|
});
|
|
1936
1811
|
if (pD(name))
|
|
1937
1812
|
return name;
|
|
1938
|
-
const publicOptions = [
|
|
1939
|
-
{
|
|
1940
|
-
value: "landing",
|
|
1941
|
-
label: "Landing Page",
|
|
1942
|
-
hint: "Next.js 16 + Tailwind 4 + shadcn"
|
|
1943
|
-
},
|
|
1944
|
-
{
|
|
1945
|
-
value: "app",
|
|
1946
|
-
label: "Web App",
|
|
1947
|
-
hint: "Landing + Better Auth + Drizzle"
|
|
1948
|
-
},
|
|
1949
|
-
{
|
|
1950
|
-
value: "turborepo",
|
|
1951
|
-
label: "Monorepo",
|
|
1952
|
-
hint: "Turborepo + apps/packages"
|
|
1953
|
-
}
|
|
1954
|
-
];
|
|
1955
|
-
const privateOptions = isMember ? [
|
|
1956
|
-
{
|
|
1957
|
-
value: "fast",
|
|
1958
|
-
label: "fast",
|
|
1959
|
-
hint: "Landing page fast methodology"
|
|
1960
|
-
},
|
|
1961
|
-
{
|
|
1962
|
-
value: "fast+",
|
|
1963
|
-
label: "fast+",
|
|
1964
|
-
hint: "Complete SaaS"
|
|
1965
|
-
},
|
|
1966
|
-
{
|
|
1967
|
-
value: "nimbus-core",
|
|
1968
|
-
label: "nimbus-core",
|
|
1969
|
-
hint: "External projects (stealth mode)"
|
|
1970
|
-
}
|
|
1971
|
-
] : [];
|
|
1972
1813
|
const type = await ve({
|
|
1973
|
-
message: "
|
|
1974
|
-
options: [
|
|
1814
|
+
message: "Choose a template:",
|
|
1815
|
+
options: [
|
|
1816
|
+
{ value: "landing", label: "Landing Page", hint: "Next.js + Tailwind + shadcn/ui" },
|
|
1817
|
+
{ value: "app", label: "Web App", hint: "Landing + Auth + Database" },
|
|
1818
|
+
{ value: "turborepo", label: "Monorepo", hint: "Turborepo + apps/packages" }
|
|
1819
|
+
]
|
|
1975
1820
|
});
|
|
1976
1821
|
if (pD(type))
|
|
1977
1822
|
return type;
|
|
1978
|
-
const
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
name,
|
|
2004
|
-
type: "nimbus-core",
|
|
2005
|
-
monorepo: false,
|
|
2006
|
-
git: true,
|
|
2007
|
-
install: false,
|
|
2008
|
-
github: repoOption === "github",
|
|
2009
|
-
githubOrg: "nimbuslab",
|
|
2010
|
-
githubDescription: `nimbus-core for ${name} - external project`,
|
|
2011
|
-
theme: "dark",
|
|
2012
|
-
aiAssistant: null,
|
|
2013
|
-
contractNumber: "",
|
|
2014
|
-
resendApiKey: "",
|
|
2015
|
-
resendFromEmail: "",
|
|
2016
|
-
contactEmail: "",
|
|
2017
|
-
railwayProject: "",
|
|
2018
|
-
railwayToken: "",
|
|
2019
|
-
stagingUrl: "",
|
|
2020
|
-
productionUrl: "",
|
|
2021
|
-
customTemplate: null,
|
|
2022
|
-
clientRepoUrl: clientRepo || null
|
|
2023
|
-
};
|
|
2024
|
-
}
|
|
2025
|
-
let monorepo = false;
|
|
2026
|
-
if (type === "fast+") {
|
|
2027
|
-
const useMonorepo = await ye({
|
|
2028
|
-
message: "Use monorepo (Turborepo)?",
|
|
2029
|
-
initialValue: false
|
|
2030
|
-
});
|
|
2031
|
-
if (pD(useMonorepo))
|
|
2032
|
-
return useMonorepo;
|
|
2033
|
-
monorepo = useMonorepo;
|
|
2034
|
-
}
|
|
2035
|
-
const git = await ye({
|
|
1823
|
+
const theme = await ve({
|
|
1824
|
+
message: "Default theme:",
|
|
1825
|
+
options: [
|
|
1826
|
+
{ value: "dark", label: "Dark", hint: "recommended" },
|
|
1827
|
+
{ value: "light", label: "Light" },
|
|
1828
|
+
{ value: "system", label: "System" }
|
|
1829
|
+
]
|
|
1830
|
+
});
|
|
1831
|
+
if (pD(theme))
|
|
1832
|
+
return theme;
|
|
1833
|
+
const aiAssistant = await ve({
|
|
1834
|
+
message: "AI Assistant configuration:",
|
|
1835
|
+
options: [
|
|
1836
|
+
{ value: "claude", label: "Claude (Anthropic)", hint: "recommended" },
|
|
1837
|
+
{ value: "cursor", label: "Cursor" },
|
|
1838
|
+
{ value: "copilot", label: "GitHub Copilot" },
|
|
1839
|
+
{ value: "gemini", label: "Google Gemini" },
|
|
1840
|
+
{ value: "windsurf", label: "Windsurf" },
|
|
1841
|
+
{ value: "none", label: "None", hint: "skip" }
|
|
1842
|
+
],
|
|
1843
|
+
initialValue: "claude"
|
|
1844
|
+
});
|
|
1845
|
+
if (pD(aiAssistant))
|
|
1846
|
+
return aiAssistant;
|
|
1847
|
+
const git = flags.noGit ? false : await ye({
|
|
2036
1848
|
message: "Initialize Git repository?",
|
|
2037
1849
|
initialValue: true
|
|
2038
1850
|
});
|
|
@@ -2040,260 +1852,47 @@ async function promptConfig(initialName, flags) {
|
|
|
2040
1852
|
return git;
|
|
2041
1853
|
let github = false;
|
|
2042
1854
|
let githubOrg = null;
|
|
2043
|
-
let
|
|
1855
|
+
let githubVisibility = "public";
|
|
2044
1856
|
if (git) {
|
|
2045
|
-
const
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
return createGithub;
|
|
2051
|
-
github = createGithub;
|
|
2052
|
-
if (github) {
|
|
2053
|
-
const org = await ve({
|
|
2054
|
-
message: "GitHub organization:",
|
|
2055
|
-
options: [
|
|
2056
|
-
{ value: "nimbuslab", label: "nimbuslab", hint: "Main org" },
|
|
2057
|
-
{ value: "fast-by-nimbuslab", label: "fast-by-nimbuslab", hint: "Client projects" },
|
|
2058
|
-
{ value: "nimbuslab-templates", label: "nimbuslab-templates", hint: "Templates" },
|
|
2059
|
-
{ value: null, label: "Pessoal", hint: "Personal" }
|
|
2060
|
-
]
|
|
1857
|
+
const ghCheck = await checkGitHubCli();
|
|
1858
|
+
if (ghCheck.installed && ghCheck.authenticated) {
|
|
1859
|
+
github = await ye({
|
|
1860
|
+
message: "Create GitHub repository?",
|
|
1861
|
+
initialValue: true
|
|
2061
1862
|
});
|
|
2062
|
-
if (pD(
|
|
2063
|
-
return
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
initialValue: type === "fast" ? "Landing page fast by nimbuslab" : "SaaS fast+ by nimbuslab"
|
|
2069
|
-
});
|
|
2070
|
-
if (pD(description))
|
|
2071
|
-
return description;
|
|
2072
|
-
githubDescription = description;
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
let contractNumber = "";
|
|
2076
|
-
if (type === "fast") {
|
|
2077
|
-
const contract = await he({
|
|
2078
|
-
message: "Contract number (ex: 001):",
|
|
2079
|
-
placeholder: "001",
|
|
2080
|
-
validate: (v2) => v2 ? undefined : "Contract number is required for fast"
|
|
2081
|
-
});
|
|
2082
|
-
if (pD(contract))
|
|
2083
|
-
return contract;
|
|
2084
|
-
contractNumber = contract;
|
|
2085
|
-
}
|
|
2086
|
-
if (isPublicTemplate) {
|
|
2087
|
-
const theme = await ve({
|
|
2088
|
-
message: "Default theme:",
|
|
2089
|
-
options: [
|
|
2090
|
-
{ value: "dark", label: "Dark", hint: "recommended" },
|
|
2091
|
-
{ value: "light", label: "Light" },
|
|
2092
|
-
{ value: "system", label: "System", hint: "follows OS preference" }
|
|
2093
|
-
]
|
|
2094
|
-
});
|
|
2095
|
-
if (pD(theme))
|
|
2096
|
-
return theme;
|
|
2097
|
-
const aiAssistant = await ve({
|
|
2098
|
-
message: "Which AI assistant do you use?",
|
|
2099
|
-
options: [
|
|
2100
|
-
{ value: "claude", label: "Claude Code", hint: "Anthropic" },
|
|
2101
|
-
{ value: "cursor", label: "Cursor", hint: "AI-first editor" },
|
|
2102
|
-
{ value: "gemini", label: "Gemini CLI", hint: "Google" },
|
|
2103
|
-
{ value: "copilot", label: "GitHub Copilot" },
|
|
2104
|
-
{ value: "windsurf", label: "Windsurf", hint: "Codeium" },
|
|
2105
|
-
{ value: "none", label: "None", hint: "skip AI config" }
|
|
2106
|
-
]
|
|
2107
|
-
});
|
|
2108
|
-
if (pD(aiAssistant))
|
|
2109
|
-
return aiAssistant;
|
|
2110
|
-
let publicGithub = false;
|
|
2111
|
-
let publicGithubOrg = null;
|
|
2112
|
-
if (git) {
|
|
2113
|
-
const gh = await checkGitHubCli();
|
|
2114
|
-
if (gh.installed && gh.authenticated) {
|
|
2115
|
-
const createRepo = await ye({
|
|
2116
|
-
message: "Create GitHub repository?",
|
|
2117
|
-
initialValue: false
|
|
2118
|
-
});
|
|
2119
|
-
if (pD(createRepo))
|
|
2120
|
-
return createRepo;
|
|
2121
|
-
publicGithub = createRepo;
|
|
2122
|
-
if (publicGithub) {
|
|
2123
|
-
const repoOptions = [
|
|
2124
|
-
{ value: gh.username, label: gh.username, hint: "personal account" },
|
|
2125
|
-
...gh.orgs.map((org) => ({ value: org, label: org }))
|
|
2126
|
-
];
|
|
2127
|
-
const repoOwner = await ve({
|
|
2128
|
-
message: "Where to create the repository?",
|
|
2129
|
-
options: repoOptions
|
|
2130
|
-
});
|
|
2131
|
-
if (pD(repoOwner))
|
|
2132
|
-
return repoOwner;
|
|
2133
|
-
publicGithubOrg = repoOwner;
|
|
2134
|
-
const repoVisibility = await ve({
|
|
2135
|
-
message: "Repository visibility:",
|
|
2136
|
-
options: [
|
|
2137
|
-
{ value: "private", label: "Private", hint: "recommended" },
|
|
2138
|
-
{ value: "public", label: "Public" }
|
|
2139
|
-
]
|
|
2140
|
-
});
|
|
2141
|
-
if (pD(repoVisibility))
|
|
2142
|
-
return repoVisibility;
|
|
2143
|
-
githubDescription = repoVisibility;
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
const install2 = await ye({
|
|
2148
|
-
message: "Install dependencies?",
|
|
2149
|
-
initialValue: true
|
|
2150
|
-
});
|
|
2151
|
-
if (pD(install2))
|
|
2152
|
-
return install2;
|
|
2153
|
-
return {
|
|
2154
|
-
name,
|
|
2155
|
-
type,
|
|
2156
|
-
monorepo: false,
|
|
2157
|
-
git,
|
|
2158
|
-
install: install2,
|
|
2159
|
-
github: publicGithub,
|
|
2160
|
-
githubOrg: publicGithubOrg,
|
|
2161
|
-
githubDescription,
|
|
2162
|
-
theme,
|
|
2163
|
-
aiAssistant: aiAssistant === "none" ? null : aiAssistant,
|
|
2164
|
-
contractNumber: "",
|
|
2165
|
-
resendApiKey: "",
|
|
2166
|
-
resendFromEmail: "",
|
|
2167
|
-
contactEmail: "",
|
|
2168
|
-
railwayProject: "",
|
|
2169
|
-
railwayToken: "",
|
|
2170
|
-
stagingUrl: "",
|
|
2171
|
-
productionUrl: "",
|
|
2172
|
-
customTemplate: flags?.template || null
|
|
2173
|
-
};
|
|
2174
|
-
}
|
|
2175
|
-
let resendApiKey = "";
|
|
2176
|
-
let resendFromEmail = "";
|
|
2177
|
-
let contactEmail = "";
|
|
2178
|
-
let railwayProject = "";
|
|
2179
|
-
let railwayToken = "";
|
|
2180
|
-
let stagingUrl = "";
|
|
2181
|
-
let productionUrl = "";
|
|
2182
|
-
const currentYear = new Date().getFullYear().toString().slice(-3);
|
|
2183
|
-
const defaultStagingUrl = type === "fast" ? `https://fast-${contractNumber}-${currentYear}.nimbuslab.net.br` : `https://${name}.nimbuslab.net.br`;
|
|
2184
|
-
const defaultFromEmail = "no-reply@nimbuslab.com.br";
|
|
2185
|
-
const defaultContactEmail = type === "fast" ? "fast@nimbuslab.com.br" : "suporte@nimbuslab.com.br";
|
|
2186
|
-
const infraOptions = await fe({
|
|
2187
|
-
message: "What do you want to configure now?",
|
|
2188
|
-
options: [
|
|
2189
|
-
{ value: "urls", label: "URLs", hint: "staging and production" },
|
|
2190
|
-
{ value: "resend", label: "Resend", hint: "form emails" },
|
|
2191
|
-
{ value: "railway", label: "Railway", hint: "deploy and hosting" }
|
|
2192
|
-
],
|
|
2193
|
-
required: false
|
|
2194
|
-
});
|
|
2195
|
-
if (pD(infraOptions))
|
|
2196
|
-
return infraOptions;
|
|
2197
|
-
const configItems = infraOptions;
|
|
2198
|
-
if (configItems.includes("urls")) {
|
|
2199
|
-
console.log();
|
|
2200
|
-
console.log(import_picocolors4.default.dim(" Project URLs"));
|
|
2201
|
-
const staging = await he({
|
|
2202
|
-
message: "Staging URL:",
|
|
2203
|
-
placeholder: defaultStagingUrl,
|
|
2204
|
-
initialValue: defaultStagingUrl
|
|
2205
|
-
});
|
|
2206
|
-
if (pD(staging))
|
|
2207
|
-
return staging;
|
|
2208
|
-
stagingUrl = staging;
|
|
2209
|
-
const production = await he({
|
|
2210
|
-
message: "Production URL:",
|
|
2211
|
-
placeholder: defaultStagingUrl.replace(".nimbuslab.net.br", ".com.br"),
|
|
2212
|
-
initialValue: ""
|
|
2213
|
-
});
|
|
2214
|
-
if (pD(production))
|
|
2215
|
-
return production;
|
|
2216
|
-
productionUrl = production;
|
|
2217
|
-
}
|
|
2218
|
-
if (configItems.includes("resend")) {
|
|
2219
|
-
console.log();
|
|
2220
|
-
console.log(import_picocolors4.default.dim(" Resend (Email)"));
|
|
2221
|
-
const resendKey = await he({
|
|
2222
|
-
message: "RESEND_API_KEY:",
|
|
2223
|
-
placeholder: "re_xxxxxxxxxxxx"
|
|
2224
|
-
});
|
|
2225
|
-
if (pD(resendKey))
|
|
2226
|
-
return resendKey;
|
|
2227
|
-
resendApiKey = resendKey;
|
|
2228
|
-
const fromEmail = await he({
|
|
2229
|
-
message: "From email:",
|
|
2230
|
-
placeholder: defaultFromEmail,
|
|
2231
|
-
initialValue: defaultFromEmail
|
|
2232
|
-
});
|
|
2233
|
-
if (pD(fromEmail))
|
|
2234
|
-
return fromEmail;
|
|
2235
|
-
resendFromEmail = fromEmail;
|
|
2236
|
-
const contact = await he({
|
|
2237
|
-
message: "Contact email (receives forms):",
|
|
2238
|
-
placeholder: defaultContactEmail,
|
|
2239
|
-
initialValue: defaultContactEmail
|
|
2240
|
-
});
|
|
2241
|
-
if (pD(contact))
|
|
2242
|
-
return contact;
|
|
2243
|
-
contactEmail = contact;
|
|
2244
|
-
}
|
|
2245
|
-
if (configItems.includes("railway")) {
|
|
2246
|
-
const railwayAuthenticated = await isRailwayAuthenticated();
|
|
2247
|
-
if (railwayAuthenticated) {
|
|
2248
|
-
console.log();
|
|
2249
|
-
console.log(import_picocolors4.default.dim(" Railway"));
|
|
2250
|
-
const projects = await listRailwayProjects();
|
|
2251
|
-
if (type === "fast") {
|
|
2252
|
-
const fastProject = projects.find((p2) => p2.toLowerCase().includes("fast by nimbuslab"));
|
|
2253
|
-
if (fastProject) {
|
|
2254
|
-
railwayProject = fastProject;
|
|
2255
|
-
console.log(import_picocolors4.default.green(` Project: ${fastProject} (automatico)`));
|
|
2256
|
-
} else {
|
|
2257
|
-
console.log(import_picocolors4.default.yellow(" Project 'Fast by nimbuslab' not found."));
|
|
2258
|
-
console.log(import_picocolors4.default.dim(" Configure manually in .env"));
|
|
2259
|
-
}
|
|
2260
|
-
} else {
|
|
2261
|
-
const projectOptions = [
|
|
2262
|
-
...projects.map((proj) => ({ value: proj, label: proj })),
|
|
2263
|
-
{ value: "__new__", label: "Create new project", hint: "via railway init" },
|
|
2264
|
-
{ value: "__skip__", label: "Skip", hint: "Configure later" }
|
|
1863
|
+
if (pD(github))
|
|
1864
|
+
return github;
|
|
1865
|
+
if (github) {
|
|
1866
|
+
const orgOptions = [
|
|
1867
|
+
{ value: ghCheck.username, label: `${ghCheck.username} (personal)`, hint: "your account" },
|
|
1868
|
+
...ghCheck.orgs.map((org) => ({ value: org, label: org, hint: "organization" }))
|
|
2265
1869
|
];
|
|
2266
|
-
|
|
2267
|
-
message: "
|
|
2268
|
-
options:
|
|
1870
|
+
githubOrg = await ve({
|
|
1871
|
+
message: "GitHub owner:",
|
|
1872
|
+
options: orgOptions,
|
|
1873
|
+
initialValue: ghCheck.username
|
|
2269
1874
|
});
|
|
2270
|
-
if (pD(
|
|
2271
|
-
return
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
console.log(import_picocolors4.default.yellow(" Error creating project via CLI."));
|
|
2283
|
-
console.log(import_picocolors4.default.dim(" Create manually at: https://railway.app/new"));
|
|
2284
|
-
}
|
|
2285
|
-
} else if (selectedProject !== "__skip__") {
|
|
2286
|
-
railwayProject = selectedProject;
|
|
2287
|
-
console.log(import_picocolors4.default.green(` Project selected: ${railwayProject}`));
|
|
2288
|
-
}
|
|
1875
|
+
if (pD(githubOrg))
|
|
1876
|
+
return githubOrg;
|
|
1877
|
+
githubVisibility = await ve({
|
|
1878
|
+
message: "Repository visibility:",
|
|
1879
|
+
options: [
|
|
1880
|
+
{ value: "public", label: "Public", hint: "anyone can see" },
|
|
1881
|
+
{ value: "private", label: "Private", hint: "you choose who can see" }
|
|
1882
|
+
],
|
|
1883
|
+
initialValue: "public"
|
|
1884
|
+
});
|
|
1885
|
+
if (pD(githubVisibility))
|
|
1886
|
+
return githubVisibility;
|
|
2289
1887
|
}
|
|
2290
|
-
} else {
|
|
2291
|
-
console.log();
|
|
2292
|
-
console.log(
|
|
2293
|
-
|
|
1888
|
+
} else if (!ghCheck.installed) {
|
|
1889
|
+
console.log(import_picocolors3.default.dim(" GitHub CLI not found (repository creation will be skipped)"));
|
|
1890
|
+
console.log(import_picocolors3.default.dim(" Install from: https://cli.github.com"));
|
|
1891
|
+
} else if (!ghCheck.authenticated) {
|
|
1892
|
+
console.log(import_picocolors3.default.yellow(" GitHub CLI not authenticated (run: gh auth login)"));
|
|
2294
1893
|
}
|
|
2295
1894
|
}
|
|
2296
|
-
const install = await ye({
|
|
1895
|
+
const install = flags.noInstall ? false : await ye({
|
|
2297
1896
|
message: "Install dependencies?",
|
|
2298
1897
|
initialValue: true
|
|
2299
1898
|
});
|
|
@@ -2302,323 +1901,174 @@ async function promptConfig(initialName, flags) {
|
|
|
2302
1901
|
return {
|
|
2303
1902
|
name,
|
|
2304
1903
|
type,
|
|
2305
|
-
monorepo,
|
|
2306
1904
|
git,
|
|
2307
1905
|
install,
|
|
2308
1906
|
github,
|
|
2309
1907
|
githubOrg,
|
|
2310
|
-
|
|
2311
|
-
theme
|
|
2312
|
-
aiAssistant: null,
|
|
2313
|
-
|
|
2314
|
-
resendApiKey,
|
|
2315
|
-
resendFromEmail,
|
|
2316
|
-
contactEmail,
|
|
2317
|
-
railwayProject,
|
|
2318
|
-
railwayToken,
|
|
2319
|
-
stagingUrl,
|
|
2320
|
-
productionUrl,
|
|
2321
|
-
customTemplate: flags?.template || null
|
|
1908
|
+
githubVisibility,
|
|
1909
|
+
theme,
|
|
1910
|
+
aiAssistant: aiAssistant === "none" ? null : aiAssistant,
|
|
1911
|
+
customTemplate: flags.template
|
|
2322
1912
|
};
|
|
2323
1913
|
}
|
|
2324
1914
|
async function createProject(config) {
|
|
2325
1915
|
const s = Y2();
|
|
2326
|
-
|
|
2327
|
-
let templateLabel;
|
|
2328
|
-
if (config.customTemplate) {
|
|
2329
|
-
templateRepo = config.customTemplate;
|
|
2330
|
-
templateLabel = `customizado (${config.customTemplate})`;
|
|
2331
|
-
} else {
|
|
2332
|
-
const templateKey = config.type === "fast+" && config.monorepo ? "fast+-monorepo" : config.type;
|
|
2333
|
-
templateRepo = TEMPLATES[templateKey];
|
|
2334
|
-
templateLabel = config.monorepo ? `${config.type} (monorepo)` : config.type;
|
|
2335
|
-
}
|
|
2336
|
-
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
|
|
2337
|
-
s.start(`Cloning template ${templateLabel}...`);
|
|
1916
|
+
const projectPath = join2(process.cwd(), config.name);
|
|
2338
1917
|
try {
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
await
|
|
2346
|
-
s.stop(`Template cloned`);
|
|
1918
|
+
await rm(projectPath, { recursive: true, force: true });
|
|
1919
|
+
} catch {}
|
|
1920
|
+
const templateRepo = config.customTemplate || TEMPLATES[config.type];
|
|
1921
|
+
const templateUrl = templateRepo.startsWith("http") ? templateRepo : `https://github.com/${templateRepo}`;
|
|
1922
|
+
s.start(`Cloning template: ${config.type}`);
|
|
1923
|
+
try {
|
|
1924
|
+
await $2`git clone --depth 1 ${templateUrl} ${config.name}`.quiet();
|
|
1925
|
+
s.stop(`Template cloned: ${config.type}`);
|
|
2347
1926
|
} catch (error) {
|
|
2348
1927
|
s.stop("Error cloning template");
|
|
2349
|
-
throw new Error(`Failed to clone template ${
|
|
1928
|
+
throw new Error(`Failed to clone template from ${templateUrl}`);
|
|
2350
1929
|
}
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
if (clientRepoUrl.includes("visualstudio.com") || clientRepoUrl.includes("dev.azure.com")) {
|
|
2357
|
-
const parts = clientRepoUrl.split("/");
|
|
2358
|
-
projectName = parts[parts.length - 1] || "client-project";
|
|
2359
|
-
} else {
|
|
2360
|
-
projectName = clientRepoUrl.split("/").pop()?.replace(".git", "") || "client-project";
|
|
2361
|
-
}
|
|
2362
|
-
await $2`git clone ${clientRepoUrl} ${config.name}/workspace/${projectName}`.quiet();
|
|
2363
|
-
s.stop(`Client repo cloned: workspace/${projectName}`);
|
|
2364
|
-
} catch (error) {
|
|
2365
|
-
s.stop("Error cloning client repo");
|
|
2366
|
-
console.log(import_picocolors4.default.dim(" You can clone manually: cd workspace && git clone <url>"));
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
if (config.type !== "nimbus-core") {
|
|
2370
|
-
s.start("Configuring project...");
|
|
1930
|
+
try {
|
|
1931
|
+
await rm(join2(projectPath, ".git"), { recursive: true, force: true });
|
|
1932
|
+
} catch {}
|
|
1933
|
+
if (config.install) {
|
|
1934
|
+
s.start("Installing dependencies...");
|
|
2371
1935
|
try {
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
pkg.name = config.name;
|
|
2375
|
-
await Bun.write(pkgPath, JSON.stringify(pkg, null, 2));
|
|
2376
|
-
s.stop("Project configured");
|
|
1936
|
+
await $2`bun install`.cwd(projectPath).quiet();
|
|
1937
|
+
s.stop("Dependencies installed");
|
|
2377
1938
|
} catch (error) {
|
|
2378
|
-
s.stop("Error
|
|
2379
|
-
|
|
2380
|
-
}
|
|
2381
|
-
if (isPublicTemplate && config.theme) {
|
|
2382
|
-
s.start(`Setting theme to ${config.theme}...`);
|
|
2383
|
-
try {
|
|
2384
|
-
const layoutPath = `${config.name}/src/app/layout.tsx`;
|
|
2385
|
-
let layout = await Bun.file(layoutPath).text();
|
|
2386
|
-
layout = layout.replace(/defaultTheme="(dark|light|system)"/, `defaultTheme="${config.theme}"`);
|
|
2387
|
-
await Bun.write(layoutPath, layout);
|
|
2388
|
-
s.stop(`Theme set to ${config.theme}`);
|
|
2389
|
-
} catch {
|
|
2390
|
-
s.stop("Theme config skipped");
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
if (isPublicTemplate && config.aiAssistant) {
|
|
2394
|
-
const aiConfig = AI_CONFIGS[config.aiAssistant];
|
|
2395
|
-
if (aiConfig) {
|
|
2396
|
-
s.start(`Generating ${config.aiAssistant} config...`);
|
|
2397
|
-
try {
|
|
2398
|
-
const content = aiConfig.content(config.type);
|
|
2399
|
-
const filePath = `${config.name}/${aiConfig.filename}`;
|
|
2400
|
-
if (aiConfig.filename.includes("/")) {
|
|
2401
|
-
const dir = aiConfig.filename.split("/").slice(0, -1).join("/");
|
|
2402
|
-
await mkdir(`${config.name}/${dir}`, { recursive: true });
|
|
2403
|
-
}
|
|
2404
|
-
await Bun.write(filePath, content);
|
|
2405
|
-
s.stop(`${aiConfig.filename} created`);
|
|
2406
|
-
} catch {
|
|
2407
|
-
s.stop("AI config skipped");
|
|
2408
|
-
}
|
|
1939
|
+
s.stop("Error installing dependencies");
|
|
1940
|
+
console.log(import_picocolors3.default.yellow(" You can install manually with: bun install"));
|
|
2409
1941
|
}
|
|
2410
1942
|
}
|
|
2411
|
-
if (config.type === "fast+") {
|
|
2412
|
-
s.start("Configurando fast+ (SaaS)...");
|
|
2413
|
-
s.stop("Configuracao fast+ preparada");
|
|
2414
|
-
}
|
|
2415
1943
|
if (config.git) {
|
|
2416
1944
|
s.start("Initializing Git...");
|
|
2417
1945
|
try {
|
|
2418
|
-
|
|
2419
|
-
await $2`git
|
|
2420
|
-
await $2`git
|
|
2421
|
-
|
|
2422
|
-
await $2`git checkout -b staging`.cwd(cwd).quiet();
|
|
2423
|
-
await $2`git checkout -b develop`.cwd(cwd).quiet();
|
|
2424
|
-
s.stop("Git initialized (main -> staging -> develop)");
|
|
1946
|
+
await $2`git init`.cwd(projectPath).quiet();
|
|
1947
|
+
await $2`git add .`.cwd(projectPath).quiet();
|
|
1948
|
+
await $2`git commit -m "Initial commit"`.cwd(projectPath).quiet();
|
|
1949
|
+
s.stop("Git initialized");
|
|
2425
1950
|
} catch (error) {
|
|
2426
1951
|
s.stop("Error initializing Git");
|
|
2427
|
-
|
|
2428
|
-
if (config.github) {
|
|
2429
|
-
s.start("Creating GitHub repository...");
|
|
2430
|
-
try {
|
|
2431
|
-
const cwd = config.name;
|
|
2432
|
-
const repoName = config.githubOrg ? `${config.githubOrg}/${config.name}` : config.name;
|
|
2433
|
-
let visibility;
|
|
2434
|
-
if (config.type === "nimbus-core") {
|
|
2435
|
-
visibility = "--private";
|
|
2436
|
-
} else if (isPublicTemplate) {
|
|
2437
|
-
visibility = config.githubDescription === "public" ? "--public" : "--private";
|
|
2438
|
-
} else {
|
|
2439
|
-
visibility = config.githubOrg === "fast-by-nimbuslab" ? "--private" : "--public";
|
|
2440
|
-
}
|
|
2441
|
-
if (isPublicTemplate) {
|
|
2442
|
-
await $2`gh repo create ${repoName} ${visibility} --source . --remote origin`.cwd(cwd).quiet();
|
|
2443
|
-
} else {
|
|
2444
|
-
await $2`gh repo create ${repoName} ${visibility} --description ${config.githubDescription} --source . --remote origin`.cwd(cwd).quiet();
|
|
2445
|
-
}
|
|
2446
|
-
await $2`git checkout main`.cwd(cwd).quiet();
|
|
2447
|
-
await $2`git push -u origin main`.cwd(cwd).quiet();
|
|
2448
|
-
await $2`git checkout staging`.cwd(cwd).quiet();
|
|
2449
|
-
await $2`git push -u origin staging`.cwd(cwd).quiet();
|
|
2450
|
-
await $2`git checkout develop`.cwd(cwd).quiet();
|
|
2451
|
-
await $2`git push -u origin develop`.cwd(cwd).quiet();
|
|
2452
|
-
s.stop(`GitHub: ${repoName}`);
|
|
2453
|
-
} catch (error) {
|
|
2454
|
-
s.stop("Error creating GitHub repository");
|
|
2455
|
-
console.log(import_picocolors4.default.dim(" You can create manually with: gh repo create"));
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
if (config.railwayProject) {
|
|
2460
|
-
s.start(`Linkando Railway: ${config.railwayProject}...`);
|
|
2461
|
-
try {
|
|
2462
|
-
await $2`railway link -p ${config.railwayProject}`.cwd(config.name).quiet();
|
|
2463
|
-
s.stop(`Railway linkado: ${config.railwayProject}`);
|
|
2464
|
-
} catch (error) {
|
|
2465
|
-
s.stop("Error linking Railway");
|
|
2466
|
-
console.log(import_picocolors4.default.dim(" Run manually: railway link"));
|
|
1952
|
+
console.log(import_picocolors3.default.yellow(" You can initialize manually with: git init"));
|
|
2467
1953
|
}
|
|
2468
1954
|
}
|
|
2469
|
-
if (config.
|
|
2470
|
-
s.start(
|
|
1955
|
+
if (config.github && config.githubOrg) {
|
|
1956
|
+
s.start(`Creating GitHub repository...`);
|
|
2471
1957
|
try {
|
|
2472
|
-
const
|
|
2473
|
-
|
|
2474
|
-
|
|
1958
|
+
const repoName = config.name;
|
|
1959
|
+
const visibility = config.githubVisibility === "public" ? "--public" : "--private";
|
|
1960
|
+
const isPersonal = config.githubOrg && !config.githubOrg.includes("/");
|
|
1961
|
+
if (isPersonal) {
|
|
1962
|
+
await $2`gh repo create ${config.githubOrg}/${repoName} ${visibility} --source . --push`.cwd(projectPath).quiet();
|
|
1963
|
+
} else {
|
|
1964
|
+
await $2`gh repo create ${repoName} ${visibility} --source . --push`.cwd(projectPath).quiet();
|
|
1965
|
+
}
|
|
1966
|
+
const repoUrl = `https://github.com/${config.githubOrg}/${repoName}`;
|
|
1967
|
+
s.stop(`GitHub repository created`);
|
|
1968
|
+
console.log(import_picocolors3.default.green(` ${repoUrl}`));
|
|
2475
1969
|
} catch (error) {
|
|
2476
|
-
s.stop("Error creating
|
|
1970
|
+
s.stop("Error creating GitHub repository");
|
|
1971
|
+
console.log(import_picocolors3.default.dim(" You can create manually with: gh repo create"));
|
|
2477
1972
|
}
|
|
2478
1973
|
}
|
|
2479
|
-
if (config.
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
}
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
"
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
`RESEND_FROM_EMAIL=${config.resendFromEmail || ""}`,
|
|
2505
|
-
`CONTACT_EMAIL=${config.contactEmail || ""}`
|
|
2506
|
-
];
|
|
2507
|
-
if (config.railwayProject || config.railwayToken) {
|
|
2508
|
-
lines.push("");
|
|
2509
|
-
lines.push("# Railway");
|
|
2510
|
-
if (config.railwayProject) {
|
|
2511
|
-
lines.push(`# Project: ${config.railwayProject}`);
|
|
1974
|
+
if (config.aiAssistant && AI_CONFIGS[config.aiAssistant]) {
|
|
1975
|
+
const aiConfig = AI_CONFIGS[config.aiAssistant];
|
|
1976
|
+
const filePath = join2(projectPath, aiConfig.filename);
|
|
1977
|
+
if (aiConfig.filename.includes("/")) {
|
|
1978
|
+
const dir = join2(projectPath, aiConfig.filename.split("/")[0]);
|
|
1979
|
+
await mkdir(dir, { recursive: true });
|
|
1980
|
+
}
|
|
1981
|
+
await Bun.write(filePath, aiConfig.content(config.type));
|
|
1982
|
+
}
|
|
1983
|
+
s.start("Generating documentation...");
|
|
1984
|
+
const generatorConfig = {
|
|
1985
|
+
name: config.name,
|
|
1986
|
+
type: config.type,
|
|
1987
|
+
description: `A modern ${config.type === "landing" ? "landing page" : config.type === "app" ? "web application" : "monorepo"} built with Next.js 16, React 19, Tailwind CSS 4, and shadcn/ui.`,
|
|
1988
|
+
stack: {
|
|
1989
|
+
framework: "Next.js 16",
|
|
1990
|
+
styling: "Tailwind CSS 4",
|
|
1991
|
+
components: "shadcn/ui",
|
|
1992
|
+
forms: config.type !== "turborepo" ? "React Hook Form + Zod" : undefined,
|
|
1993
|
+
auth: config.type === "app" ? "Better Auth" : undefined
|
|
1994
|
+
},
|
|
1995
|
+
features: {
|
|
1996
|
+
auth: config.type === "app",
|
|
1997
|
+
contactForm: config.type === "landing",
|
|
1998
|
+
analytics: false
|
|
2512
1999
|
}
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
lines.push("");
|
|
2517
|
-
lines.push("# Database (fast+)");
|
|
2518
|
-
lines.push("DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app");
|
|
2519
|
-
lines.push("");
|
|
2520
|
-
lines.push("# Auth (fast+)");
|
|
2521
|
-
lines.push("BETTER_AUTH_SECRET=");
|
|
2522
|
-
lines.push("BETTER_AUTH_URL=http://localhost:3000");
|
|
2523
|
-
}
|
|
2524
|
-
return lines.join(`
|
|
2525
|
-
`) + `
|
|
2526
|
-
`;
|
|
2527
|
-
}
|
|
2528
|
-
function showNextSteps(config) {
|
|
2529
|
-
const isPublicTemplate = ["landing", "app", "turborepo"].includes(config.type);
|
|
2530
|
-
const needsSetup = config.type === "app";
|
|
2000
|
+
};
|
|
2001
|
+
await generateAIFriendlyDocs(projectPath, generatorConfig);
|
|
2002
|
+
s.stop("Documentation generated");
|
|
2531
2003
|
console.log();
|
|
2532
|
-
|
|
2004
|
+
Se(import_picocolors3.default.green(`\u2713 Project created: ${config.name}`));
|
|
2533
2005
|
console.log();
|
|
2534
|
-
console.log(
|
|
2535
|
-
|
|
2536
|
-
console.log();
|
|
2537
|
-
console.log(import_picocolors4.default.dim(" nimbus-core: Motor para projetos externos"));
|
|
2538
|
-
console.log();
|
|
2539
|
-
console.log(import_picocolors4.default.dim(" Para usar a Lola:"));
|
|
2540
|
-
console.log(` ${import_picocolors4.default.cyan("lola")}`);
|
|
2541
|
-
console.log();
|
|
2542
|
-
console.log(import_picocolors4.default.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"));
|
|
2543
|
-
console.log();
|
|
2544
|
-
if (config.github) {
|
|
2545
|
-
const repoUrl = `https://github.com/nimbuslab/${config.name}`;
|
|
2546
|
-
console.log(import_picocolors4.default.green(` GitHub (private): ${repoUrl}`));
|
|
2547
|
-
console.log();
|
|
2548
|
-
}
|
|
2549
|
-
console.log(import_picocolors4.default.dim(" Docs: See README.md for full instructions"));
|
|
2550
|
-
console.log();
|
|
2551
|
-
return;
|
|
2552
|
-
}
|
|
2006
|
+
console.log(import_picocolors3.default.bold("Next steps:"));
|
|
2007
|
+
console.log(` ${import_picocolors3.default.cyan(`cd ${config.name}`)}`);
|
|
2553
2008
|
if (!config.install) {
|
|
2554
|
-
console.log(` ${
|
|
2009
|
+
console.log(` ${import_picocolors3.default.cyan("bun install")}`);
|
|
2555
2010
|
}
|
|
2556
|
-
|
|
2557
|
-
console.log(` ${import_picocolors4.default.cyan("bun")} setup`);
|
|
2558
|
-
}
|
|
2559
|
-
console.log(` ${import_picocolors4.default.cyan("bun")} dev`);
|
|
2011
|
+
console.log(` ${import_picocolors3.default.cyan("bun dev")}`);
|
|
2560
2012
|
console.log();
|
|
2561
|
-
if (
|
|
2562
|
-
console.log(
|
|
2563
|
-
console.log(
|
|
2564
|
-
console.log(import_picocolors4.default.dim(" - Run database migrations"));
|
|
2565
|
-
console.log(import_picocolors4.default.dim(" - Create demo user (demo@example.com / demo1234)"));
|
|
2013
|
+
if (config.type === "app") {
|
|
2014
|
+
console.log(import_picocolors3.default.dim(" For database setup:"));
|
|
2015
|
+
console.log(` ${import_picocolors3.default.cyan("bun setup")}`);
|
|
2566
2016
|
console.log();
|
|
2567
2017
|
}
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2018
|
+
}
|
|
2019
|
+
async function create(args) {
|
|
2020
|
+
const checkCmd = process.platform === "win32" ? "where" : "which";
|
|
2021
|
+
console.log(import_picocolors3.default.dim("Checking dependencies..."));
|
|
2022
|
+
const hasGit = await $2`${checkCmd} git`.quiet().nothrow().then((r2) => r2.exitCode === 0);
|
|
2023
|
+
const hasBun = await $2`${checkCmd} bun`.quiet().nothrow().then((r2) => r2.exitCode === 0);
|
|
2024
|
+
if (!hasGit) {
|
|
2025
|
+
console.log(import_picocolors3.default.red("\u2717 Git not found"));
|
|
2026
|
+
console.log(import_picocolors3.default.dim(" Install from: https://git-scm.com"));
|
|
2027
|
+
process.exit(1);
|
|
2575
2028
|
}
|
|
2576
|
-
if (
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
if (config.aiAssistant) {
|
|
2581
|
-
const aiConfig = AI_CONFIGS[config.aiAssistant];
|
|
2582
|
-
if (aiConfig) {
|
|
2583
|
-
console.log(import_picocolors4.default.dim(` AI config: ${aiConfig.filename}`));
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
if (config.theme !== "dark" || config.aiAssistant) {
|
|
2587
|
-
console.log();
|
|
2588
|
-
}
|
|
2029
|
+
if (!hasBun) {
|
|
2030
|
+
console.log(import_picocolors3.default.red("\u2717 Bun not found"));
|
|
2031
|
+
console.log(import_picocolors3.default.dim(" Install from: https://bun.sh"));
|
|
2032
|
+
process.exit(1);
|
|
2589
2033
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2034
|
+
console.log(import_picocolors3.default.green("\u2713 Dependencies OK"));
|
|
2035
|
+
console.log();
|
|
2036
|
+
const { flags, projectName } = parseFlags(args);
|
|
2037
|
+
Ie(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" Create Next.js Project ")));
|
|
2038
|
+
let config;
|
|
2039
|
+
if (flags.yes && projectName && (flags.landing || flags.app || flags.turborepo)) {
|
|
2040
|
+
const type = flags.landing ? "landing" : flags.app ? "app" : "turborepo";
|
|
2041
|
+
config = {
|
|
2042
|
+
name: projectName,
|
|
2043
|
+
type,
|
|
2044
|
+
git: !flags.noGit,
|
|
2045
|
+
install: !flags.noInstall,
|
|
2046
|
+
github: false,
|
|
2047
|
+
githubOrg: null,
|
|
2048
|
+
githubVisibility: "public",
|
|
2049
|
+
theme: "dark",
|
|
2050
|
+
aiAssistant: null,
|
|
2051
|
+
customTemplate: flags.template
|
|
2052
|
+
};
|
|
2053
|
+
console.log(import_picocolors3.default.dim(` Project: ${projectName}`));
|
|
2054
|
+
console.log(import_picocolors3.default.dim(` Type: ${type}`));
|
|
2055
|
+
console.log(import_picocolors3.default.dim(` Git: ${config.git ? "yes" : "no"}`));
|
|
2056
|
+
console.log(import_picocolors3.default.dim(` Install: ${config.install ? "yes" : "no"}`));
|
|
2057
|
+
if (flags.template)
|
|
2058
|
+
console.log(import_picocolors3.default.dim(` Template: ${flags.template}`));
|
|
2600
2059
|
console.log();
|
|
2601
|
-
}
|
|
2602
|
-
if (!isPublicTemplate) {
|
|
2603
|
-
if (config.resendApiKey || config.stagingUrl) {
|
|
2604
|
-
console.log(import_picocolors4.default.green(" .env configured!"));
|
|
2605
|
-
console.log();
|
|
2606
|
-
} else {
|
|
2607
|
-
console.log(import_picocolors4.default.yellow(" Tip: Configure .env manually or use 'bun setup'."));
|
|
2608
|
-
console.log();
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
if (isPublicTemplate) {
|
|
2612
|
-
console.log(import_picocolors4.default.dim(" Open source template (MIT) by nimbuslab"));
|
|
2613
|
-
console.log(import_picocolors4.default.dim(` https://github.com/nimbuslab/create-next-${config.type === "turborepo" ? "turborepo" : config.type}`));
|
|
2614
2060
|
} else {
|
|
2615
|
-
|
|
2061
|
+
config = await promptConfig(projectName, flags);
|
|
2616
2062
|
}
|
|
2617
|
-
|
|
2063
|
+
if (pD(config)) {
|
|
2064
|
+
xe("Operation cancelled");
|
|
2065
|
+
process.exit(0);
|
|
2066
|
+
}
|
|
2067
|
+
await createProject(config);
|
|
2618
2068
|
}
|
|
2619
2069
|
|
|
2620
2070
|
// src/commands/analyze.ts
|
|
2621
|
-
var
|
|
2071
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
2622
2072
|
import { existsSync, readFileSync } from "fs";
|
|
2623
2073
|
import { join as join3 } from "path";
|
|
2624
2074
|
function detectPackageManager(dir) {
|
|
@@ -2744,12 +2194,12 @@ async function analyze(args) {
|
|
|
2744
2194
|
const targetDir = args[0] || ".";
|
|
2745
2195
|
const absoluteDir = targetDir.startsWith("/") ? targetDir : join3(process.cwd(), targetDir);
|
|
2746
2196
|
console.log();
|
|
2747
|
-
console.log(
|
|
2197
|
+
console.log(import_picocolors4.default.cyan(" Analisando projeto..."));
|
|
2748
2198
|
console.log();
|
|
2749
2199
|
const pkgPath = join3(absoluteDir, "package.json");
|
|
2750
2200
|
if (!existsSync(pkgPath)) {
|
|
2751
|
-
console.log(
|
|
2752
|
-
console.log(
|
|
2201
|
+
console.log(import_picocolors4.default.red(" Erro: package.json nao encontrado"));
|
|
2202
|
+
console.log(import_picocolors4.default.dim(` Diretorio: ${absoluteDir}`));
|
|
2753
2203
|
process.exit(1);
|
|
2754
2204
|
}
|
|
2755
2205
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
@@ -2772,36 +2222,36 @@ async function analyze(args) {
|
|
|
2772
2222
|
recommendations: []
|
|
2773
2223
|
};
|
|
2774
2224
|
result.recommendations = generateRecommendations(result);
|
|
2775
|
-
console.log(
|
|
2225
|
+
console.log(import_picocolors4.default.bold(" Projeto: ") + import_picocolors4.default.cyan(result.name) + import_picocolors4.default.dim(` v${result.version}`));
|
|
2776
2226
|
console.log();
|
|
2777
|
-
console.log(
|
|
2778
|
-
console.log(` Framework: ${result.framework ?
|
|
2779
|
-
console.log(` Styling: ${result.styling.map((s) =>
|
|
2780
|
-
console.log(` Package Manager: ${result.packageManager === "bun" ?
|
|
2781
|
-
console.log(` TypeScript: ${result.typescript ?
|
|
2782
|
-
console.log(` Monorepo: ${result.monorepo ?
|
|
2783
|
-
console.log(` Auth: ${result.auth ?
|
|
2784
|
-
console.log(` Database: ${result.database ?
|
|
2227
|
+
console.log(import_picocolors4.default.bold(" Stack Detectada:"));
|
|
2228
|
+
console.log(` Framework: ${result.framework ? import_picocolors4.default.green(result.framework + "@" + result.frameworkVersion) : import_picocolors4.default.dim("nenhum")}`);
|
|
2229
|
+
console.log(` Styling: ${result.styling.map((s) => import_picocolors4.default.green(s)).join(", ")}`);
|
|
2230
|
+
console.log(` Package Manager: ${result.packageManager === "bun" ? import_picocolors4.default.green(result.packageManager) : import_picocolors4.default.yellow(result.packageManager)}`);
|
|
2231
|
+
console.log(` TypeScript: ${result.typescript ? import_picocolors4.default.green("sim") : import_picocolors4.default.dim("nao")}`);
|
|
2232
|
+
console.log(` Monorepo: ${result.monorepo ? import_picocolors4.default.green(result.monorepo) : import_picocolors4.default.dim("nao")}`);
|
|
2233
|
+
console.log(` Auth: ${result.auth ? import_picocolors4.default.green(result.auth) : import_picocolors4.default.dim("nenhum")}`);
|
|
2234
|
+
console.log(` Database: ${result.database ? import_picocolors4.default.green(result.database) : import_picocolors4.default.dim("nenhum")}`);
|
|
2785
2235
|
console.log();
|
|
2786
2236
|
if (result.recommendations.length > 0) {
|
|
2787
|
-
console.log(
|
|
2237
|
+
console.log(import_picocolors4.default.bold(" Recomendacoes:"));
|
|
2788
2238
|
result.recommendations.forEach((rec, i) => {
|
|
2789
|
-
console.log(
|
|
2239
|
+
console.log(import_picocolors4.default.yellow(` ${i + 1}. ${rec}`));
|
|
2790
2240
|
});
|
|
2791
2241
|
console.log();
|
|
2792
2242
|
} else {
|
|
2793
|
-
console.log(
|
|
2243
|
+
console.log(import_picocolors4.default.green(" Projeto ja esta na stack recomendada!"));
|
|
2794
2244
|
console.log();
|
|
2795
2245
|
}
|
|
2796
2246
|
if (args.includes("--json")) {
|
|
2797
|
-
console.log(
|
|
2247
|
+
console.log(import_picocolors4.default.dim(" JSON:"));
|
|
2798
2248
|
console.log(JSON.stringify(result, null, 2));
|
|
2799
2249
|
}
|
|
2800
2250
|
return result;
|
|
2801
2251
|
}
|
|
2802
2252
|
|
|
2803
2253
|
// src/commands/upgrade.ts
|
|
2804
|
-
var
|
|
2254
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
2805
2255
|
var UPGRADE_PLANS = {
|
|
2806
2256
|
next: (current) => {
|
|
2807
2257
|
const major = parseInt(current.replace(/[^0-9]/g, "").slice(0, 2));
|
|
@@ -2918,10 +2368,10 @@ async function upgrade(args) {
|
|
|
2918
2368
|
const target = args.find((a) => !a.startsWith("-"));
|
|
2919
2369
|
console.log();
|
|
2920
2370
|
if (showPlan || !target) {
|
|
2921
|
-
console.log(
|
|
2371
|
+
console.log(import_picocolors5.default.cyan(" Analisando projeto para plano de upgrade..."));
|
|
2922
2372
|
console.log();
|
|
2923
2373
|
const analysis = await analyze([".", "--quiet"]);
|
|
2924
|
-
console.log(
|
|
2374
|
+
console.log(import_picocolors5.default.bold(" Upgrades Disponiveis:"));
|
|
2925
2375
|
console.log();
|
|
2926
2376
|
let hasUpgrades = false;
|
|
2927
2377
|
if (analysis.frameworkVersion && analysis.framework === "nextjs") {
|
|
@@ -2976,44 +2426,44 @@ async function upgrade(args) {
|
|
|
2976
2426
|
}
|
|
2977
2427
|
}
|
|
2978
2428
|
if (!hasUpgrades) {
|
|
2979
|
-
console.log(
|
|
2429
|
+
console.log(import_picocolors5.default.green(" Projeto ja esta atualizado!"));
|
|
2980
2430
|
}
|
|
2981
2431
|
console.log();
|
|
2982
|
-
console.log(
|
|
2983
|
-
console.log(
|
|
2984
|
-
console.log(
|
|
2985
|
-
console.log(
|
|
2432
|
+
console.log(import_picocolors5.default.dim(" Para executar um upgrade especifico:"));
|
|
2433
|
+
console.log(import_picocolors5.default.dim(" nimbus upgrade next"));
|
|
2434
|
+
console.log(import_picocolors5.default.dim(" nimbus upgrade tailwind"));
|
|
2435
|
+
console.log(import_picocolors5.default.dim(" nimbus upgrade bun"));
|
|
2986
2436
|
console.log();
|
|
2987
2437
|
return;
|
|
2988
2438
|
}
|
|
2989
|
-
console.log(
|
|
2990
|
-
console.log(
|
|
2439
|
+
console.log(import_picocolors5.default.yellow(` Upgrade ${target} ainda nao implementado.`));
|
|
2440
|
+
console.log(import_picocolors5.default.dim(" Por enquanto, siga os passos do --plan manualmente."));
|
|
2991
2441
|
console.log();
|
|
2992
2442
|
}
|
|
2993
2443
|
function printUpgradePlan(name, plan) {
|
|
2994
2444
|
const complexityColor = {
|
|
2995
|
-
low:
|
|
2996
|
-
medium:
|
|
2997
|
-
high:
|
|
2445
|
+
low: import_picocolors5.default.green,
|
|
2446
|
+
medium: import_picocolors5.default.yellow,
|
|
2447
|
+
high: import_picocolors5.default.red
|
|
2998
2448
|
};
|
|
2999
|
-
console.log(` ${
|
|
3000
|
-
console.log(` ${
|
|
3001
|
-
console.log(` ${
|
|
2449
|
+
console.log(` ${import_picocolors5.default.bold(name)}`);
|
|
2450
|
+
console.log(` ${import_picocolors5.default.dim("Atual:")} ${plan.current} ${import_picocolors5.default.dim("->")} ${import_picocolors5.default.cyan(plan.target)}`);
|
|
2451
|
+
console.log(` ${import_picocolors5.default.dim("Complexidade:")} ${complexityColor[plan.complexity](plan.complexity)}`);
|
|
3002
2452
|
console.log();
|
|
3003
|
-
console.log(` ${
|
|
2453
|
+
console.log(` ${import_picocolors5.default.dim("Breaking Changes:")}`);
|
|
3004
2454
|
plan.breakingChanges.forEach((bc) => {
|
|
3005
|
-
console.log(` ${
|
|
2455
|
+
console.log(` ${import_picocolors5.default.yellow("!")} ${bc}`);
|
|
3006
2456
|
});
|
|
3007
2457
|
console.log();
|
|
3008
|
-
console.log(` ${
|
|
2458
|
+
console.log(` ${import_picocolors5.default.dim("Passos:")}`);
|
|
3009
2459
|
plan.steps.forEach((step, i) => {
|
|
3010
|
-
console.log(` ${
|
|
2460
|
+
console.log(` ${import_picocolors5.default.dim(`${i + 1}.`)} ${step}`);
|
|
3011
2461
|
});
|
|
3012
2462
|
console.log();
|
|
3013
2463
|
}
|
|
3014
2464
|
|
|
3015
2465
|
// src/commands/update.ts
|
|
3016
|
-
var
|
|
2466
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
3017
2467
|
import { execSync, spawnSync } from "child_process";
|
|
3018
2468
|
var PACKAGE_NAME = "@nimbuslab/cli";
|
|
3019
2469
|
function hasBunInstall() {
|
|
@@ -3149,7 +2599,7 @@ async function update(args) {
|
|
|
3149
2599
|
const filteredArgs = args.filter((a) => a !== "--force" && a !== "-f");
|
|
3150
2600
|
const flag = filteredArgs[0];
|
|
3151
2601
|
if (flag === "--list" || flag === "-l") {
|
|
3152
|
-
Ie(
|
|
2602
|
+
Ie(import_picocolors6.default.cyan("Versoes disponiveis"));
|
|
3153
2603
|
const spinner2 = Y2();
|
|
3154
2604
|
spinner2.start("Buscando versoes...");
|
|
3155
2605
|
const versions = await getAvailableVersions();
|
|
@@ -3161,29 +2611,29 @@ async function update(args) {
|
|
|
3161
2611
|
const current = getCurrentVersion();
|
|
3162
2612
|
const pm2 = detectPackageManager2();
|
|
3163
2613
|
console.log();
|
|
3164
|
-
console.log(
|
|
2614
|
+
console.log(import_picocolors6.default.bold("Ultimas 10 versoes:"));
|
|
3165
2615
|
versions.slice(0, 10).forEach((v2, i) => {
|
|
3166
2616
|
const isCurrent = v2 === current;
|
|
3167
|
-
const prefix = isCurrent ?
|
|
3168
|
-
const suffix = isCurrent ?
|
|
3169
|
-
const isLatest = i === 0 ?
|
|
2617
|
+
const prefix = isCurrent ? import_picocolors6.default.green("-> ") : " ";
|
|
2618
|
+
const suffix = isCurrent ? import_picocolors6.default.dim(" (instalada)") : "";
|
|
2619
|
+
const isLatest = i === 0 ? import_picocolors6.default.yellow(" (latest)") : "";
|
|
3170
2620
|
console.log(`${prefix}${v2}${suffix}${isLatest}`);
|
|
3171
2621
|
});
|
|
3172
2622
|
console.log();
|
|
3173
|
-
console.log(
|
|
3174
|
-
console.log(
|
|
3175
|
-
console.log(
|
|
3176
|
-
console.log(
|
|
2623
|
+
console.log(import_picocolors6.default.dim(`Total: ${versions.length} versoes`));
|
|
2624
|
+
console.log(import_picocolors6.default.dim(`Package manager detectado: ${pm2 === "unknown" ? "nenhum" : pm2}`));
|
|
2625
|
+
console.log(import_picocolors6.default.dim(`Instalar versao especifica: nimbus update <versao>`));
|
|
2626
|
+
console.log(import_picocolors6.default.dim(`Forcar reinstalacao: nimbus update --force`));
|
|
3177
2627
|
return;
|
|
3178
2628
|
}
|
|
3179
2629
|
const targetVersion = flag || "latest";
|
|
3180
2630
|
const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-");
|
|
3181
|
-
Ie(
|
|
2631
|
+
Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
|
|
3182
2632
|
const spinner = Y2();
|
|
3183
2633
|
spinner.start("Verificando instalacoes...");
|
|
3184
2634
|
const cleanup = cleanupDuplicateInstalls();
|
|
3185
2635
|
if (cleanup.cleaned) {
|
|
3186
|
-
spinner.stop(
|
|
2636
|
+
spinner.stop(import_picocolors6.default.yellow(cleanup.message));
|
|
3187
2637
|
} else {
|
|
3188
2638
|
spinner.stop("OK");
|
|
3189
2639
|
}
|
|
@@ -3201,7 +2651,7 @@ async function update(args) {
|
|
|
3201
2651
|
spinner.stop(`Ultima versao: ${latestVersion || "desconhecida"}`);
|
|
3202
2652
|
if (!forceFlag && latestVersion && latestVersion === currentVersion) {
|
|
3203
2653
|
M2.success("Voce ja esta na ultima versao!");
|
|
3204
|
-
console.log(
|
|
2654
|
+
console.log(import_picocolors6.default.dim(" Use --force para reinstalar"));
|
|
3205
2655
|
return;
|
|
3206
2656
|
}
|
|
3207
2657
|
}
|
|
@@ -3239,33 +2689,33 @@ async function update(args) {
|
|
|
3239
2689
|
const isWindows = process.platform === "win32";
|
|
3240
2690
|
if (isWindows) {
|
|
3241
2691
|
console.log();
|
|
3242
|
-
console.log(
|
|
2692
|
+
console.log(import_picocolors6.default.yellow(" Reinicie o terminal para aplicar a atualizacao."));
|
|
3243
2693
|
} else if (isUsingFnm()) {
|
|
3244
2694
|
console.log();
|
|
3245
|
-
console.log(
|
|
3246
|
-
console.log(
|
|
3247
|
-
console.log(
|
|
2695
|
+
console.log(import_picocolors6.default.yellow(" fnm detectado - execute para aplicar:"));
|
|
2696
|
+
console.log(import_picocolors6.default.cyan(" hash -r"));
|
|
2697
|
+
console.log(import_picocolors6.default.dim(" Ou abra um novo terminal."));
|
|
3248
2698
|
}
|
|
3249
|
-
Se(
|
|
2699
|
+
Se(import_picocolors6.default.green("Pronto!"));
|
|
3250
2700
|
} catch (error) {
|
|
3251
2701
|
spinner.stop("Erro na atualizacao");
|
|
3252
2702
|
const err = error;
|
|
3253
2703
|
M2.error("Falha ao atualizar");
|
|
3254
2704
|
if (err.stderr) {
|
|
3255
|
-
console.log(
|
|
2705
|
+
console.log(import_picocolors6.default.dim(err.stderr));
|
|
3256
2706
|
}
|
|
3257
2707
|
console.log();
|
|
3258
|
-
console.log(
|
|
2708
|
+
console.log(import_picocolors6.default.yellow("Tente manualmente:"));
|
|
3259
2709
|
if (pm === "bun") {
|
|
3260
|
-
console.log(
|
|
2710
|
+
console.log(import_picocolors6.default.cyan(` bun add -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
|
|
3261
2711
|
} else {
|
|
3262
|
-
console.log(
|
|
2712
|
+
console.log(import_picocolors6.default.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
|
|
3263
2713
|
}
|
|
3264
2714
|
}
|
|
3265
2715
|
}
|
|
3266
2716
|
|
|
3267
2717
|
// src/commands/setup-node.ts
|
|
3268
|
-
var
|
|
2718
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
3269
2719
|
import { execSync as execSync2, spawnSync as spawnSync2 } from "child_process";
|
|
3270
2720
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
3271
2721
|
import { homedir } from "os";
|
|
@@ -3534,7 +2984,7 @@ async function removeFnm(fnm) {
|
|
|
3534
2984
|
const scoopCheck = spawnSync2("scoop", ["list"], { encoding: "utf-8", shell: true });
|
|
3535
2985
|
if (scoopCheck.stdout?.includes("fnm")) {
|
|
3536
2986
|
execSync2("scoop uninstall fnm", { stdio: "pipe" });
|
|
3537
|
-
console.log(
|
|
2987
|
+
console.log(import_picocolors7.default.dim(" Removido via Scoop"));
|
|
3538
2988
|
removed = true;
|
|
3539
2989
|
}
|
|
3540
2990
|
} catch {}
|
|
@@ -3543,7 +2993,7 @@ async function removeFnm(fnm) {
|
|
|
3543
2993
|
const chocoCheck = spawnSync2("choco", ["list", "--local-only"], { encoding: "utf-8", shell: true });
|
|
3544
2994
|
if (chocoCheck.stdout?.includes("fnm")) {
|
|
3545
2995
|
execSync2("choco uninstall fnm -y", { stdio: "pipe" });
|
|
3546
|
-
console.log(
|
|
2996
|
+
console.log(import_picocolors7.default.dim(" Removido via Chocolatey"));
|
|
3547
2997
|
removed = true;
|
|
3548
2998
|
}
|
|
3549
2999
|
} catch {}
|
|
@@ -3553,7 +3003,7 @@ async function removeFnm(fnm) {
|
|
|
3553
3003
|
const wingetCheck = spawnSync2("winget", ["list", "--name", "fnm"], { encoding: "utf-8", shell: true });
|
|
3554
3004
|
if (wingetCheck.stdout?.includes("fnm")) {
|
|
3555
3005
|
execSync2("winget uninstall fnm --silent", { stdio: "pipe" });
|
|
3556
|
-
console.log(
|
|
3006
|
+
console.log(import_picocolors7.default.dim(" Removido via winget"));
|
|
3557
3007
|
removed = true;
|
|
3558
3008
|
}
|
|
3559
3009
|
} catch {}
|
|
@@ -3569,12 +3019,12 @@ async function removeFnm(fnm) {
|
|
|
3569
3019
|
if (existsSync2(dir)) {
|
|
3570
3020
|
try {
|
|
3571
3021
|
execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: "cmd.exe" });
|
|
3572
|
-
console.log(
|
|
3022
|
+
console.log(import_picocolors7.default.dim(` Removido ${dir}`));
|
|
3573
3023
|
removed = true;
|
|
3574
3024
|
} catch {
|
|
3575
3025
|
try {
|
|
3576
3026
|
execSync2(`powershell -Command "Remove-Item -Path '${dir}' -Recurse -Force"`, { stdio: "pipe" });
|
|
3577
|
-
console.log(
|
|
3027
|
+
console.log(import_picocolors7.default.dim(` Removido ${dir}`));
|
|
3578
3028
|
removed = true;
|
|
3579
3029
|
} catch {}
|
|
3580
3030
|
}
|
|
@@ -3583,16 +3033,16 @@ async function removeFnm(fnm) {
|
|
|
3583
3033
|
try {
|
|
3584
3034
|
execSync2(`powershell -Command "[Environment]::SetEnvironmentVariable('FNM_DIR', $null, 'User')"`, { stdio: "pipe" });
|
|
3585
3035
|
execSync2(`powershell -Command "[Environment]::SetEnvironmentVariable('FNM_MULTISHELL_PATH', $null, 'User')"`, { stdio: "pipe" });
|
|
3586
|
-
console.log(
|
|
3036
|
+
console.log(import_picocolors7.default.dim(" Variaveis de ambiente FNM removidas"));
|
|
3587
3037
|
removed = true;
|
|
3588
3038
|
} catch {}
|
|
3589
3039
|
for (const configFile of fnm.configFiles || []) {
|
|
3590
3040
|
if (removeFnmFromConfig(configFile)) {
|
|
3591
|
-
console.log(
|
|
3041
|
+
console.log(import_picocolors7.default.dim(` Removido de ${configFile}`));
|
|
3592
3042
|
removed = true;
|
|
3593
3043
|
}
|
|
3594
3044
|
}
|
|
3595
|
-
spinner.stop(removed ? "fnm removido!" :
|
|
3045
|
+
spinner.stop(removed ? "fnm removido!" : import_picocolors7.default.yellow("fnm nao encontrado"));
|
|
3596
3046
|
return removed;
|
|
3597
3047
|
} else {
|
|
3598
3048
|
spinner.start("Removendo fnm...");
|
|
@@ -3601,13 +3051,13 @@ async function removeFnm(fnm) {
|
|
|
3601
3051
|
const brewCheck = spawnSync2("brew", ["list", "fnm"], { encoding: "utf-8", shell: true });
|
|
3602
3052
|
if (brewCheck.status === 0) {
|
|
3603
3053
|
execSync2("brew uninstall fnm", { stdio: "pipe" });
|
|
3604
|
-
console.log(
|
|
3054
|
+
console.log(import_picocolors7.default.dim(" Removido via Homebrew"));
|
|
3605
3055
|
removed = true;
|
|
3606
3056
|
}
|
|
3607
3057
|
} catch {}
|
|
3608
3058
|
for (const configFile of fnm.configFiles || []) {
|
|
3609
3059
|
if (removeFnmFromConfig(configFile)) {
|
|
3610
|
-
console.log(
|
|
3060
|
+
console.log(import_picocolors7.default.dim(` Removido de ${configFile}`));
|
|
3611
3061
|
removed = true;
|
|
3612
3062
|
}
|
|
3613
3063
|
}
|
|
@@ -3618,7 +3068,7 @@ async function removeFnm(fnm) {
|
|
|
3618
3068
|
for (const fnmDir of fnmDirs) {
|
|
3619
3069
|
if (existsSync2(fnmDir)) {
|
|
3620
3070
|
execSync2(`rm -rf "${fnmDir}"`, { stdio: "pipe" });
|
|
3621
|
-
console.log(
|
|
3071
|
+
console.log(import_picocolors7.default.dim(` Removido ${fnmDir}`));
|
|
3622
3072
|
removed = true;
|
|
3623
3073
|
}
|
|
3624
3074
|
}
|
|
@@ -3629,7 +3079,7 @@ async function removeFnm(fnm) {
|
|
|
3629
3079
|
for (const bin of fnmBins) {
|
|
3630
3080
|
if (existsSync2(bin)) {
|
|
3631
3081
|
execSync2(`rm -f "${bin}"`, { stdio: "pipe" });
|
|
3632
|
-
console.log(
|
|
3082
|
+
console.log(import_picocolors7.default.dim(` Removido ${bin}`));
|
|
3633
3083
|
removed = true;
|
|
3634
3084
|
}
|
|
3635
3085
|
}
|
|
@@ -3637,7 +3087,7 @@ async function removeFnm(fnm) {
|
|
|
3637
3087
|
return removed;
|
|
3638
3088
|
}
|
|
3639
3089
|
} catch (error) {
|
|
3640
|
-
spinner.stop(
|
|
3090
|
+
spinner.stop(import_picocolors7.default.red("Erro ao remover fnm"));
|
|
3641
3091
|
return false;
|
|
3642
3092
|
}
|
|
3643
3093
|
}
|
|
@@ -3651,7 +3101,7 @@ async function removeNvm(nvm) {
|
|
|
3651
3101
|
const wingetCheck = spawnSync2("winget", ["list", "--name", "nvm"], { encoding: "utf-8", shell: true });
|
|
3652
3102
|
if (wingetCheck.stdout?.toLowerCase().includes("nvm")) {
|
|
3653
3103
|
execSync2("winget uninstall nvm --silent", { stdio: "pipe" });
|
|
3654
|
-
console.log(
|
|
3104
|
+
console.log(import_picocolors7.default.dim(" Removido via winget"));
|
|
3655
3105
|
removed = true;
|
|
3656
3106
|
}
|
|
3657
3107
|
} catch {}
|
|
@@ -3664,46 +3114,46 @@ async function removeNvm(nvm) {
|
|
|
3664
3114
|
if (existsSync2(dir)) {
|
|
3665
3115
|
try {
|
|
3666
3116
|
execSync2(`rmdir /s /q "${dir}"`, { stdio: "pipe", shell: "cmd.exe" });
|
|
3667
|
-
console.log(
|
|
3117
|
+
console.log(import_picocolors7.default.dim(` Removido ${dir}`));
|
|
3668
3118
|
removed = true;
|
|
3669
3119
|
} catch {}
|
|
3670
3120
|
}
|
|
3671
3121
|
}
|
|
3672
3122
|
for (const configFile of nvm.configFiles || []) {
|
|
3673
3123
|
if (removeNvmFromConfig(configFile)) {
|
|
3674
|
-
console.log(
|
|
3124
|
+
console.log(import_picocolors7.default.dim(` Removido de ${configFile}`));
|
|
3675
3125
|
removed = true;
|
|
3676
3126
|
}
|
|
3677
3127
|
}
|
|
3678
3128
|
if (!removed) {
|
|
3679
|
-
console.log(
|
|
3129
|
+
console.log(import_picocolors7.default.yellow(`
|
|
3680
3130
|
nvm-windows pode precisar de remocao manual:`));
|
|
3681
|
-
console.log(
|
|
3682
|
-
console.log(
|
|
3683
|
-
console.log(
|
|
3131
|
+
console.log(import_picocolors7.default.dim(" 1. Abra 'Adicionar ou remover programas'"));
|
|
3132
|
+
console.log(import_picocolors7.default.dim(" 2. Procure por 'NVM for Windows'"));
|
|
3133
|
+
console.log(import_picocolors7.default.dim(" 3. Clique em Desinstalar"));
|
|
3684
3134
|
}
|
|
3685
|
-
spinner.stop(removed ? "nvm removido!" :
|
|
3135
|
+
spinner.stop(removed ? "nvm removido!" : import_picocolors7.default.yellow("Verifique manualmente"));
|
|
3686
3136
|
return removed;
|
|
3687
3137
|
} else {
|
|
3688
3138
|
spinner.start("Removendo nvm...");
|
|
3689
3139
|
let removed = false;
|
|
3690
3140
|
for (const configFile of nvm.configFiles || []) {
|
|
3691
3141
|
if (removeNvmFromConfig(configFile)) {
|
|
3692
|
-
console.log(
|
|
3142
|
+
console.log(import_picocolors7.default.dim(` Removido de ${configFile}`));
|
|
3693
3143
|
removed = true;
|
|
3694
3144
|
}
|
|
3695
3145
|
}
|
|
3696
3146
|
const nvmDir = process.env.NVM_DIR || join4(HOME, ".nvm");
|
|
3697
3147
|
if (existsSync2(nvmDir)) {
|
|
3698
3148
|
execSync2(`rm -rf "${nvmDir}"`, { stdio: "pipe" });
|
|
3699
|
-
console.log(
|
|
3149
|
+
console.log(import_picocolors7.default.dim(` Removido ${nvmDir}`));
|
|
3700
3150
|
removed = true;
|
|
3701
3151
|
}
|
|
3702
3152
|
spinner.stop(removed ? "nvm removido!" : "nvm nao encontrado");
|
|
3703
3153
|
return removed;
|
|
3704
3154
|
}
|
|
3705
3155
|
} catch (error) {
|
|
3706
|
-
spinner.stop(
|
|
3156
|
+
spinner.stop(import_picocolors7.default.red("Erro ao remover nvm"));
|
|
3707
3157
|
return false;
|
|
3708
3158
|
}
|
|
3709
3159
|
}
|
|
@@ -3723,13 +3173,13 @@ async function installVolta() {
|
|
|
3723
3173
|
});
|
|
3724
3174
|
spinner.stop("Volta instalado!");
|
|
3725
3175
|
const voltaPath = join4(HOME, ".volta", "bin");
|
|
3726
|
-
console.log(
|
|
3176
|
+
console.log(import_picocolors7.default.dim(` Adicionando ${voltaPath} ao PATH...`));
|
|
3727
3177
|
try {
|
|
3728
3178
|
execSync2(`setx PATH "%PATH%;${voltaPath}"`, { stdio: "pipe", shell: "cmd.exe" });
|
|
3729
3179
|
} catch {}
|
|
3730
3180
|
return true;
|
|
3731
3181
|
} catch (e2) {
|
|
3732
|
-
spinner.stop(
|
|
3182
|
+
spinner.stop(import_picocolors7.default.yellow("winget falhou, tentando outro metodo..."));
|
|
3733
3183
|
}
|
|
3734
3184
|
}
|
|
3735
3185
|
const chocoCheck = spawnSync2(CHECK_CMD, ["choco"], { encoding: "utf-8", shell: true });
|
|
@@ -3740,7 +3190,7 @@ async function installVolta() {
|
|
|
3740
3190
|
spinner.stop("Volta instalado!");
|
|
3741
3191
|
return true;
|
|
3742
3192
|
} catch {
|
|
3743
|
-
spinner.stop(
|
|
3193
|
+
spinner.stop(import_picocolors7.default.yellow("Chocolatey falhou"));
|
|
3744
3194
|
}
|
|
3745
3195
|
}
|
|
3746
3196
|
spinner.start("Baixando Volta diretamente...");
|
|
@@ -3764,17 +3214,17 @@ async function installVolta() {
|
|
|
3764
3214
|
spinner.stop("Volta instalado!");
|
|
3765
3215
|
return true;
|
|
3766
3216
|
} catch (e2) {
|
|
3767
|
-
spinner.stop(
|
|
3217
|
+
spinner.stop(import_picocolors7.default.yellow("Download direto falhou"));
|
|
3768
3218
|
}
|
|
3769
3219
|
console.log();
|
|
3770
|
-
console.log(
|
|
3220
|
+
console.log(import_picocolors7.default.bold(" Instale manualmente:"));
|
|
3771
3221
|
console.log();
|
|
3772
|
-
console.log(
|
|
3773
|
-
console.log(
|
|
3222
|
+
console.log(import_picocolors7.default.cyan(" 1. Baixe: https://github.com/volta-cli/volta/releases/latest"));
|
|
3223
|
+
console.log(import_picocolors7.default.dim(" (arquivo volta-windows.msi)"));
|
|
3774
3224
|
console.log();
|
|
3775
|
-
console.log(
|
|
3225
|
+
console.log(import_picocolors7.default.cyan(" 2. Execute o instalador"));
|
|
3776
3226
|
console.log();
|
|
3777
|
-
console.log(
|
|
3227
|
+
console.log(import_picocolors7.default.cyan(" 3. Reinicie o terminal"));
|
|
3778
3228
|
console.log();
|
|
3779
3229
|
return false;
|
|
3780
3230
|
} else {
|
|
@@ -3793,15 +3243,15 @@ export PATH="$VOLTA_HOME/bin:$PATH"
|
|
|
3793
3243
|
const content = readFileSync2(shellConfig, "utf-8");
|
|
3794
3244
|
if (!content.includes("VOLTA_HOME")) {
|
|
3795
3245
|
writeFileSync(shellConfig, content + voltaSetup);
|
|
3796
|
-
console.log(
|
|
3246
|
+
console.log(import_picocolors7.default.dim(` Adicionado ao ${shellConfig}`));
|
|
3797
3247
|
}
|
|
3798
3248
|
}
|
|
3799
3249
|
spinner.stop("Volta instalado!");
|
|
3800
3250
|
return true;
|
|
3801
3251
|
}
|
|
3802
3252
|
} catch (error) {
|
|
3803
|
-
spinner.stop(
|
|
3804
|
-
console.log(
|
|
3253
|
+
spinner.stop(import_picocolors7.default.red("Erro ao instalar Volta"));
|
|
3254
|
+
console.log(import_picocolors7.default.dim(` ${error}`));
|
|
3805
3255
|
return false;
|
|
3806
3256
|
}
|
|
3807
3257
|
}
|
|
@@ -3814,7 +3264,7 @@ async function installNodeWithVolta() {
|
|
|
3814
3264
|
spinner.stop("Node.js instalado!");
|
|
3815
3265
|
return true;
|
|
3816
3266
|
} catch (error) {
|
|
3817
|
-
spinner.stop(
|
|
3267
|
+
spinner.stop(import_picocolors7.default.red("Erro ao instalar Node.js"));
|
|
3818
3268
|
return false;
|
|
3819
3269
|
}
|
|
3820
3270
|
}
|
|
@@ -3829,16 +3279,16 @@ async function reinstallGlobalPackages(packages) {
|
|
|
3829
3279
|
execSync2(`"${voltaBin}" install ${pkg}`, { stdio: "pipe" });
|
|
3830
3280
|
spinner.stop(`${pkg} instalado!`);
|
|
3831
3281
|
} catch {
|
|
3832
|
-
spinner.stop(
|
|
3282
|
+
spinner.stop(import_picocolors7.default.yellow(`${pkg} - falha (instale manualmente)`));
|
|
3833
3283
|
}
|
|
3834
3284
|
}
|
|
3835
3285
|
}
|
|
3836
3286
|
async function setupNode(args) {
|
|
3837
3287
|
const checkOnly = args.includes("--check") || args.includes("-c");
|
|
3838
3288
|
console.log();
|
|
3839
|
-
Ie(
|
|
3289
|
+
Ie(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" nimbus setup node ")));
|
|
3840
3290
|
console.log();
|
|
3841
|
-
console.log(
|
|
3291
|
+
console.log(import_picocolors7.default.bold(" Detectando ambiente..."));
|
|
3842
3292
|
console.log();
|
|
3843
3293
|
const fnm = detectFnm();
|
|
3844
3294
|
const nvm = detectNvm();
|
|
@@ -3846,27 +3296,27 @@ async function setupNode(args) {
|
|
|
3846
3296
|
const node = detectNode();
|
|
3847
3297
|
const status = (installed, version) => {
|
|
3848
3298
|
if (!installed)
|
|
3849
|
-
return
|
|
3850
|
-
return
|
|
3299
|
+
return import_picocolors7.default.dim("nao instalado");
|
|
3300
|
+
return import_picocolors7.default.green(`instalado${version ? ` (${version})` : ""}`);
|
|
3851
3301
|
};
|
|
3852
|
-
console.log(` ${
|
|
3853
|
-
console.log(` ${
|
|
3854
|
-
console.log(` ${
|
|
3302
|
+
console.log(` ${import_picocolors7.default.bold("fnm:")} ${status(fnm.installed, fnm.version)}`);
|
|
3303
|
+
console.log(` ${import_picocolors7.default.bold("nvm:")} ${status(nvm.installed, nvm.version)}`);
|
|
3304
|
+
console.log(` ${import_picocolors7.default.bold("volta:")} ${status(volta.installed, volta.version)}`);
|
|
3855
3305
|
console.log();
|
|
3856
|
-
console.log(` ${
|
|
3306
|
+
console.log(` ${import_picocolors7.default.bold("node:")} ${node.version || import_picocolors7.default.dim("nao encontrado")}`);
|
|
3857
3307
|
if (node.manager) {
|
|
3858
|
-
console.log(` ${
|
|
3308
|
+
console.log(` ${import_picocolors7.default.dim(`gerenciado por: ${node.manager}`)}`);
|
|
3859
3309
|
}
|
|
3860
3310
|
console.log();
|
|
3861
3311
|
if (volta.installed && !fnm.installed && !nvm.installed) {
|
|
3862
3312
|
M2.success("Ambiente OK! Volta instalado e configurado.");
|
|
3863
|
-
Se(
|
|
3313
|
+
Se(import_picocolors7.default.green("Nada a fazer."));
|
|
3864
3314
|
return;
|
|
3865
3315
|
}
|
|
3866
3316
|
if (checkOnly) {
|
|
3867
3317
|
if (fnm.installed || nvm.installed) {
|
|
3868
|
-
console.log(
|
|
3869
|
-
console.log(
|
|
3318
|
+
console.log(import_picocolors7.default.yellow(" Recomendacao: migre para Volta"));
|
|
3319
|
+
console.log(import_picocolors7.default.dim(" Execute: nimbus setup node"));
|
|
3870
3320
|
}
|
|
3871
3321
|
Se("");
|
|
3872
3322
|
return;
|
|
@@ -3874,15 +3324,15 @@ async function setupNode(args) {
|
|
|
3874
3324
|
const hasOldManager = fnm.installed || nvm.installed;
|
|
3875
3325
|
const globalPackages = getGlobalPackages();
|
|
3876
3326
|
if (hasOldManager) {
|
|
3877
|
-
console.log(
|
|
3327
|
+
console.log(import_picocolors7.default.yellow(" Gerenciadores antigos detectados!"));
|
|
3878
3328
|
console.log();
|
|
3879
|
-
console.log(
|
|
3880
|
-
console.log(
|
|
3329
|
+
console.log(import_picocolors7.default.dim(" fnm e nvm causam problemas de cache do shell."));
|
|
3330
|
+
console.log(import_picocolors7.default.dim(" Volta resolve isso e funciona melhor no Windows."));
|
|
3881
3331
|
console.log();
|
|
3882
3332
|
if (globalPackages.length > 0) {
|
|
3883
|
-
console.log(
|
|
3333
|
+
console.log(import_picocolors7.default.bold(" Pacotes globais encontrados:"));
|
|
3884
3334
|
for (const pkg of globalPackages) {
|
|
3885
|
-
console.log(
|
|
3335
|
+
console.log(import_picocolors7.default.dim(` - ${pkg}`));
|
|
3886
3336
|
}
|
|
3887
3337
|
console.log();
|
|
3888
3338
|
}
|
|
@@ -3897,9 +3347,9 @@ async function setupNode(args) {
|
|
|
3897
3347
|
actions.push("Instalar Node.js via Volta");
|
|
3898
3348
|
if (globalPackages.length > 0)
|
|
3899
3349
|
actions.push(`Reinstalar ${globalPackages.length} pacotes globais`);
|
|
3900
|
-
console.log(
|
|
3350
|
+
console.log(import_picocolors7.default.bold(" O que sera feito:"));
|
|
3901
3351
|
for (const action of actions) {
|
|
3902
|
-
console.log(
|
|
3352
|
+
console.log(import_picocolors7.default.cyan(` -> ${action}`));
|
|
3903
3353
|
}
|
|
3904
3354
|
console.log();
|
|
3905
3355
|
const confirm = await ye({
|
|
@@ -3912,60 +3362,60 @@ async function setupNode(args) {
|
|
|
3912
3362
|
}
|
|
3913
3363
|
console.log();
|
|
3914
3364
|
if (fnm.installed) {
|
|
3915
|
-
console.log(
|
|
3365
|
+
console.log(import_picocolors7.default.bold(" Removendo fnm..."));
|
|
3916
3366
|
await removeFnm(fnm);
|
|
3917
3367
|
console.log();
|
|
3918
3368
|
}
|
|
3919
3369
|
if (nvm.installed) {
|
|
3920
|
-
console.log(
|
|
3370
|
+
console.log(import_picocolors7.default.bold(" Removendo nvm..."));
|
|
3921
3371
|
await removeNvm(nvm);
|
|
3922
3372
|
console.log();
|
|
3923
3373
|
}
|
|
3924
3374
|
if (!volta.installed) {
|
|
3925
|
-
console.log(
|
|
3375
|
+
console.log(import_picocolors7.default.bold(" Instalando Volta..."));
|
|
3926
3376
|
const installed = await installVolta();
|
|
3927
3377
|
if (!installed) {
|
|
3928
|
-
Se(
|
|
3378
|
+
Se(import_picocolors7.default.red("Falha na instalacao. Tente manualmente."));
|
|
3929
3379
|
return;
|
|
3930
3380
|
}
|
|
3931
3381
|
console.log();
|
|
3932
3382
|
}
|
|
3933
|
-
console.log(
|
|
3383
|
+
console.log(import_picocolors7.default.bold(" Instalando Node.js..."));
|
|
3934
3384
|
await installNodeWithVolta();
|
|
3935
3385
|
console.log();
|
|
3936
3386
|
if (globalPackages.length > 0) {
|
|
3937
|
-
console.log(
|
|
3387
|
+
console.log(import_picocolors7.default.bold(" Reinstalando pacotes globais..."));
|
|
3938
3388
|
await reinstallGlobalPackages(globalPackages);
|
|
3939
3389
|
console.log();
|
|
3940
3390
|
}
|
|
3941
|
-
console.log(
|
|
3942
|
-
console.log(
|
|
3943
|
-
console.log(
|
|
3391
|
+
console.log(import_picocolors7.default.green(" ====================================="));
|
|
3392
|
+
console.log(import_picocolors7.default.green(" Migracao concluida!"));
|
|
3393
|
+
console.log(import_picocolors7.default.green(" ====================================="));
|
|
3944
3394
|
console.log();
|
|
3945
3395
|
if (IS_WINDOWS) {
|
|
3946
|
-
console.log(
|
|
3396
|
+
console.log(import_picocolors7.default.yellow(" IMPORTANTE: Reinicie o terminal!"));
|
|
3947
3397
|
console.log();
|
|
3948
|
-
console.log(
|
|
3949
|
-
console.log(
|
|
3398
|
+
console.log(import_picocolors7.default.dim(" Feche todas as janelas do PowerShell/Terminal"));
|
|
3399
|
+
console.log(import_picocolors7.default.dim(" e abra novamente para aplicar as mudancas."));
|
|
3950
3400
|
} else {
|
|
3951
|
-
console.log(
|
|
3401
|
+
console.log(import_picocolors7.default.yellow(" IMPORTANTE: Reinicie o terminal ou execute:"));
|
|
3952
3402
|
console.log();
|
|
3953
|
-
console.log(
|
|
3954
|
-
console.log(
|
|
3955
|
-
console.log(
|
|
3403
|
+
console.log(import_picocolors7.default.cyan(" source ~/.zshrc"));
|
|
3404
|
+
console.log(import_picocolors7.default.dim(" # ou"));
|
|
3405
|
+
console.log(import_picocolors7.default.cyan(" source ~/.bashrc"));
|
|
3956
3406
|
}
|
|
3957
3407
|
console.log();
|
|
3958
|
-
console.log(
|
|
3959
|
-
console.log(
|
|
3960
|
-
console.log(
|
|
3961
|
-
console.log(
|
|
3408
|
+
console.log(import_picocolors7.default.bold(" Depois, verifique:"));
|
|
3409
|
+
console.log(import_picocolors7.default.dim(" volta --version"));
|
|
3410
|
+
console.log(import_picocolors7.default.dim(" node --version"));
|
|
3411
|
+
console.log(import_picocolors7.default.dim(" nimbus --version"));
|
|
3962
3412
|
console.log();
|
|
3963
|
-
Se(
|
|
3413
|
+
Se(import_picocolors7.default.green("Pronto! Volta configurado."));
|
|
3964
3414
|
}
|
|
3965
3415
|
|
|
3966
3416
|
// src/index.ts
|
|
3967
3417
|
var PACKAGE_NAME2 = "@nimbuslab/cli";
|
|
3968
|
-
var CURRENT_VERSION = "1.1
|
|
3418
|
+
var CURRENT_VERSION = "1.2.1";
|
|
3969
3419
|
var LOGO = `
|
|
3970
3420
|
\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
|
|
3971
3421
|
\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
|
|
@@ -3997,22 +3447,22 @@ function showUpdateNotice(latestVersion) {
|
|
|
3997
3447
|
const current = CURRENT_VERSION;
|
|
3998
3448
|
const latest = latestVersion;
|
|
3999
3449
|
const command = "nimbus update";
|
|
4000
|
-
const line1 = `
|
|
3450
|
+
const line1 = ` New version available: ${current} \u2192 ${latest}`;
|
|
4001
3451
|
const line2 = ` Atualize com: ${command}`;
|
|
4002
3452
|
const maxLen = Math.max(line1.length, line2.length);
|
|
4003
3453
|
const border = "\u2500".repeat(maxLen + 2);
|
|
4004
|
-
console.log(
|
|
4005
|
-
console.log(
|
|
4006
|
-
console.log(
|
|
4007
|
-
console.log(
|
|
3454
|
+
console.log(import_picocolors8.default.yellow(` \u250C${border}\u2510`));
|
|
3455
|
+
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.white(line1.padEnd(maxLen + 2)) + import_picocolors8.default.yellow(`\u2502`));
|
|
3456
|
+
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.cyan(line2.padEnd(maxLen + 2)) + import_picocolors8.default.yellow(`\u2502`));
|
|
3457
|
+
console.log(import_picocolors8.default.yellow(` \u2514${border}\u2518`));
|
|
4008
3458
|
console.log();
|
|
4009
3459
|
}
|
|
4010
3460
|
async function main() {
|
|
4011
3461
|
const args = process.argv.slice(2);
|
|
4012
3462
|
const command = args[0];
|
|
4013
|
-
console.log(
|
|
4014
|
-
console.log(
|
|
4015
|
-
console.log(
|
|
3463
|
+
console.log(import_picocolors8.default.cyan(LOGO));
|
|
3464
|
+
console.log(import_picocolors8.default.white(" nimbuslab CLI"));
|
|
3465
|
+
console.log(import_picocolors8.default.dim(" Create awesome projects"));
|
|
4016
3466
|
console.log();
|
|
4017
3467
|
const latestVersion = await checkForUpdates();
|
|
4018
3468
|
if (latestVersion) {
|
|
@@ -4031,8 +3481,8 @@ async function main() {
|
|
|
4031
3481
|
if (subcommand === "node") {
|
|
4032
3482
|
await setupNode(args.slice(2));
|
|
4033
3483
|
} else {
|
|
4034
|
-
console.log(
|
|
4035
|
-
console.log(
|
|
3484
|
+
console.log(import_picocolors8.default.red(`Subcomando desconhecido: ${subcommand || "(vazio)"}`));
|
|
3485
|
+
console.log(import_picocolors8.default.dim(" Uso: nimbus setup node"));
|
|
4036
3486
|
process.exit(1);
|
|
4037
3487
|
}
|
|
4038
3488
|
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
@@ -4040,71 +3490,65 @@ async function main() {
|
|
|
4040
3490
|
} else if (command === "version" || command === "--version" || command === "-v") {
|
|
4041
3491
|
showVersion();
|
|
4042
3492
|
} else {
|
|
4043
|
-
console.log(
|
|
3493
|
+
console.log(import_picocolors8.default.red(`Comando desconhecido: ${command}`));
|
|
4044
3494
|
showHelp();
|
|
4045
3495
|
process.exit(1);
|
|
4046
3496
|
}
|
|
4047
3497
|
}
|
|
4048
3498
|
function showHelp() {
|
|
4049
3499
|
console.log(`
|
|
4050
|
-
${
|
|
3500
|
+
${import_picocolors8.default.bold("Usage:")} nimbus [command] [options]
|
|
4051
3501
|
|
|
4052
|
-
${
|
|
3502
|
+
${import_picocolors8.default.bold("Comandos:")}
|
|
4053
3503
|
create [nome] Criar novo projeto
|
|
4054
3504
|
analyze [dir] Analisar stack do projeto
|
|
4055
|
-
upgrade [
|
|
4056
|
-
update [
|
|
3505
|
+
upgrade [target] Update dependencies
|
|
3506
|
+
update [version] Update CLI itself
|
|
4057
3507
|
setup [alvo] Configurar ambiente
|
|
4058
|
-
lola [a\xE7\xE3o] Lola - Code Agent
|
|
4059
3508
|
help Mostrar esta ajuda
|
|
4060
|
-
version
|
|
3509
|
+
version Show version
|
|
4061
3510
|
|
|
4062
|
-
${
|
|
3511
|
+
${import_picocolors8.default.bold("Templates:")}
|
|
4063
3512
|
--landing Landing page (Next.js 16 + Tailwind 4 + shadcn)
|
|
4064
3513
|
--app Web app (Landing + Better Auth + Drizzle)
|
|
4065
3514
|
--turborepo Monorepo (Turborepo + apps/packages)
|
|
4066
3515
|
|
|
4067
|
-
${
|
|
4068
|
-
analyze .
|
|
3516
|
+
${import_picocolors8.default.bold("Analyze & Upgrade:")}
|
|
3517
|
+
analyze . Detect stack and show recommendations
|
|
4069
3518
|
analyze --json Output em JSON
|
|
4070
3519
|
upgrade --plan Mostrar plano de upgrade
|
|
4071
3520
|
upgrade next Atualizar Next.js
|
|
4072
3521
|
upgrade tailwind Atualizar Tailwind CSS
|
|
4073
3522
|
|
|
4074
|
-
${
|
|
3523
|
+
${import_picocolors8.default.bold("Update (CLI):")}
|
|
4075
3524
|
update Atualizar para ultima versao
|
|
4076
3525
|
update 0.11.0 Instalar versao especifica
|
|
4077
3526
|
update --list Listar versoes disponiveis
|
|
4078
3527
|
update --force Forcar reinstalacao (limpa cache)
|
|
4079
3528
|
|
|
4080
|
-
${
|
|
3529
|
+
${import_picocolors8.default.bold("Setup (Ambiente):")}
|
|
4081
3530
|
setup node Migrar para Volta (remove fnm/nvm)
|
|
4082
3531
|
setup node --check Verificar ambiente atual
|
|
4083
3532
|
|
|
4084
|
-
${
|
|
4085
|
-
-y, --yes
|
|
4086
|
-
--no-git
|
|
4087
|
-
--no-install
|
|
3533
|
+
${import_picocolors8.default.bold("Options:")}
|
|
3534
|
+
-y, --yes Accept defaults
|
|
3535
|
+
--no-git Skip Git initialization
|
|
3536
|
+
--no-install Skip dependency installation
|
|
4088
3537
|
--template <url> Usar template customizado
|
|
4089
3538
|
|
|
4090
|
-
${
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
${
|
|
4095
|
-
${
|
|
4096
|
-
${
|
|
4097
|
-
${import_picocolors9.default.dim("$")} nimbus analyze ./my-project
|
|
4098
|
-
${import_picocolors9.default.dim("$")} nimbus upgrade --plan
|
|
4099
|
-
${import_picocolors9.default.dim("$")} nimbus update
|
|
4100
|
-
${import_picocolors9.default.dim("$")} nimbus setup node
|
|
4101
|
-
${import_picocolors9.default.dim("$")} nimbus lola install
|
|
3539
|
+
${import_picocolors8.default.bold("Exemplos:")}
|
|
3540
|
+
${import_picocolors8.default.dim("$")} nimbus create my-landing --landing
|
|
3541
|
+
${import_picocolors8.default.dim("$")} nimbus create my-app --app
|
|
3542
|
+
${import_picocolors8.default.dim("$")} nimbus analyze ./my-project
|
|
3543
|
+
${import_picocolors8.default.dim("$")} nimbus upgrade --plan
|
|
3544
|
+
${import_picocolors8.default.dim("$")} nimbus update
|
|
3545
|
+
${import_picocolors8.default.dim("$")} nimbus setup node
|
|
4102
3546
|
`);
|
|
4103
3547
|
}
|
|
4104
3548
|
function showVersion() {
|
|
4105
3549
|
console.log(`${PACKAGE_NAME2} v${CURRENT_VERSION}`);
|
|
4106
3550
|
}
|
|
4107
3551
|
main().catch((err) => {
|
|
4108
|
-
console.error(
|
|
3552
|
+
console.error(import_picocolors8.default.red("Erro:"), err.message);
|
|
4109
3553
|
process.exit(1);
|
|
4110
3554
|
});
|