gufi-cli 0.1.4 → 0.1.7

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/CLAUDE.md CHANGED
@@ -1419,6 +1419,29 @@ gufi automation calcular_stock -c 116 --edit
1419
1419
  gufi automation calcular_stock -c 116 --file script.js
1420
1420
  ```
1421
1421
 
1422
+ ### Environment Variables
1423
+
1424
+ ```bash
1425
+ # Ver variables de entorno de la company
1426
+ gufi env
1427
+
1428
+ # Crear/actualizar variable
1429
+ gufi env:set STRIPE_API_KEY sk-live-xxx
1430
+
1431
+ # Eliminar variable
1432
+ gufi env:delete STRIPE_API_KEY
1433
+ ```
1434
+
1435
+ ### Schema (Estructura de Tablas)
1436
+
1437
+ ```bash
1438
+ # Ver todas las tablas de la company
1439
+ gufi schema
1440
+
1441
+ # Filtrar por módulo
1442
+ gufi schema -m 360
1443
+ ```
1444
+
1422
1445
  ### Row CRUD (Datos de Tablas)
1423
1446
 
1424
1447
  ```bash
@@ -1452,23 +1475,23 @@ gufi rows:create m360_t16192 --file datos.json
1452
1475
  ### Desarrollo de Views
1453
1476
 
1454
1477
  ```bash
1455
- # Ver tus packages y views
1456
- gufi list
1478
+ # Ver tus views del Marketplace
1479
+ gufi views
1457
1480
 
1458
1481
  # Descargar view para editar localmente
1459
- gufi pull "Stock Overview"
1482
+ gufi view:pull "Stock Overview"
1460
1483
 
1461
1484
  # Auto-sync al guardar archivos
1462
- gufi watch
1485
+ gufi view:watch
1463
1486
 
1464
1487
  # Ver console.log del LivePreview
1465
- gufi logs
1488
+ gufi view:logs
1466
1489
 
1467
1490
  # Subir cambios manualmente
1468
- gufi push
1491
+ gufi view:push
1469
1492
 
1470
1493
  # Ver estado de sincronización
1471
- gufi status
1494
+ gufi view:status
1472
1495
  ```
1473
1496
 
1474
1497
  ### Opciones Globales
