@create-lft-app/cli 1.0.14 → 1.1.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/dist/bin/cli.js +150 -171
- package/dist/bin/cli.js.map +1 -1
- package/dist/src/index.js +148 -169
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/app/auth/login/page.tsx +0 -153
- package/templates/app/dashboard/page.tsx +0 -102
- package/templates/app/globals.css +0 -249
- package/templates/app/layout.tsx +0 -40
- package/templates/app/page.tsx +0 -5
- package/templates/components/dashboard/widget.tsx +0 -113
- package/templates/components/layout/admin-midday-sidebar.tsx +0 -247
- package/templates/components/layout/admin-sidebar.tsx +0 -146
- package/templates/components/layout/header.tsx +0 -71
- package/templates/components/layout/main-content.tsx +0 -28
- package/templates/components/layout/midday-sidebar.tsx +0 -381
- package/templates/components/layout/nav-user.tsx +0 -108
- package/templates/components/layout/page-header.tsx +0 -95
- package/templates/components/layout/sidebar-context.tsx +0 -33
- package/templates/components/layout/sidebar.tsx +0 -194
- package/templates/components/layout/suspension-banner.tsx +0 -21
- package/templates/components/ui/accordion.tsx +0 -58
- package/templates/components/ui/alert-dialog.tsx +0 -165
- package/templates/components/ui/alert.tsx +0 -66
- package/templates/components/ui/avatar.tsx +0 -55
- package/templates/components/ui/badge.tsx +0 -50
- package/templates/components/ui/button.tsx +0 -89
- package/templates/components/ui/calendar.tsx +0 -220
- package/templates/components/ui/card.tsx +0 -89
- package/templates/components/ui/checkbox.tsx +0 -38
- package/templates/components/ui/collapsible.tsx +0 -33
- package/templates/components/ui/command.tsx +0 -196
- package/templates/components/ui/dialog.tsx +0 -153
- package/templates/components/ui/dropdown-menu.tsx +0 -280
- package/templates/components/ui/form.tsx +0 -171
- package/templates/components/ui/icons.tsx +0 -167
- package/templates/components/ui/input.tsx +0 -28
- package/templates/components/ui/label.tsx +0 -25
- package/templates/components/ui/popover.tsx +0 -59
- package/templates/components/ui/progress.tsx +0 -32
- package/templates/components/ui/radio-group.tsx +0 -45
- package/templates/components/ui/scroll-area.tsx +0 -63
- package/templates/components/ui/select.tsx +0 -208
- package/templates/components/ui/separator.tsx +0 -28
- package/templates/components/ui/sheet.tsx +0 -146
- package/templates/components/ui/sidebar.tsx +0 -726
- package/templates/components/ui/skeleton.tsx +0 -15
- package/templates/components/ui/slider.tsx +0 -58
- package/templates/components/ui/sonner.tsx +0 -47
- package/templates/components/ui/spinner.tsx +0 -27
- package/templates/components/ui/submit-button.tsx +0 -47
- package/templates/components/ui/switch.tsx +0 -31
- package/templates/components/ui/table.tsx +0 -120
- package/templates/components/ui/tabs.tsx +0 -75
- package/templates/components/ui/textarea.tsx +0 -26
- package/templates/components/ui/tooltip.tsx +0 -70
- package/templates/hooks/use-mobile.ts +0 -21
- package/templates/lib/supabase/client.ts +0 -8
- package/templates/lib/supabase/server.ts +0 -29
- package/templates/lib/utils.ts +0 -6
- package/templates/modules/auth/actions/auth-actions.ts +0 -12
package/dist/bin/cli.js
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
import { program } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
-
import
|
|
7
|
+
import path3 from "path";
|
|
8
|
+
import { existsSync as existsSync3 } from "fs";
|
|
8
9
|
import { confirm } from "@inquirer/prompts";
|
|
9
10
|
|
|
10
11
|
// src/config/index.ts
|
|
11
12
|
import { existsSync, readFileSync } from "fs";
|
|
12
13
|
var configFilePath = "";
|
|
13
14
|
var loadedConfig = null;
|
|
14
|
-
function setConfigPath(
|
|
15
|
-
configFilePath =
|
|
15
|
+
function setConfigPath(path4) {
|
|
16
|
+
configFilePath = path4;
|
|
16
17
|
loadedConfig = null;
|
|
17
18
|
}
|
|
18
19
|
function getConfigPath() {
|
|
@@ -196,6 +197,20 @@ async function createGitHubRepo(projectName, config) {
|
|
|
196
197
|
`GitHub: ${owner}/${projectName}`
|
|
197
198
|
);
|
|
198
199
|
}
|
|
200
|
+
async function checkGitHubRepoExists(projectName, config) {
|
|
201
|
+
const octokit = new Octokit({ auth: config.credentials.github.token });
|
|
202
|
+
const org = config.defaults.githubOrg;
|
|
203
|
+
const owner = org || config.credentials.github.username;
|
|
204
|
+
try {
|
|
205
|
+
const existing = await octokit.rest.repos.get({
|
|
206
|
+
owner,
|
|
207
|
+
repo: projectName
|
|
208
|
+
});
|
|
209
|
+
return { exists: true, url: existing.data.html_url };
|
|
210
|
+
} catch {
|
|
211
|
+
return { exists: false };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
199
214
|
|
|
200
215
|
// src/services/supabase.ts
|
|
201
216
|
var SUPABASE_API_URL = "https://api.supabase.com/v1";
|
|
@@ -297,6 +312,23 @@ function generateSecurePassword() {
|
|
|
297
312
|
}
|
|
298
313
|
return password;
|
|
299
314
|
}
|
|
315
|
+
async function checkSupabaseProjectExists(projectName, config) {
|
|
316
|
+
const token = config.credentials.supabase.accessToken;
|
|
317
|
+
const existing = await findExistingProject(projectName, token);
|
|
318
|
+
if (existing) {
|
|
319
|
+
return { exists: true, url: `https://${existing.id}.supabase.co`, projectId: existing.id };
|
|
320
|
+
}
|
|
321
|
+
return { exists: false };
|
|
322
|
+
}
|
|
323
|
+
async function getExistingSupabaseKeys(projectId, config) {
|
|
324
|
+
const token = config.credentials.supabase.accessToken;
|
|
325
|
+
const { anonKey, serviceKey } = await getProjectApiKeys(projectId, token);
|
|
326
|
+
return {
|
|
327
|
+
url: `https://${projectId}.supabase.co`,
|
|
328
|
+
anonKey,
|
|
329
|
+
serviceKey
|
|
330
|
+
};
|
|
331
|
+
}
|
|
300
332
|
|
|
301
333
|
// src/utils/validation.ts
|
|
302
334
|
function validateProjectName(name) {
|
|
@@ -412,6 +444,15 @@ async function createJiraProject(projectName, config) {
|
|
|
412
444
|
`Proyecto Jira: ${projectKey}`
|
|
413
445
|
);
|
|
414
446
|
}
|
|
447
|
+
async function checkJiraProjectExists(projectName, config) {
|
|
448
|
+
const { email, apiToken, domain } = config.credentials.jira;
|
|
449
|
+
const auth = Buffer.from(`${email}:${apiToken}`).toString("base64");
|
|
450
|
+
const existing = await findExistingJiraProject(projectName, auth, domain);
|
|
451
|
+
if (existing) {
|
|
452
|
+
return { exists: true, url: `https://${domain}/browse/${existing.key}` };
|
|
453
|
+
}
|
|
454
|
+
return { exists: false };
|
|
455
|
+
}
|
|
415
456
|
|
|
416
457
|
// src/steps/scaffold-nextjs.ts
|
|
417
458
|
import { execa } from "execa";
|
|
@@ -424,21 +465,13 @@ async function scaffoldNextJs(projectName, projectPath) {
|
|
|
424
465
|
return;
|
|
425
466
|
}
|
|
426
467
|
await withSpinner(
|
|
427
|
-
"Inicializando proyecto Next.js...",
|
|
468
|
+
"Inicializando proyecto Next.js con template LFT...",
|
|
428
469
|
async () => {
|
|
429
470
|
await execa("npx", [
|
|
430
|
-
"create-
|
|
471
|
+
"@create-lft-app/nextjs@latest",
|
|
431
472
|
projectName,
|
|
432
|
-
"--
|
|
433
|
-
|
|
434
|
-
"--eslint",
|
|
435
|
-
"--app",
|
|
436
|
-
"--turbopack",
|
|
437
|
-
"--src-dir",
|
|
438
|
-
"--import-alias",
|
|
439
|
-
"@/*",
|
|
440
|
-
"--use-npm",
|
|
441
|
-
"--yes"
|
|
473
|
+
"--cwd",
|
|
474
|
+
process.cwd()
|
|
442
475
|
], {
|
|
443
476
|
cwd: process.cwd(),
|
|
444
477
|
stdio: "pipe"
|
|
@@ -448,137 +481,13 @@ async function scaffoldNextJs(projectName, projectPath) {
|
|
|
448
481
|
);
|
|
449
482
|
}
|
|
450
483
|
|
|
451
|
-
// src/steps/copy-template.ts
|
|
452
|
-
import { cp, mkdir } from "fs/promises";
|
|
453
|
-
import path2 from "path";
|
|
454
|
-
import { fileURLToPath } from "url";
|
|
455
|
-
var __filename2 = fileURLToPath(import.meta.url);
|
|
456
|
-
var __dirname2 = path2.dirname(__filename2);
|
|
457
|
-
async function copyTemplate(projectPath) {
|
|
458
|
-
await withSpinner(
|
|
459
|
-
"Copiando template LFT...",
|
|
460
|
-
async () => {
|
|
461
|
-
const templatesDir = path2.join(__dirname2, "..", "..", "templates");
|
|
462
|
-
const srcDir = path2.join(projectPath, "src");
|
|
463
|
-
await cp(
|
|
464
|
-
path2.join(templatesDir, "components", "ui"),
|
|
465
|
-
path2.join(srcDir, "components", "ui"),
|
|
466
|
-
{ recursive: true }
|
|
467
|
-
);
|
|
468
|
-
await cp(
|
|
469
|
-
path2.join(templatesDir, "components", "layout"),
|
|
470
|
-
path2.join(srcDir, "components", "layout"),
|
|
471
|
-
{ recursive: true }
|
|
472
|
-
);
|
|
473
|
-
await cp(
|
|
474
|
-
path2.join(templatesDir, "components", "dashboard"),
|
|
475
|
-
path2.join(srcDir, "components", "dashboard"),
|
|
476
|
-
{ recursive: true }
|
|
477
|
-
);
|
|
478
|
-
await cp(
|
|
479
|
-
path2.join(templatesDir, "lib"),
|
|
480
|
-
path2.join(srcDir, "lib"),
|
|
481
|
-
{ recursive: true }
|
|
482
|
-
);
|
|
483
|
-
await cp(
|
|
484
|
-
path2.join(templatesDir, "modules"),
|
|
485
|
-
path2.join(srcDir, "modules"),
|
|
486
|
-
{ recursive: true }
|
|
487
|
-
);
|
|
488
|
-
await mkdir(path2.join(srcDir, "hooks"), { recursive: true });
|
|
489
|
-
await cp(
|
|
490
|
-
path2.join(templatesDir, "hooks"),
|
|
491
|
-
path2.join(srcDir, "hooks"),
|
|
492
|
-
{ recursive: true }
|
|
493
|
-
);
|
|
494
|
-
await cp(
|
|
495
|
-
path2.join(templatesDir, "app", "layout.tsx"),
|
|
496
|
-
path2.join(srcDir, "app", "layout.tsx")
|
|
497
|
-
);
|
|
498
|
-
await cp(
|
|
499
|
-
path2.join(templatesDir, "app", "page.tsx"),
|
|
500
|
-
path2.join(srcDir, "app", "page.tsx")
|
|
501
|
-
);
|
|
502
|
-
await mkdir(path2.join(srcDir, "app", "dashboard"), { recursive: true });
|
|
503
|
-
await cp(
|
|
504
|
-
path2.join(templatesDir, "app", "dashboard", "page.tsx"),
|
|
505
|
-
path2.join(srcDir, "app", "dashboard", "page.tsx")
|
|
506
|
-
);
|
|
507
|
-
await mkdir(path2.join(srcDir, "app", "auth", "login"), { recursive: true });
|
|
508
|
-
await cp(
|
|
509
|
-
path2.join(templatesDir, "app", "auth", "login", "page.tsx"),
|
|
510
|
-
path2.join(srcDir, "app", "auth", "login", "page.tsx")
|
|
511
|
-
);
|
|
512
|
-
await cp(
|
|
513
|
-
path2.join(templatesDir, "app", "globals.css"),
|
|
514
|
-
path2.join(srcDir, "app", "globals.css")
|
|
515
|
-
);
|
|
516
|
-
},
|
|
517
|
-
"Template LFT copiado (47 componentes + p\xE1ginas)"
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
484
|
// src/steps/install-deps.ts
|
|
522
485
|
import { execa as execa2 } from "execa";
|
|
523
|
-
var TEMPLATE_DEPENDENCIES = [
|
|
524
|
-
// Radix UI primitives
|
|
525
|
-
"@radix-ui/react-accordion",
|
|
526
|
-
"@radix-ui/react-alert-dialog",
|
|
527
|
-
"@radix-ui/react-avatar",
|
|
528
|
-
"@radix-ui/react-checkbox",
|
|
529
|
-
"@radix-ui/react-collapsible",
|
|
530
|
-
"@radix-ui/react-dialog",
|
|
531
|
-
"@radix-ui/react-dropdown-menu",
|
|
532
|
-
"@radix-ui/react-label",
|
|
533
|
-
"@radix-ui/react-popover",
|
|
534
|
-
"@radix-ui/react-progress",
|
|
535
|
-
"@radix-ui/react-radio-group",
|
|
536
|
-
"@radix-ui/react-scroll-area",
|
|
537
|
-
"@radix-ui/react-select",
|
|
538
|
-
"@radix-ui/react-separator",
|
|
539
|
-
"@radix-ui/react-slider",
|
|
540
|
-
"@radix-ui/react-slot",
|
|
541
|
-
"@radix-ui/react-switch",
|
|
542
|
-
"@radix-ui/react-tabs",
|
|
543
|
-
"@radix-ui/react-tooltip",
|
|
544
|
-
// UI Utilities
|
|
545
|
-
"class-variance-authority",
|
|
546
|
-
"clsx",
|
|
547
|
-
"tailwind-merge",
|
|
548
|
-
// Icons
|
|
549
|
-
"lucide-react",
|
|
550
|
-
// Form handling
|
|
551
|
-
"react-hook-form",
|
|
552
|
-
"@hookform/resolvers",
|
|
553
|
-
// Command menu
|
|
554
|
-
"cmdk",
|
|
555
|
-
// Date picker
|
|
556
|
-
"react-day-picker",
|
|
557
|
-
"date-fns",
|
|
558
|
-
// Toast notifications
|
|
559
|
-
"sonner",
|
|
560
|
-
// Theme
|
|
561
|
-
"next-themes",
|
|
562
|
-
// Animations
|
|
563
|
-
"tw-animate-css",
|
|
564
|
-
// Validation
|
|
565
|
-
"zod",
|
|
566
|
-
// Supabase client
|
|
567
|
-
"@supabase/supabase-js",
|
|
568
|
-
"@supabase/ssr"
|
|
569
|
-
];
|
|
570
|
-
var TEMPLATE_DEV_DEPENDENCIES = [
|
|
571
|
-
"tailwindcss-animate"
|
|
572
|
-
];
|
|
573
486
|
async function installDependencies(projectPath) {
|
|
574
487
|
await withSpinner(
|
|
575
|
-
|
|
488
|
+
"Instalando dependencias...",
|
|
576
489
|
async () => {
|
|
577
|
-
await execa2("npm", ["install"
|
|
578
|
-
cwd: projectPath,
|
|
579
|
-
stdio: "pipe"
|
|
580
|
-
});
|
|
581
|
-
await execa2("npm", ["install", "-D", ...TEMPLATE_DEV_DEPENDENCIES], {
|
|
490
|
+
await execa2("npm", ["install"], {
|
|
582
491
|
cwd: projectPath,
|
|
583
492
|
stdio: "pipe"
|
|
584
493
|
});
|
|
@@ -589,7 +498,7 @@ async function installDependencies(projectPath) {
|
|
|
589
498
|
|
|
590
499
|
// src/steps/create-env.ts
|
|
591
500
|
import { writeFile, readFile, appendFile } from "fs/promises";
|
|
592
|
-
import
|
|
501
|
+
import path2 from "path";
|
|
593
502
|
async function createEnvFile(projectPath, supabaseKeys) {
|
|
594
503
|
await withSpinner(
|
|
595
504
|
"Creando archivo .env.local...",
|
|
@@ -600,10 +509,10 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=${supabaseKeys.anonKey}
|
|
|
600
509
|
SUPABASE_SERVICE_ROLE_KEY=${supabaseKeys.serviceKey}
|
|
601
510
|
`;
|
|
602
511
|
await writeFile(
|
|
603
|
-
|
|
512
|
+
path2.join(projectPath, ".env.local"),
|
|
604
513
|
envContent
|
|
605
514
|
);
|
|
606
|
-
const gitignorePath =
|
|
515
|
+
const gitignorePath = path2.join(projectPath, ".gitignore");
|
|
607
516
|
try {
|
|
608
517
|
const gitignore = await readFile(gitignorePath, "utf-8");
|
|
609
518
|
if (!gitignore.includes(".env.local")) {
|
|
@@ -701,31 +610,78 @@ async function createProject(projectName, options = {}) {
|
|
|
701
610
|
if (!validation.valid) {
|
|
702
611
|
throw new Error(validation.error);
|
|
703
612
|
}
|
|
704
|
-
const projectPath =
|
|
613
|
+
const projectPath = path3.resolve(process.cwd(), projectName);
|
|
705
614
|
if (!await hasConfig()) {
|
|
706
615
|
logger.warning('No se encontr\xF3 configuraci\xF3n. Ejecuta "create-lft-app config" primero.');
|
|
707
616
|
throw new Error("Configuraci\xF3n no encontrada");
|
|
708
617
|
}
|
|
709
618
|
const config = await loadConfig();
|
|
619
|
+
logger.info("Verificando recursos existentes...");
|
|
620
|
+
const status = {
|
|
621
|
+
github: { exists: false },
|
|
622
|
+
supabase: { exists: false },
|
|
623
|
+
jira: { exists: false },
|
|
624
|
+
nextjs: { exists: existsSync3(projectPath) }
|
|
625
|
+
};
|
|
626
|
+
const checks = [];
|
|
627
|
+
if (!options.skipGithub) {
|
|
628
|
+
checks.push(
|
|
629
|
+
checkGitHubRepoExists(projectName, config).then((result) => {
|
|
630
|
+
status.github = result;
|
|
631
|
+
})
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
if (!options.skipSupabase) {
|
|
635
|
+
checks.push(
|
|
636
|
+
checkSupabaseProjectExists(projectName, config).then((result) => {
|
|
637
|
+
status.supabase = result;
|
|
638
|
+
})
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
if (!options.skipJira) {
|
|
642
|
+
checks.push(
|
|
643
|
+
checkJiraProjectExists(projectName, config).then((result) => {
|
|
644
|
+
status.jira = result;
|
|
645
|
+
})
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
await Promise.all(checks);
|
|
710
649
|
logger.newLine();
|
|
711
|
-
logger.title("Resumen de recursos
|
|
650
|
+
logger.title("Resumen de recursos:");
|
|
712
651
|
logger.newLine();
|
|
713
652
|
const resources = [];
|
|
653
|
+
const owner = config.defaults.githubOrg || config.credentials.github.username;
|
|
714
654
|
if (!options.skipGithub) {
|
|
715
|
-
|
|
655
|
+
const githubStatus = status.github.exists ? "\u2713 ya existe" : "se crear\xE1";
|
|
656
|
+
resources.push({
|
|
657
|
+
label: "GitHub",
|
|
658
|
+
value: `${owner}/${projectName} (${githubStatus})`
|
|
659
|
+
});
|
|
716
660
|
}
|
|
717
661
|
if (!options.skipSupabase) {
|
|
718
|
-
|
|
662
|
+
const supabaseStatus = status.supabase.exists ? "\u2713 ya existe" : "se crear\xE1";
|
|
663
|
+
resources.push({
|
|
664
|
+
label: "Supabase",
|
|
665
|
+
value: `${projectName} en ${config.defaults.supabaseRegion} (${supabaseStatus})`
|
|
666
|
+
});
|
|
719
667
|
}
|
|
720
668
|
if (!options.skipJira) {
|
|
721
|
-
|
|
669
|
+
const jiraStatus = status.jira.exists ? "\u2713 ya existe" : "se crear\xE1";
|
|
670
|
+
resources.push({
|
|
671
|
+
label: "Jira",
|
|
672
|
+
value: `Proyecto "${projectName}" (${jiraStatus})`
|
|
673
|
+
});
|
|
722
674
|
}
|
|
723
|
-
|
|
675
|
+
const nextjsStatus = status.nextjs.exists ? "\u2713 ya existe" : "se crear\xE1";
|
|
676
|
+
resources.push({
|
|
677
|
+
label: "Next.js",
|
|
678
|
+
value: `App Router + TypeScript + Tailwind (${nextjsStatus})`
|
|
679
|
+
});
|
|
724
680
|
logger.table(resources);
|
|
725
681
|
logger.newLine();
|
|
726
682
|
if (!options.autoConfirm) {
|
|
727
683
|
const shouldContinue = await confirm({
|
|
728
|
-
message: "\xBFContinuar
|
|
684
|
+
message: "\xBFContinuar?",
|
|
729
685
|
default: true
|
|
730
686
|
});
|
|
731
687
|
if (!shouldContinue) {
|
|
@@ -740,35 +696,58 @@ async function createProject(projectName, options = {}) {
|
|
|
740
696
|
let supabaseKeys;
|
|
741
697
|
const externalTasks = [];
|
|
742
698
|
if (!options.skipGithub) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
699
|
+
if (status.github.exists) {
|
|
700
|
+
urls.github = status.github.url;
|
|
701
|
+
logger.success(`GitHub: ${owner}/${projectName} (ya existe)`);
|
|
702
|
+
} else {
|
|
703
|
+
externalTasks.push(
|
|
704
|
+
createGitHubRepo(projectName, config).then((url) => {
|
|
705
|
+
urls.github = url;
|
|
706
|
+
})
|
|
707
|
+
);
|
|
708
|
+
}
|
|
748
709
|
}
|
|
749
710
|
if (!options.skipSupabase) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
711
|
+
if (status.supabase.exists && status.supabase.projectId) {
|
|
712
|
+
externalTasks.push(
|
|
713
|
+
getExistingSupabaseKeys(status.supabase.projectId, config).then((result) => {
|
|
714
|
+
urls.supabase = result.url;
|
|
715
|
+
supabaseKeys = result;
|
|
716
|
+
logger.success(`Supabase: ${projectName} (ya existe)`);
|
|
717
|
+
})
|
|
718
|
+
);
|
|
719
|
+
} else {
|
|
720
|
+
externalTasks.push(
|
|
721
|
+
createSupabaseProject(projectName, config).then((result) => {
|
|
722
|
+
urls.supabase = result.url;
|
|
723
|
+
supabaseKeys = result;
|
|
724
|
+
})
|
|
725
|
+
);
|
|
726
|
+
}
|
|
756
727
|
}
|
|
757
728
|
if (!options.skipJira) {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
729
|
+
if (status.jira.exists) {
|
|
730
|
+
urls.jira = status.jira.url;
|
|
731
|
+
logger.success(`Jira: ${projectName} (ya existe)`);
|
|
732
|
+
} else {
|
|
733
|
+
externalTasks.push(
|
|
734
|
+
createJiraProject(projectName, config).then((url) => {
|
|
735
|
+
urls.jira = url;
|
|
736
|
+
})
|
|
737
|
+
);
|
|
738
|
+
}
|
|
763
739
|
}
|
|
764
740
|
await Promise.all(externalTasks);
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
741
|
+
if (!status.nextjs.exists) {
|
|
742
|
+
await scaffoldNextJs(projectName, projectPath);
|
|
743
|
+
await installDependencies(projectPath);
|
|
744
|
+
} else {
|
|
745
|
+
logger.success(`Next.js: ${projectName} (ya existe)`);
|
|
746
|
+
}
|
|
768
747
|
if (supabaseKeys) {
|
|
769
748
|
await createEnvFile(projectPath, supabaseKeys);
|
|
770
749
|
}
|
|
771
|
-
if (!options.skipGit && urls.github) {
|
|
750
|
+
if (!options.skipGit && urls.github && !status.nextjs.exists) {
|
|
772
751
|
await setupGit(projectPath, urls.github);
|
|
773
752
|
}
|
|
774
753
|
logger.newLine();
|