@create-lft-app/cli 1.0.2 → 1.0.3

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/src/index.js CHANGED
@@ -1,170 +1,82 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import path5 from "path";
5
- import { confirm as confirm2 } from "@inquirer/prompts";
6
-
7
- // src/config/index.ts
8
- import fs from "fs/promises";
9
- import path from "path";
10
- import os from "os";
11
- import { createCipheriv, createDecipheriv, randomBytes, createHash } from "crypto";
12
- import nodeMachineId from "node-machine-id";
13
- import { input, password, select, confirm } from "@inquirer/prompts";
4
+ import path4 from "path";
5
+ import { confirm } from "@inquirer/prompts";
14
6
 
15
- // src/ui/logger.ts
16
- import chalk from "chalk";
17
- var logger = {
18
- info: (message) => {
19
- console.log(chalk.blue("\u2139"), message);
20
- },
21
- success: (message) => {
22
- console.log(chalk.green("\u2714"), message);
23
- },
24
- warning: (message) => {
25
- console.log(chalk.yellow("\u26A0"), message);
26
- },
27
- error: (message) => {
28
- console.log(chalk.red("\u2716"), message);
29
- },
30
- step: (step, total, message) => {
31
- console.log(chalk.cyan(`[${step}/${total}]`), message);
32
- },
33
- newLine: () => {
34
- console.log();
7
+ // src/config/static-config.ts
8
+ var STATIC_CONFIG = {
9
+ github: {
10
+ token: "__GITHUB_TOKEN__",
11
+ username: "__GITHUB_USERNAME__",
12
+ org: "__GITHUB_ORG__"
35
13
  },
36
- divider: () => {
37
- console.log(chalk.gray("\u2500".repeat(50)));
38
- },
39
- title: (message) => {
40
- console.log(chalk.bold.white(message));
41
- },
42
- subtitle: (message) => {
43
- console.log(chalk.gray(message));
44
- },
45
- link: (label, url) => {
46
- console.log(` ${chalk.gray(label + ":")} ${chalk.cyan.underline(url)}`);
47
- },
48
- list: (items) => {
49
- items.forEach((item) => {
50
- console.log(chalk.gray(" \u2022"), item);
51
- });
14
+ supabase: {
15
+ token: "__SUPABASE_TOKEN__",
16
+ orgId: "__SUPABASE_ORG_ID__",
17
+ region: "us-east-1"
52
18
  },
53
- table: (rows) => {
54
- const maxLabelLength = Math.max(...rows.map((r) => r.label.length));
55
- rows.forEach(({ label, value }) => {
56
- const paddedLabel = label.padEnd(maxLabelLength);
57
- console.log(` ${chalk.gray(paddedLabel)} ${value}`);
58
- });
19
+ jira: {
20
+ email: "__JIRA_EMAIL__",
21
+ token: "__JIRA_TOKEN__",
22
+ domain: "__JIRA_DOMAIN__"
59
23
  }
60
24
  };
61
25
 
62
- // src/ui/spinner.ts
63
- import ora from "ora";
64
- function createSpinner(text) {
65
- return ora({
66
- text,
67
- spinner: "dots"
68
- });
69
- }
70
- async function withSpinner(text, fn, successText) {
71
- const spinner = createSpinner(text).start();
72
- try {
73
- const result = await fn();
74
- spinner.succeed(successText || text);
75
- return result;
76
- } catch (error) {
77
- spinner.fail();
78
- throw error;
79
- }
80
- }
81
-
82
26
  // src/config/index.ts
83
- var { machineIdSync } = nodeMachineId;
84
- var CONFIG_FILE = path.join(os.homedir(), ".lftrc");
85
- var ALGORITHM = "aes-256-gcm";
86
- function getEncryptionKey() {
87
- const machineId = machineIdSync();
88
- return createHash("sha256").update(machineId + "lft-secret").digest();
89
- }
90
- function decryptConfig(encrypted) {
91
- const { iv, tag, data } = JSON.parse(encrypted);
92
- const key = getEncryptionKey();
93
- const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(iv, "hex"));
94
- decipher.setAuthTag(Buffer.from(tag, "hex"));
95
- let decrypted = decipher.update(data, "hex", "utf8");
96
- decrypted += decipher.final("utf8");
97
- return JSON.parse(decrypted);
98
- }
99
- var ENV_VARS = {
100
- GITHUB_TOKEN: "LFT_GITHUB_TOKEN",
101
- GITHUB_USERNAME: "LFT_GITHUB_USERNAME",
102
- GITHUB_ORG: "LFT_GITHUB_ORG",
103
- SUPABASE_TOKEN: "LFT_SUPABASE_TOKEN",
104
- SUPABASE_ORG_ID: "LFT_SUPABASE_ORG_ID",
105
- SUPABASE_REGION: "LFT_SUPABASE_REGION",
106
- JIRA_EMAIL: "LFT_JIRA_EMAIL",
107
- JIRA_TOKEN: "LFT_JIRA_TOKEN",
108
- JIRA_DOMAIN: "LFT_JIRA_DOMAIN"
109
- };
110
- function loadConfigFromEnv() {
111
- const githubToken = process.env[ENV_VARS.GITHUB_TOKEN];
112
- const githubUsername = process.env[ENV_VARS.GITHUB_USERNAME];
113
- const supabaseToken = process.env[ENV_VARS.SUPABASE_TOKEN];
114
- const supabaseOrgId = process.env[ENV_VARS.SUPABASE_ORG_ID];
115
- const jiraEmail = process.env[ENV_VARS.JIRA_EMAIL];
116
- const jiraToken = process.env[ENV_VARS.JIRA_TOKEN];
117
- const jiraDomain = process.env[ENV_VARS.JIRA_DOMAIN];
118
- if (!githubToken || !supabaseToken || !jiraToken) {
119
- return null;
120
- }
27
+ async function loadConfig() {
121
28
  return {
122
29
  version: "1.0.0",
123
30
  credentials: {
124
31
  github: {
125
- token: githubToken,
126
- username: githubUsername || ""
32
+ token: STATIC_CONFIG.github.token,
33
+ username: STATIC_CONFIG.github.username
127
34
  },
128
35
  supabase: {
129
- accessToken: supabaseToken,
130
- organizationId: supabaseOrgId || ""
36
+ accessToken: STATIC_CONFIG.supabase.token,
37
+ organizationId: STATIC_CONFIG.supabase.orgId
131
38
  },
132
39
  jira: {
133
- email: jiraEmail || "",
134
- apiToken: jiraToken,
135
- domain: jiraDomain || ""
40
+ email: STATIC_CONFIG.jira.email,
41
+ apiToken: STATIC_CONFIG.jira.token,
42
+ domain: STATIC_CONFIG.jira.domain
136
43
  }
137
44
  },
138
45
  defaults: {
139
- githubOrg: process.env[ENV_VARS.GITHUB_ORG],
140
- supabaseRegion: process.env[ENV_VARS.SUPABASE_REGION] || "us-east-1",
46
+ githubOrg: STATIC_CONFIG.github.org || void 0,
47
+ supabaseRegion: STATIC_CONFIG.supabase.region,
141
48
  jiraProjectType: "software"
142
49
  }
143
50
  };
144
51
  }
145
- function hasEnvConfig() {
146
- return !!(process.env[ENV_VARS.GITHUB_TOKEN] && process.env[ENV_VARS.SUPABASE_TOKEN] && process.env[ENV_VARS.JIRA_TOKEN]);
147
- }
148
52
  async function hasConfig() {
149
- if (hasEnvConfig()) return true;
150
- try {
151
- await fs.access(CONFIG_FILE);
152
- return true;
153
- } catch {
154
- return false;
155
- }
53
+ return STATIC_CONFIG.github.token !== "__GITHUB_TOKEN__" && STATIC_CONFIG.supabase.token !== "__SUPABASE_TOKEN__" && STATIC_CONFIG.jira.token !== "__JIRA_TOKEN__";
156
54
  }
157
- async function loadConfig() {
158
- const envConfig = loadConfigFromEnv();
159
- if (envConfig) {
160
- return envConfig;
55
+
56
+ // src/services/github.ts
57
+ import { Octokit } from "octokit";
58
+
59
+ // src/ui/spinner.ts
60
+ import ora from "ora";
61
+ function createSpinner(text) {
62
+ return ora({
63
+ text,
64
+ spinner: "dots"
65
+ });
66
+ }
67
+ async function withSpinner(text, fn, successText) {
68
+ const spinner = createSpinner(text).start();
69
+ try {
70
+ const result = await fn();
71
+ spinner.succeed(successText || text);
72
+ return result;
73
+ } catch (error) {
74
+ spinner.fail();
75
+ throw error;
161
76
  }
162
- const encrypted = await fs.readFile(CONFIG_FILE, "utf8");
163
- return decryptConfig(encrypted);
164
77
  }
165
78
 
166
79
  // src/services/github.ts
167
- import { Octokit } from "octokit";
168
80
  async function createGitHubRepo(projectName, config) {
169
81
  const octokit = new Octokit({ auth: config.credentials.github.token });
170
82
  const org = config.defaults.githubOrg;
@@ -270,16 +182,16 @@ async function createSupabaseProject(projectName, config) {
270
182
  }
271
183
  function generateSecurePassword() {
272
184
  const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
273
- let password2 = "";
185
+ let password = "";
274
186
  for (let i = 0; i < 32; i++) {
275
- password2 += chars.charAt(Math.floor(Math.random() * chars.length));
187
+ password += chars.charAt(Math.floor(Math.random() * chars.length));
276
188
  }
277
- return password2;
189
+ return password;
278
190
  }
279
191
 
280
192
  // src/utils/validation.ts
281
- import fs2 from "fs";
282
- import path2 from "path";
193
+ import fs from "fs";
194
+ import path from "path";
283
195
  function validateProjectName(name) {
284
196
  if (!name || name.trim() === "") {
285
197
  return { valid: false, error: "El nombre del proyecto no puede estar vac\xEDo" };
@@ -303,8 +215,8 @@ function validateProjectName(name) {
303
215
  if (name.length > 50) {
304
216
  return { valid: false, error: "El nombre no puede tener m\xE1s de 50 caracteres" };
305
217
  }
306
- const projectPath = path2.resolve(process.cwd(), name);
307
- if (fs2.existsSync(projectPath)) {
218
+ const projectPath = path.resolve(process.cwd(), name);
219
+ if (fs.existsSync(projectPath)) {
308
220
  return { valid: false, error: `El directorio "${name}" ya existe` };
309
221
  }
310
222
  return { valid: true };
@@ -408,59 +320,59 @@ async function scaffoldNextJs(projectName, projectPath) {
408
320
 
409
321
  // src/steps/copy-template.ts
410
322
  import { cp, mkdir, readFile, writeFile } from "fs/promises";
411
- import path3 from "path";
323
+ import path2 from "path";
412
324
  import { fileURLToPath } from "url";
413
325
  var __filename2 = fileURLToPath(import.meta.url);
414
- var __dirname2 = path3.dirname(__filename2);
326
+ var __dirname2 = path2.dirname(__filename2);
415
327
  async function copyTemplate(projectPath) {
416
328
  await withSpinner(
417
329
  "Copiando template LFT...",
418
330
  async () => {
419
- const templatesDir = path3.join(__dirname2, "..", "..", "templates");
420
- const srcDir = path3.join(projectPath, "src");
331
+ const templatesDir = path2.join(__dirname2, "..", "..", "templates");
332
+ const srcDir = path2.join(projectPath, "src");
421
333
  await cp(
422
- path3.join(templatesDir, "components", "ui"),
423
- path3.join(srcDir, "components", "ui"),
334
+ path2.join(templatesDir, "components", "ui"),
335
+ path2.join(srcDir, "components", "ui"),
424
336
  { recursive: true }
425
337
  );
426
338
  await cp(
427
- path3.join(templatesDir, "components", "layout"),
428
- path3.join(srcDir, "components", "layout"),
339
+ path2.join(templatesDir, "components", "layout"),
340
+ path2.join(srcDir, "components", "layout"),
429
341
  { recursive: true }
430
342
  );
431
343
  await cp(
432
- path3.join(templatesDir, "components", "dashboard"),
433
- path3.join(srcDir, "components", "dashboard"),
344
+ path2.join(templatesDir, "components", "dashboard"),
345
+ path2.join(srcDir, "components", "dashboard"),
434
346
  { recursive: true }
435
347
  );
436
- await mkdir(path3.join(srcDir, "lib"), { recursive: true });
348
+ await mkdir(path2.join(srcDir, "lib"), { recursive: true });
437
349
  await cp(
438
- path3.join(templatesDir, "lib", "utils.ts"),
439
- path3.join(srcDir, "lib", "utils.ts")
350
+ path2.join(templatesDir, "lib", "utils.ts"),
351
+ path2.join(srcDir, "lib", "utils.ts")
440
352
  );
441
- await mkdir(path3.join(srcDir, "hooks"), { recursive: true });
353
+ await mkdir(path2.join(srcDir, "hooks"), { recursive: true });
442
354
  await cp(
443
- path3.join(templatesDir, "hooks"),
444
- path3.join(srcDir, "hooks"),
355
+ path2.join(templatesDir, "hooks"),
356
+ path2.join(srcDir, "hooks"),
445
357
  { recursive: true }
446
358
  );
447
359
  await cp(
448
- path3.join(templatesDir, "app", "layout.tsx"),
449
- path3.join(srcDir, "app", "layout.tsx")
360
+ path2.join(templatesDir, "app", "layout.tsx"),
361
+ path2.join(srcDir, "app", "layout.tsx")
450
362
  );
451
363
  await cp(
452
- path3.join(templatesDir, "app", "page.tsx"),
453
- path3.join(srcDir, "app", "page.tsx")
364
+ path2.join(templatesDir, "app", "page.tsx"),
365
+ path2.join(srcDir, "app", "page.tsx")
454
366
  );
455
- await mkdir(path3.join(srcDir, "app", "dashboard"), { recursive: true });
367
+ await mkdir(path2.join(srcDir, "app", "dashboard"), { recursive: true });
456
368
  await cp(
457
- path3.join(templatesDir, "app", "dashboard", "page.tsx"),
458
- path3.join(srcDir, "app", "dashboard", "page.tsx")
369
+ path2.join(templatesDir, "app", "dashboard", "page.tsx"),
370
+ path2.join(srcDir, "app", "dashboard", "page.tsx")
459
371
  );
460
- await mkdir(path3.join(srcDir, "app", "auth", "login"), { recursive: true });
372
+ await mkdir(path2.join(srcDir, "app", "auth", "login"), { recursive: true });
461
373
  await cp(
462
- path3.join(templatesDir, "app", "auth", "login", "page.tsx"),
463
- path3.join(srcDir, "app", "auth", "login", "page.tsx")
374
+ path2.join(templatesDir, "app", "auth", "login", "page.tsx"),
375
+ path2.join(srcDir, "app", "auth", "login", "page.tsx")
464
376
  );
465
377
  await mergeGlobalStyles(projectPath, templatesDir);
466
378
  },
@@ -468,8 +380,8 @@ async function copyTemplate(projectPath) {
468
380
  );
469
381
  }
470
382
  async function mergeGlobalStyles(projectPath, templatesDir) {
471
- const templateCssPath = path3.join(templatesDir, "app", "globals.css");
472
- const projectCssPath = path3.join(projectPath, "src", "app", "globals.css");
383
+ const templateCssPath = path2.join(templatesDir, "app", "globals.css");
384
+ const projectCssPath = path2.join(projectPath, "src", "app", "globals.css");
473
385
  try {
474
386
  const templateCss = await readFile(templateCssPath, "utf-8");
475
387
  const existingCss = await readFile(projectCssPath, "utf-8");
@@ -546,7 +458,7 @@ async function installDependencies(projectPath) {
546
458
 
547
459
  // src/steps/create-env.ts
548
460
  import { writeFile as writeFile2, readFile as readFile2, appendFile } from "fs/promises";
549
- import path4 from "path";
461
+ import path3 from "path";
550
462
  async function createEnvFile(projectPath, supabaseKeys) {
551
463
  await withSpinner(
552
464
  "Creando archivo .env.local...",
@@ -557,10 +469,10 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=${supabaseKeys.anonKey}
557
469
  SUPABASE_SERVICE_ROLE_KEY=${supabaseKeys.serviceKey}
558
470
  `;
559
471
  await writeFile2(
560
- path4.join(projectPath, ".env.local"),
472
+ path3.join(projectPath, ".env.local"),
561
473
  envContent
562
474
  );
563
- const gitignorePath = path4.join(projectPath, ".gitignore");
475
+ const gitignorePath = path3.join(projectPath, ".gitignore");
564
476
  try {
565
477
  const gitignore = await readFile2(gitignorePath, "utf-8");
566
478
  if (!gitignore.includes(".env.local")) {
@@ -604,6 +516,53 @@ async function setupGit(projectPath, remoteUrl) {
604
516
  );
605
517
  }
606
518
 
519
+ // src/ui/logger.ts
520
+ import chalk from "chalk";
521
+ var logger = {
522
+ info: (message) => {
523
+ console.log(chalk.blue("\u2139"), message);
524
+ },
525
+ success: (message) => {
526
+ console.log(chalk.green("\u2714"), message);
527
+ },
528
+ warning: (message) => {
529
+ console.log(chalk.yellow("\u26A0"), message);
530
+ },
531
+ error: (message) => {
532
+ console.log(chalk.red("\u2716"), message);
533
+ },
534
+ step: (step, total, message) => {
535
+ console.log(chalk.cyan(`[${step}/${total}]`), message);
536
+ },
537
+ newLine: () => {
538
+ console.log();
539
+ },
540
+ divider: () => {
541
+ console.log(chalk.gray("\u2500".repeat(50)));
542
+ },
543
+ title: (message) => {
544
+ console.log(chalk.bold.white(message));
545
+ },
546
+ subtitle: (message) => {
547
+ console.log(chalk.gray(message));
548
+ },
549
+ link: (label, url) => {
550
+ console.log(` ${chalk.gray(label + ":")} ${chalk.cyan.underline(url)}`);
551
+ },
552
+ list: (items) => {
553
+ items.forEach((item) => {
554
+ console.log(chalk.gray(" \u2022"), item);
555
+ });
556
+ },
557
+ table: (rows) => {
558
+ const maxLabelLength = Math.max(...rows.map((r) => r.label.length));
559
+ rows.forEach(({ label, value }) => {
560
+ const paddedLabel = label.padEnd(maxLabelLength);
561
+ console.log(` ${chalk.gray(paddedLabel)} ${value}`);
562
+ });
563
+ }
564
+ };
565
+
607
566
  // src/ui/banner.ts
608
567
  import boxen from "boxen";
609
568
  import chalk2 from "chalk";
@@ -645,7 +604,7 @@ async function createProject(projectName, options = {}) {
645
604
  if (!validation.valid) {
646
605
  throw new Error(validation.error);
647
606
  }
648
- const projectPath = path5.resolve(process.cwd(), projectName);
607
+ const projectPath = path4.resolve(process.cwd(), projectName);
649
608
  if (!await hasConfig()) {
650
609
  logger.warning('No se encontr\xF3 configuraci\xF3n. Ejecuta "create-lft-app config" primero.');
651
610
  throw new Error("Configuraci\xF3n no encontrada");
@@ -668,7 +627,7 @@ async function createProject(projectName, options = {}) {
668
627
  logger.table(resources);
669
628
  logger.newLine();
670
629
  if (!options.autoConfirm) {
671
- const shouldContinue = await confirm2({
630
+ const shouldContinue = await confirm({
672
631
  message: "\xBFContinuar con la creaci\xF3n?",
673
632
  default: true
674
633
  });