@@ -0,0 +1,30 @@
1
+ /**
2
+ * gufi env - Manage company environment variables
3
+ * gufi schema - View company table structure
4
+ */
5
+ interface EnvOptions {
6
+ company?: string;
7
+ set?: string;
8
+ delete?: boolean;
9
+ }
10
+ interface SchemaOptions {
11
+ company?: string;
12
+ module?: string;
13
+ }
14
+ /**
15
+ * gufi env - List environment variables
16
+ */
17
+ export declare function envListCommand(options: EnvOptions): Promise<void>;
18
+ /**
19
+ * gufi env:set <key> <value> - Set an environment variable
20
+ */
21
+ export declare function envSetCommand(key: string, value: string, options: EnvOptions): Promise<void>;
22
+ /**
23
+ * gufi env:delete <key> - Delete an environment variable
24
+ */
25
+ export declare function envDeleteCommand(key: string, options: EnvOptions): Promise<void>;
26
+ /**
27
+ * gufi schema - View company table structure
28
+ */
29
+ export declare function schemaCommand(options: SchemaOptions): Promise<void>;
30
+ export {};
@@ -0,0 +1,145 @@
1
+ /**
2
+ * gufi env - Manage company environment variables
3
+ * gufi schema - View company table structure
4
+ */
5
+ import chalk from "chalk";
6
+ import ora from "ora";
7
+ import { getToken, getApiUrl } from "../lib/config.js";
8
+ async function apiRequest(endpoint, options = {}) {
9
+ const token = getToken();
10
+ if (!token) {
11
+ throw new Error("No estás logueado. Ejecuta: gufi login");
12
+ }
13
+ const url = `${getApiUrl()}${endpoint}`;
14
+ const response = await fetch(url, {
15
+ ...options,
16
+ headers: {
17
+ "Content-Type": "application/json",
18
+ Authorization: `Bearer ${token}`,
19
+ "X-Client": "cli",
20
+ ...options.headers,
21
+ },
22
+ });
23
+ if (!response.ok) {
24
+ const text = await response.text();
25
+ throw new Error(`API Error ${response.status}: ${text}`);
26
+ }
27
+ return response.json();
28
+ }
29
+ /**
30
+ * gufi env - List environment variables
31
+ */
32
+ export async function envListCommand(options) {
33
+ const spinner = ora("Cargando variables de entorno...").start();
34
+ try {
35
+ const data = await apiRequest("/api/cli/env");
36
+ spinner.stop();
37
+ console.log(chalk.magenta("\n 🔐 Variables de Entorno\n"));
38
+ if (!data || data.length === 0) {
39
+ console.log(chalk.gray(" No hay variables configuradas\n"));
40
+ console.log(chalk.gray(" Usa: gufi env:set <KEY> <VALUE>\n"));
41
+ return;
42
+ }
43
+ // Show as table
44
+ const maxKeyLen = Math.max(...data.map((v) => v.key.length), 10);
45
+ console.log(chalk.gray(" " + "KEY".padEnd(maxKeyLen + 2) + "VALUE"));
46
+ console.log(chalk.gray(" " + "─".repeat(maxKeyLen + 20)));
47
+ for (const env of data) {
48
+ const maskedValue = env.is_secret
49
+ ? "••••••••"
50
+ : (env.value?.substring(0, 30) + (env.value?.length > 30 ? "..." : ""));
51
+ console.log(" " +
52
+ chalk.cyan(env.key.padEnd(maxKeyLen + 2)) +
53
+ chalk.white(maskedValue));
54
+ }
55
+ console.log(chalk.gray(`\n Total: ${data.length} variables\n`));
56
+ }
57
+ catch (error) {
58
+ spinner.fail(chalk.red(error.message));
59
+ process.exit(1);
60
+ }
61
+ }
62
+ /**
63
+ * gufi env:set <key> <value> - Set an environment variable
64
+ */
65
+ export async function envSetCommand(key, value, options) {
66
+ const spinner = ora(`Guardando ${key}...`).start();
67
+ try {
68
+ await apiRequest("/api/cli/env", {
69
+ method: "POST",
70
+ body: JSON.stringify({ key, value }),
71
+ });
72
+ spinner.succeed(chalk.green(`${key} guardada`));
73
+ console.log();
74
+ }
75
+ catch (error) {
76
+ spinner.fail(chalk.red(error.message));
77
+ process.exit(1);
78
+ }
79
+ }
80
+ /**
81
+ * gufi env:delete <key> - Delete an environment variable
82
+ */
83
+ export async function envDeleteCommand(key, options) {
84
+ const spinner = ora(`Eliminando ${key}...`).start();
85
+ try {
86
+ await apiRequest(`/api/cli/env/${encodeURIComponent(key)}`, {
87
+ method: "DELETE",
88
+ });
89
+ spinner.succeed(chalk.green(`${key} eliminada`));
90
+ console.log();
91
+ }
92
+ catch (error) {
93
+ spinner.fail(chalk.red(error.message));
94
+ process.exit(1);
95
+ }
96
+ }
97
+ /**
98
+ * gufi schema - View company table structure
99
+ */
100
+ export async function schemaCommand(options) {
101
+ const spinner = ora("Cargando schema...").start();
102
+ try {
103
+ const data = await apiRequest("/api/cli/schema");
104
+ spinner.stop();
105
+ console.log(chalk.magenta("\n 📊 Schema de la Company\n"));
106
+ if (!data.modules || data.modules.length === 0) {
107
+ console.log(chalk.gray(" No hay módulos\n"));
108
+ return;
109
+ }
110
+ for (const module of data.modules) {
111
+ // Filter by module if specified
112
+ if (options.module && module.id !== parseInt(options.module)) {
113
+ continue;
114
+ }
115
+ console.log(chalk.cyan(` 📦 ${module.name}`) +
116
+ chalk.gray(` (ID: ${module.id})`));
117
+ if (module.entities && module.entities.length > 0) {
118
+ for (const entity of module.entities) {
119
+ const tableName = `m${module.id}_t${entity.id}`;
120
+ console.log(chalk.white(` └─ ${entity.name}`) +
121
+ chalk.gray(` → ${tableName}`));
122
+ // Show fields if available
123
+ if (entity.fields && entity.fields.length > 0) {
124
+ const fieldList = entity.fields
125
+ .slice(0, 5)
126
+ .map((f) => f.name)
127
+ .join(", ");
128
+ const more = entity.fields.length > 5
129
+ ? ` +${entity.fields.length - 5} más`
130
+ : "";
131
+ console.log(chalk.gray(` campos: ${fieldList}${more}`));
132
+ }
133
+ }
134
+ }
135
+ console.log();
136
+ }
137
+ // Summary
138
+ const totalTables = data.modules.reduce((acc, m) => acc + (m.entities?.length || 0), 0);
139
+ console.log(chalk.gray(` ${data.modules.length} módulos, ${totalTables} tablas\n`));
140
+ }
141
+ catch (error) {
142
+ spinner.fail(chalk.red(error.message));
143
+ process.exit(1);
144
+ }
145
+ }
package/dist/index.js CHANGED
@@ -39,130 +39,157 @@ import { listCommand } from "./commands/list.js";
39
39
  import { logsCommand } from "./commands/logs.js";
40
40
  import { companiesCommand, modulesCommand, moduleCommand, moduleUpdateCommand, companyCreateCommand, automationsCommand, automationCommand, } from "./commands/companies.js";
41
41
  import { rowsListCommand, rowGetCommand, rowCreateCommand, rowUpdateCommand, rowDeleteCommand, rowDuplicateCommand, rowsBulkCreateCommand, } from "./commands/rows.js";
42
+ import { envListCommand, envSetCommand, envDeleteCommand, schemaCommand, } from "./commands/env.js";
42
43
  const program = new Command();
43
44
  program
44
45
  .name("gufi")
45
- .description("Gufi Developer CLI - Develop Gufi views locally")
46
- .version("0.1.0");
47
- // Auth commands
46
+ .description("🟣 Gufi CLI - Desarrolla módulos, vistas y automations")
47
+ .version("0.1.7");
48
+ // ════════════════════════════════════════════════════════════════════
49
+ // 🔐 Auth
50
+ // ════════════════════════════════════════════════════════════════════
48
51
  program
49
52
  .command("login")
50
- .description("Login to Gufi")
51
- .option("--api <url>", "Custom API URL")
53
+ .description("Iniciar sesión en Gufi")
54
+ .option("--api <url>", "URL de API personalizada")
52
55
  .action(loginCommand);
53
56
  program
54
57
  .command("logout")
55
- .description("Logout from Gufi")
58
+ .description("Cerrar sesión")
56
59
  .action(logoutCommand);
57
60
  program
58
61
  .command("whoami")
59
- .description("Show current logged in user")
62
+ .description("Ver usuario actual")
60
63
  .action(whoamiCommand);
61
- // Sync commands
62
- program
63
- .command("pull [view]")
64
- .description("Download view files from Gufi")
65
- .action(pullCommand);
66
- program
67
- .command("push")
68
- .description("Upload local changes to Gufi")
69
- .action(pushCommand);
70
- program
71
- .command("watch [dir]")
72
- .description("Watch for file changes and auto-sync")
73
- .action(watchCommand);
74
- program
75
- .command("status")
76
- .description("Show sync status")
77
- .action(statusCommand);
78
- program
79
- .command("list")
80
- .alias("ls")
81
- .description("List your packages and views")
82
- .action(listCommand);
83
- program
84
- .command("logs [dir]")
85
- .description("Stream console logs from LivePreview in real-time")
86
- .action(logsCommand);
87
64
  // ════════════════════════════════════════════════════════════════════
88
- // SDK Commands - Companies, Modules, Automations
65
+ // 🏢 Companies & Modules
89
66
  // ════════════════════════════════════════════════════════════════════
90
67
  program
91
68
  .command("companies")
92
- .description("List your companies")
69
+ .description("Ver mis companies")
93
70
  .action(companiesCommand);
71
+ program
72
+ .command("company:create <name>")
73
+ .description("Crear nueva company")
74
+ .action(companyCreateCommand);
94
75
  program
95
76
  .command("modules <company_id>")
96
- .description("List modules of a company")
77
+ .description("Ver módulos de una company")
97
78
  .action(modulesCommand);
79
+ program
80
+ .command("schema")
81
+ .description("Ver estructura de tablas de la company")
82
+ .option("-m, --module <id>", "Filtrar por módulo")
83
+ .action(schemaCommand);
98
84
  program
99
85
  .command("module <module_id>")
100
- .description("View or edit a module JSON")
101
- .option("-e, --edit", "Open in editor to edit")
102
- .option("-c, --company <id>", "Company ID (if not default)")
103
- .option("-f, --file <path>", "Save JSON to file")
86
+ .description("Ver/editar JSON de un módulo")
87
+ .option("-e, --edit", "Abrir en editor")
88
+ .option("-c, --company <id>", "ID de company")
89
+ .option("-f, --file <path>", "Exportar a archivo")
104
90
  .action(moduleCommand);
105
91
  program
106
92
  .command("module:update <module_id> <json_file>")
107
- .description("Update module from a JSON file")
108
- .option("-c, --company <id>", "Company ID (if not default)")
109
- .option("--dry-run", "Validate without saving")
93
+ .description("Actualizar módulo desde archivo JSON")
94
+ .option("-c, --company <id>", "ID de company")
95
+ .option("--dry-run", "Validar sin guardar")
110
96
  .action(moduleUpdateCommand);
111
- program
112
- .command("company:create <name>")
113
- .description("Create a new company")
114
- .action(companyCreateCommand);
97
+ // ════════════════════════════════════════════════════════════════════
98
+ // ⚡ Automations
99
+ // ════════════════════════════════════════════════════════════════════
115
100
  program
116
101
  .command("automations")
117
- .description("List all automation scripts")
118
- .option("-c, --company <id>", "Company ID (if not default)")
102
+ .description("Ver scripts de automation")
103
+ .option("-c, --company <id>", "ID de company")
119
104
  .action(automationsCommand);
120
105
  program
121
106
  .command("automation <name>")
122
- .description("View or edit an automation by name")
123
- .option("-e, --edit", "Open in editor to edit")
124
- .option("-c, --company <id>", "Company ID (if not default)")
125
- .option("-f, --file <path>", "Save code to file")
107
+ .description("Ver/editar código de automation")
108
+ .option("-e, --edit", "Abrir en editor")
109
+ .option("-c, --company <id>", "ID de company")
110
+ .option("-f, --file <path>", "Exportar a archivo")
126
111
  .action(automationCommand);
127
112
  // ════════════════════════════════════════════════════════════════════
128
- // Row CRUD Commands - Create, Read, Update, Delete rows
113
+ // 🔐 Environment Variables
114
+ // ════════════════════════════════════════════════════════════════════
115
+ program
116
+ .command("env")
117
+ .description("Ver variables de entorno de la company")
118
+ .action(envListCommand);
119
+ program
120
+ .command("env:set <key> <value>")
121
+ .description("Crear/actualizar variable de entorno")
122
+ .action(envSetCommand);
123
+ program
124
+ .command("env:delete <key>")
125
+ .description("Eliminar variable de entorno")
126
+ .action(envDeleteCommand);
127
+ // ════════════════════════════════════════════════════════════════════
128
+ // 📊 Row CRUD - Datos de tablas
129
129
  // ════════════════════════════════════════════════════════════════════
130
130
  program
131
131
  .command("rows <table>")
132
- .description("List rows from a table")
133
- .option("-l, --limit <n>", "Number of rows to fetch", "20")
134
- .option("-o, --offset <n>", "Starting offset", "0")
135
- .option("-s, --sort <field>", "Sort by field", "id")
136
- .option("--order <dir>", "Sort order (ASC/DESC)", "DESC")
137
- .option("-f, --filter <expr>", "Filter expression (field=value)")
132
+ .description("Listar registros (ej: gufi rows m360_t16192)")
133
+ .option("-l, --limit <n>", "Cantidad", "20")
134
+ .option("-o, --offset <n>", "Desde", "0")
135
+ .option("-s, --sort <field>", "Ordenar por", "id")
136
+ .option("--order <dir>", "ASC/DESC", "DESC")
137
+ .option("-f, --filter <expr>", "Filtro (campo=valor)")
138
138
  .action(rowsListCommand);
139
139
  program
140
140
  .command("row <table> <id>")
141
- .description("Get a single row by ID")
141
+ .description("Ver un registro por ID")
142
142
  .action(rowGetCommand);
143
143
  program
144
144
  .command("row:create <table>")
145
- .description("Create a new row")
146
- .option("-d, --data <json>", "JSON data for the row")
147
- .option("-f, --file <path>", "JSON file with row data")
145
+ .description("Crear registro")
146
+ .option("-d, --data <json>", "JSON con datos")
147
+ .option("-f, --file <path>", "Archivo JSON")
148
148
  .action(rowCreateCommand);
149
149
  program
150
150
  .command("row:update <table> <id>")
151
- .description("Update a row by ID")
152
- .option("-d, --data <json>", "JSON data to update")
153
- .option("-f, --file <path>", "JSON file with update data")
151
+ .description("Actualizar registro")
152
+ .option("-d, --data <json>", "JSON con cambios")
153
+ .option("-f, --file <path>", "Archivo JSON")
154
154
  .action(rowUpdateCommand);
155
155
  program
156
156
  .command("row:delete <table> <id>")
157
- .description("Delete a row by ID")
157
+ .description("Eliminar registro")
158
158
  .action(rowDeleteCommand);
159
159
  program
160
160
  .command("row:duplicate <table> <id>")
161
- .description("Duplicate an existing row")
161
+ .description("Duplicar registro existente")
162
162
  .action(rowDuplicateCommand);
163
163
  program
164
164
  .command("rows:create <table>")
165
- .description("Bulk create rows from JSON file")
166
- .option("-f, --file <path>", "JSON file with array of rows")
165
+ .description("Crear múltiples registros desde JSON")
166
+ .option("-f, --file <path>", "Archivo con array de objetos")
167
167
  .action(rowsBulkCreateCommand);
168
+ // ════════════════════════════════════════════════════════════════════
169
+ // 🎨 Views (Marketplace) - Desarrollo local
170
+ // ════════════════════════════════════════════════════════════════════
171
+ program
172
+ .command("views")
173
+ .description("Ver mis views del Marketplace")
174
+ .action(listCommand);
175
+ program
176
+ .command("view:pull [name]")
177
+ .description("Descargar vista para editar localmente")
178
+ .action(pullCommand);
179
+ program
180
+ .command("view:push")
181
+ .description("Subir cambios locales a Gufi")
182
+ .action(pushCommand);
183
+ program
184
+ .command("view:watch [dir]")
185
+ .description("Auto-sync al guardar archivos")
186
+ .action(watchCommand);
187
+ program
188
+ .command("view:status")
189
+ .description("Ver estado de sincronización")
190
+ .action(statusCommand);
191
+ program
192
+ .command("view:logs [dir]")
193
+ .description("Ver console.log del LivePreview")
194
+ .action(logsCommand);
168
195
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gufi-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "CLI for developing Gufi Marketplace views locally with Claude Code",
5
5
  "bin": {
6
6
  "gufi": "./bin/gufi.js"