gufi-cli 0.1.3 → 0.1.6
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 +37 -7
- package/dist/commands/rows.d.ts +46 -0
- package/dist/commands/rows.js +243 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +110 -53
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -1419,26 +1419,56 @@ gufi automation calcular_stock -c 116 --edit
|
|
|
1419
1419
|
gufi automation calcular_stock -c 116 --file script.js
|
|
1420
1420
|
```
|
|
1421
1421
|
|
|
1422
|
+
### Row CRUD (Datos de Tablas)
|
|
1423
|
+
|
|
1424
|
+
```bash
|
|
1425
|
+
# Listar registros de una tabla
|
|
1426
|
+
gufi rows m360_t16192 # Últimos 20 registros
|
|
1427
|
+
gufi rows m360_t16192 -l 50 # Últimos 50 registros
|
|
1428
|
+
gufi rows m360_t16192 -f estado=activo # Filtrar por campo
|
|
1429
|
+
|
|
1430
|
+
# Ver un registro específico
|
|
1431
|
+
gufi row m360_t16192 123
|
|
1432
|
+
|
|
1433
|
+
# Crear registro
|
|
1434
|
+
gufi row:create m360_t16192 --data '{"nombre":"Test","estado":"activo"}'
|
|
1435
|
+
gufi row:create m360_t16192 --file nuevo.json
|
|
1436
|
+
|
|
1437
|
+
# Actualizar registro
|
|
1438
|
+
gufi row:update m360_t16192 123 --data '{"estado":"completado"}'
|
|
1439
|
+
gufi row:update m360_t16192 123 --file cambios.json
|
|
1440
|
+
|
|
1441
|
+
# Eliminar registro
|
|
1442
|
+
gufi row:delete m360_t16192 123
|
|
1443
|
+
|
|
1444
|
+
# Duplicar registro (copia sin id/timestamps)
|
|
1445
|
+
gufi row:duplicate m360_t16192 123
|
|
1446
|
+
|
|
1447
|
+
# Crear múltiples registros desde archivo JSON
|
|
1448
|
+
gufi rows:create m360_t16192 --file datos.json
|
|
1449
|
+
# datos.json debe ser un array: [{"nombre":"A"},{"nombre":"B"}]
|
|
1450
|
+
```
|
|
1451
|
+
|
|
1422
1452
|
### Desarrollo de Views
|
|
1423
1453
|
|
|
1424
1454
|
```bash
|
|
1425
|
-
# Ver tus
|
|
1426
|
-
gufi
|
|
1455
|
+
# Ver tus views del Marketplace
|
|
1456
|
+
gufi views
|
|
1427
1457
|
|
|
1428
1458
|
# Descargar view para editar localmente
|
|
1429
|
-
gufi pull "Stock Overview"
|
|
1459
|
+
gufi view:pull "Stock Overview"
|
|
1430
1460
|
|
|
1431
1461
|
# Auto-sync al guardar archivos
|
|
1432
|
-
gufi watch
|
|
1462
|
+
gufi view:watch
|
|
1433
1463
|
|
|
1434
1464
|
# Ver console.log del LivePreview
|
|
1435
|
-
gufi logs
|
|
1465
|
+
gufi view:logs
|
|
1436
1466
|
|
|
1437
1467
|
# Subir cambios manualmente
|
|
1438
|
-
gufi push
|
|
1468
|
+
gufi view:push
|
|
1439
1469
|
|
|
1440
1470
|
# Ver estado de sincronización
|
|
1441
|
-
gufi status
|
|
1471
|
+
gufi view:status
|
|
1442
1472
|
```
|
|
1443
1473
|
|
|
1444
1474
|
### Opciones Globales
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gufi rows - CRUD operations on table rows
|
|
3
|
+
* For quick testing and data manipulation
|
|
4
|
+
*/
|
|
5
|
+
interface RowsOptions {
|
|
6
|
+
company?: string;
|
|
7
|
+
limit?: string;
|
|
8
|
+
offset?: string;
|
|
9
|
+
sort?: string;
|
|
10
|
+
order?: string;
|
|
11
|
+
filter?: string;
|
|
12
|
+
}
|
|
13
|
+
interface RowOptions {
|
|
14
|
+
company?: string;
|
|
15
|
+
data?: string;
|
|
16
|
+
file?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* gufi rows <table> - List rows from a table
|
|
20
|
+
*/
|
|
21
|
+
export declare function rowsListCommand(table: string, options: RowsOptions): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* gufi row <table> <id> - Get a single row
|
|
24
|
+
*/
|
|
25
|
+
export declare function rowGetCommand(table: string, id: string, options: RowOptions): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* gufi row:create <table> --data '{...}' - Create a row
|
|
28
|
+
*/
|
|
29
|
+
export declare function rowCreateCommand(table: string, options: RowOptions): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* gufi row:update <table> <id> --data '{...}' - Update a row
|
|
32
|
+
*/
|
|
33
|
+
export declare function rowUpdateCommand(table: string, id: string, options: RowOptions): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* gufi row:delete <table> <id> - Delete a row
|
|
36
|
+
*/
|
|
37
|
+
export declare function rowDeleteCommand(table: string, id: string, options: RowOptions): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* gufi row:duplicate <table> <id> - Duplicate a row
|
|
40
|
+
*/
|
|
41
|
+
export declare function rowDuplicateCommand(table: string, id: string, options: RowOptions): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* gufi rows:create <table> --file datos.json - Bulk create rows
|
|
44
|
+
*/
|
|
45
|
+
export declare function rowsBulkCreateCommand(table: string, options: RowOptions): Promise<void>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gufi rows - CRUD operations on table rows
|
|
3
|
+
* For quick testing and data manipulation
|
|
4
|
+
*/
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import ora from "ora";
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import { getToken, getApiUrl } from "../lib/config.js";
|
|
9
|
+
async function apiRequest(endpoint, options = {}) {
|
|
10
|
+
const token = getToken();
|
|
11
|
+
if (!token) {
|
|
12
|
+
throw new Error("No estás logueado. Ejecuta: gufi login");
|
|
13
|
+
}
|
|
14
|
+
const url = `${getApiUrl()}${endpoint}`;
|
|
15
|
+
const response = await fetch(url, {
|
|
16
|
+
...options,
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
Authorization: `Bearer ${token}`,
|
|
20
|
+
"X-Client": "cli",
|
|
21
|
+
...options.headers,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
const text = await response.text();
|
|
26
|
+
throw new Error(`API Error ${response.status}: ${text}`);
|
|
27
|
+
}
|
|
28
|
+
return response.json();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* gufi rows <table> - List rows from a table
|
|
32
|
+
*/
|
|
33
|
+
export async function rowsListCommand(table, options) {
|
|
34
|
+
const spinner = ora("Cargando registros...").start();
|
|
35
|
+
try {
|
|
36
|
+
const limit = options.limit || "20";
|
|
37
|
+
const offset = options.offset || "0";
|
|
38
|
+
const sort = options.sort || "id";
|
|
39
|
+
const order = options.order || "DESC";
|
|
40
|
+
let endpoint = `/api/tables/${table}?_start=${offset}&_end=${parseInt(offset) + parseInt(limit)}&_sort=${sort}&_order=${order}`;
|
|
41
|
+
if (options.filter) {
|
|
42
|
+
// Parse filter like "estado=pendiente"
|
|
43
|
+
const [field, value] = options.filter.split("=");
|
|
44
|
+
if (field && value) {
|
|
45
|
+
endpoint += `&${field}=${encodeURIComponent(value)}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const data = await apiRequest(endpoint);
|
|
49
|
+
spinner.stop();
|
|
50
|
+
console.log(chalk.magenta(`\n 📋 ${table}\n`));
|
|
51
|
+
if (!data || data.length === 0) {
|
|
52
|
+
console.log(chalk.gray(" No hay registros\n"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Show as table
|
|
56
|
+
const rows = Array.isArray(data) ? data : [data];
|
|
57
|
+
// Get columns from first row
|
|
58
|
+
const columns = Object.keys(rows[0]).slice(0, 6); // Max 6 columns
|
|
59
|
+
// Header
|
|
60
|
+
console.log(chalk.gray(" " + columns.map((c) => c.padEnd(15)).join(" ")));
|
|
61
|
+
console.log(chalk.gray(" " + "─".repeat(columns.length * 16)));
|
|
62
|
+
// Rows
|
|
63
|
+
for (const row of rows) {
|
|
64
|
+
const values = columns.map((col) => {
|
|
65
|
+
let val = row[col];
|
|
66
|
+
if (val === null || val === undefined)
|
|
67
|
+
val = "-";
|
|
68
|
+
if (typeof val === "object")
|
|
69
|
+
val = JSON.stringify(val).slice(0, 12);
|
|
70
|
+
return String(val).slice(0, 14).padEnd(15);
|
|
71
|
+
});
|
|
72
|
+
console.log(" " + values.join(" "));
|
|
73
|
+
}
|
|
74
|
+
console.log(chalk.gray(`\n Total: ${rows.length} registros\n`));
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
spinner.fail(chalk.red(error.message));
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* gufi row <table> <id> - Get a single row
|
|
83
|
+
*/
|
|
84
|
+
export async function rowGetCommand(table, id, options) {
|
|
85
|
+
const spinner = ora("Cargando registro...").start();
|
|
86
|
+
try {
|
|
87
|
+
const data = await apiRequest(`/api/tables/${table}/${id}`);
|
|
88
|
+
spinner.stop();
|
|
89
|
+
console.log(chalk.magenta(`\n 📄 ${table} #${id}\n`));
|
|
90
|
+
console.log(JSON.stringify(data, null, 2));
|
|
91
|
+
console.log();
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
spinner.fail(chalk.red(error.message));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* gufi row:create <table> --data '{...}' - Create a row
|
|
100
|
+
*/
|
|
101
|
+
export async function rowCreateCommand(table, options) {
|
|
102
|
+
const spinner = ora("Creando registro...").start();
|
|
103
|
+
try {
|
|
104
|
+
let data;
|
|
105
|
+
if (options.file) {
|
|
106
|
+
const content = fs.readFileSync(options.file, "utf-8");
|
|
107
|
+
data = JSON.parse(content);
|
|
108
|
+
}
|
|
109
|
+
else if (options.data) {
|
|
110
|
+
data = JSON.parse(options.data);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
spinner.fail(chalk.red("Usa --data '{...}' o --file datos.json"));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
const result = await apiRequest(`/api/tables/${table}`, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
body: JSON.stringify(data),
|
|
119
|
+
});
|
|
120
|
+
spinner.succeed(chalk.green(`Registro creado: ID ${result.id || result.data?.id}`));
|
|
121
|
+
console.log(chalk.gray(JSON.stringify(result.data || result, null, 2)));
|
|
122
|
+
console.log();
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
spinner.fail(chalk.red(error.message));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* gufi row:update <table> <id> --data '{...}' - Update a row
|
|
131
|
+
*/
|
|
132
|
+
export async function rowUpdateCommand(table, id, options) {
|
|
133
|
+
const spinner = ora("Actualizando registro...").start();
|
|
134
|
+
try {
|
|
135
|
+
let data;
|
|
136
|
+
if (options.file) {
|
|
137
|
+
const content = fs.readFileSync(options.file, "utf-8");
|
|
138
|
+
data = JSON.parse(content);
|
|
139
|
+
}
|
|
140
|
+
else if (options.data) {
|
|
141
|
+
data = JSON.parse(options.data);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
spinner.fail(chalk.red("Usa --data '{...}' o --file datos.json"));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
const result = await apiRequest(`/api/tables/${table}/${id}`, {
|
|
148
|
+
method: "PUT",
|
|
149
|
+
body: JSON.stringify(data),
|
|
150
|
+
});
|
|
151
|
+
spinner.succeed(chalk.green(`Registro #${id} actualizado`));
|
|
152
|
+
console.log(chalk.gray(JSON.stringify(result.data || result, null, 2)));
|
|
153
|
+
console.log();
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
spinner.fail(chalk.red(error.message));
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* gufi row:delete <table> <id> - Delete a row
|
|
162
|
+
*/
|
|
163
|
+
export async function rowDeleteCommand(table, id, options) {
|
|
164
|
+
const spinner = ora("Eliminando registro...").start();
|
|
165
|
+
try {
|
|
166
|
+
await apiRequest(`/api/tables/${table}/${id}`, {
|
|
167
|
+
method: "DELETE",
|
|
168
|
+
});
|
|
169
|
+
spinner.succeed(chalk.green(`Registro #${id} eliminado`));
|
|
170
|
+
console.log();
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
spinner.fail(chalk.red(error.message));
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* gufi row:duplicate <table> <id> - Duplicate a row
|
|
179
|
+
*/
|
|
180
|
+
export async function rowDuplicateCommand(table, id, options) {
|
|
181
|
+
const spinner = ora("Duplicando registro...").start();
|
|
182
|
+
try {
|
|
183
|
+
// Get original row
|
|
184
|
+
const original = await apiRequest(`/api/tables/${table}/${id}`);
|
|
185
|
+
// Remove id and timestamps
|
|
186
|
+
const { id: _, created_at, updated_at, ...data } = original;
|
|
187
|
+
// Create new row
|
|
188
|
+
const result = await apiRequest(`/api/tables/${table}`, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
body: JSON.stringify(data),
|
|
191
|
+
});
|
|
192
|
+
spinner.succeed(chalk.green(`Registro duplicado: #${id} → #${result.id || result.data?.id}`));
|
|
193
|
+
console.log();
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
spinner.fail(chalk.red(error.message));
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* gufi rows:create <table> --file datos.json - Bulk create rows
|
|
202
|
+
*/
|
|
203
|
+
export async function rowsBulkCreateCommand(table, options) {
|
|
204
|
+
if (!options.file) {
|
|
205
|
+
console.log(chalk.red("\n ✗ Usa --file datos.json\n"));
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
const spinner = ora("Creando registros...").start();
|
|
209
|
+
try {
|
|
210
|
+
const content = fs.readFileSync(options.file, "utf-8");
|
|
211
|
+
const rows = JSON.parse(content);
|
|
212
|
+
if (!Array.isArray(rows)) {
|
|
213
|
+
spinner.fail(chalk.red("El archivo debe contener un array de objetos"));
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
let created = 0;
|
|
217
|
+
let errors = 0;
|
|
218
|
+
for (const row of rows) {
|
|
219
|
+
try {
|
|
220
|
+
await apiRequest(`/api/tables/${table}`, {
|
|
221
|
+
method: "POST",
|
|
222
|
+
body: JSON.stringify(row),
|
|
223
|
+
});
|
|
224
|
+
created++;
|
|
225
|
+
spinner.text = `Creando registros... ${created}/${rows.length}`;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
errors++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (errors === 0) {
|
|
232
|
+
spinner.succeed(chalk.green(`${created} registros creados`));
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
spinner.warn(chalk.yellow(`${created} creados, ${errors} errores`));
|
|
236
|
+
}
|
|
237
|
+
console.log();
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
spinner.fail(chalk.red(error.message));
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,5 +20,14 @@
|
|
|
20
20
|
* gufi company:create Create a new company
|
|
21
21
|
* gufi automations List automation scripts
|
|
22
22
|
* gufi automation <name> View/edit automation code (--edit, --file)
|
|
23
|
+
*
|
|
24
|
+
* Row CRUD Commands:
|
|
25
|
+
* gufi rows <table> List rows from a table
|
|
26
|
+
* gufi row <table> <id> Get a single row
|
|
27
|
+
* gufi row:create <table> Create a new row (--data or --file)
|
|
28
|
+
* gufi row:update <table> <id> Update a row (--data or --file)
|
|
29
|
+
* gufi row:delete <table> <id> Delete a row
|
|
30
|
+
* gufi row:duplicate <table> <id> Duplicate a row
|
|
31
|
+
* gufi rows:create <table> Bulk create from JSON file
|
|
23
32
|
*/
|
|
24
33
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,15 @@
|
|
|
20
20
|
* gufi company:create Create a new company
|
|
21
21
|
* gufi automations List automation scripts
|
|
22
22
|
* gufi automation <name> View/edit automation code (--edit, --file)
|
|
23
|
+
*
|
|
24
|
+
* Row CRUD Commands:
|
|
25
|
+
* gufi rows <table> List rows from a table
|
|
26
|
+
* gufi row <table> <id> Get a single row
|
|
27
|
+
* gufi row:create <table> Create a new row (--data or --file)
|
|
28
|
+
* gufi row:update <table> <id> Update a row (--data or --file)
|
|
29
|
+
* gufi row:delete <table> <id> Delete a row
|
|
30
|
+
* gufi row:duplicate <table> <id> Duplicate a row
|
|
31
|
+
* gufi rows:create <table> Bulk create from JSON file
|
|
23
32
|
*/
|
|
24
33
|
import { Command } from "commander";
|
|
25
34
|
import { loginCommand, logoutCommand, whoamiCommand } from "./commands/login.js";
|
|
@@ -29,89 +38,137 @@ import { watchCommand } from "./commands/watch.js";
|
|
|
29
38
|
import { listCommand } from "./commands/list.js";
|
|
30
39
|
import { logsCommand } from "./commands/logs.js";
|
|
31
40
|
import { companiesCommand, modulesCommand, moduleCommand, moduleUpdateCommand, companyCreateCommand, automationsCommand, automationCommand, } from "./commands/companies.js";
|
|
41
|
+
import { rowsListCommand, rowGetCommand, rowCreateCommand, rowUpdateCommand, rowDeleteCommand, rowDuplicateCommand, rowsBulkCreateCommand, } from "./commands/rows.js";
|
|
32
42
|
const program = new Command();
|
|
33
43
|
program
|
|
34
44
|
.name("gufi")
|
|
35
|
-
.description("Gufi
|
|
36
|
-
.version("0.1.
|
|
37
|
-
//
|
|
45
|
+
.description("🟣 Gufi CLI - Desarrolla módulos, vistas y automations")
|
|
46
|
+
.version("0.1.6");
|
|
47
|
+
// ════════════════════════════════════════════════════════════════════
|
|
48
|
+
// 🔐 Auth
|
|
49
|
+
// ════════════════════════════════════════════════════════════════════
|
|
38
50
|
program
|
|
39
51
|
.command("login")
|
|
40
|
-
.description("
|
|
41
|
-
.option("--api <url>", "
|
|
52
|
+
.description("Iniciar sesión en Gufi")
|
|
53
|
+
.option("--api <url>", "URL de API personalizada")
|
|
42
54
|
.action(loginCommand);
|
|
43
55
|
program
|
|
44
56
|
.command("logout")
|
|
45
|
-
.description("
|
|
57
|
+
.description("Cerrar sesión")
|
|
46
58
|
.action(logoutCommand);
|
|
47
59
|
program
|
|
48
60
|
.command("whoami")
|
|
49
|
-
.description("
|
|
61
|
+
.description("Ver usuario actual")
|
|
50
62
|
.action(whoamiCommand);
|
|
51
|
-
// Sync commands
|
|
52
|
-
program
|
|
53
|
-
.command("pull [view]")
|
|
54
|
-
.description("Download view files from Gufi")
|
|
55
|
-
.action(pullCommand);
|
|
56
|
-
program
|
|
57
|
-
.command("push")
|
|
58
|
-
.description("Upload local changes to Gufi")
|
|
59
|
-
.action(pushCommand);
|
|
60
|
-
program
|
|
61
|
-
.command("watch [dir]")
|
|
62
|
-
.description("Watch for file changes and auto-sync")
|
|
63
|
-
.action(watchCommand);
|
|
64
|
-
program
|
|
65
|
-
.command("status")
|
|
66
|
-
.description("Show sync status")
|
|
67
|
-
.action(statusCommand);
|
|
68
|
-
program
|
|
69
|
-
.command("list")
|
|
70
|
-
.alias("ls")
|
|
71
|
-
.description("List your packages and views")
|
|
72
|
-
.action(listCommand);
|
|
73
|
-
program
|
|
74
|
-
.command("logs [dir]")
|
|
75
|
-
.description("Stream console logs from LivePreview in real-time")
|
|
76
|
-
.action(logsCommand);
|
|
77
63
|
// ════════════════════════════════════════════════════════════════════
|
|
78
|
-
//
|
|
64
|
+
// 🏢 Companies & Modules
|
|
79
65
|
// ════════════════════════════════════════════════════════════════════
|
|
80
66
|
program
|
|
81
67
|
.command("companies")
|
|
82
|
-
.description("
|
|
68
|
+
.description("Ver mis companies")
|
|
83
69
|
.action(companiesCommand);
|
|
70
|
+
program
|
|
71
|
+
.command("company:create <name>")
|
|
72
|
+
.description("Crear nueva company")
|
|
73
|
+
.action(companyCreateCommand);
|
|
84
74
|
program
|
|
85
75
|
.command("modules <company_id>")
|
|
86
|
-
.description("
|
|
76
|
+
.description("Ver módulos de una company")
|
|
87
77
|
.action(modulesCommand);
|
|
88
78
|
program
|
|
89
79
|
.command("module <module_id>")
|
|
90
|
-
.description("
|
|
91
|
-
.option("-e, --edit", "
|
|
92
|
-
.option("-c, --company <id>", "
|
|
93
|
-
.option("-f, --file <path>", "
|
|
80
|
+
.description("Ver/editar JSON de un módulo")
|
|
81
|
+
.option("-e, --edit", "Abrir en editor")
|
|
82
|
+
.option("-c, --company <id>", "ID de company")
|
|
83
|
+
.option("-f, --file <path>", "Exportar a archivo")
|
|
94
84
|
.action(moduleCommand);
|
|
95
85
|
program
|
|
96
86
|
.command("module:update <module_id> <json_file>")
|
|
97
|
-
.description("
|
|
98
|
-
.option("-c, --company <id>", "
|
|
99
|
-
.option("--dry-run", "
|
|
87
|
+
.description("Actualizar módulo desde archivo JSON")
|
|
88
|
+
.option("-c, --company <id>", "ID de company")
|
|
89
|
+
.option("--dry-run", "Validar sin guardar")
|
|
100
90
|
.action(moduleUpdateCommand);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.action(companyCreateCommand);
|
|
91
|
+
// ════════════════════════════════════════════════════════════════════
|
|
92
|
+
// ⚡ Automations
|
|
93
|
+
// ════════════════════════════════════════════════════════════════════
|
|
105
94
|
program
|
|
106
95
|
.command("automations")
|
|
107
|
-
.description("
|
|
108
|
-
.option("-c, --company <id>", "
|
|
96
|
+
.description("Ver scripts de automation")
|
|
97
|
+
.option("-c, --company <id>", "ID de company")
|
|
109
98
|
.action(automationsCommand);
|
|
110
99
|
program
|
|
111
100
|
.command("automation <name>")
|
|
112
|
-
.description("
|
|
113
|
-
.option("-e, --edit", "
|
|
114
|
-
.option("-c, --company <id>", "
|
|
115
|
-
.option("-f, --file <path>", "
|
|
101
|
+
.description("Ver/editar código de automation")
|
|
102
|
+
.option("-e, --edit", "Abrir en editor")
|
|
103
|
+
.option("-c, --company <id>", "ID de company")
|
|
104
|
+
.option("-f, --file <path>", "Exportar a archivo")
|
|
116
105
|
.action(automationCommand);
|
|
106
|
+
// ════════════════════════════════════════════════════════════════════
|
|
107
|
+
// 📊 Row CRUD - Datos de tablas
|
|
108
|
+
// ════════════════════════════════════════════════════════════════════
|
|
109
|
+
program
|
|
110
|
+
.command("rows <table>")
|
|
111
|
+
.description("Listar registros (ej: gufi rows m360_t16192)")
|
|
112
|
+
.option("-l, --limit <n>", "Cantidad", "20")
|
|
113
|
+
.option("-o, --offset <n>", "Desde", "0")
|
|
114
|
+
.option("-s, --sort <field>", "Ordenar por", "id")
|
|
115
|
+
.option("--order <dir>", "ASC/DESC", "DESC")
|
|
116
|
+
.option("-f, --filter <expr>", "Filtro (campo=valor)")
|
|
117
|
+
.action(rowsListCommand);
|
|
118
|
+
program
|
|
119
|
+
.command("row <table> <id>")
|
|
120
|
+
.description("Ver un registro por ID")
|
|
121
|
+
.action(rowGetCommand);
|
|
122
|
+
program
|
|
123
|
+
.command("row:create <table>")
|
|
124
|
+
.description("Crear registro")
|
|
125
|
+
.option("-d, --data <json>", "JSON con datos")
|
|
126
|
+
.option("-f, --file <path>", "Archivo JSON")
|
|
127
|
+
.action(rowCreateCommand);
|
|
128
|
+
program
|
|
129
|
+
.command("row:update <table> <id>")
|
|
130
|
+
.description("Actualizar registro")
|
|
131
|
+
.option("-d, --data <json>", "JSON con cambios")
|
|
132
|
+
.option("-f, --file <path>", "Archivo JSON")
|
|
133
|
+
.action(rowUpdateCommand);
|
|
134
|
+
program
|
|
135
|
+
.command("row:delete <table> <id>")
|
|
136
|
+
.description("Eliminar registro")
|
|
137
|
+
.action(rowDeleteCommand);
|
|
138
|
+
program
|
|
139
|
+
.command("row:duplicate <table> <id>")
|
|
140
|
+
.description("Duplicar registro existente")
|
|
141
|
+
.action(rowDuplicateCommand);
|
|
142
|
+
program
|
|
143
|
+
.command("rows:create <table>")
|
|
144
|
+
.description("Crear múltiples registros desde JSON")
|
|
145
|
+
.option("-f, --file <path>", "Archivo con array de objetos")
|
|
146
|
+
.action(rowsBulkCreateCommand);
|
|
147
|
+
// ════════════════════════════════════════════════════════════════════
|
|
148
|
+
// 🎨 Views (Marketplace) - Desarrollo local
|
|
149
|
+
// ════════════════════════════════════════════════════════════════════
|
|
150
|
+
program
|
|
151
|
+
.command("views")
|
|
152
|
+
.description("Ver mis views del Marketplace")
|
|
153
|
+
.action(listCommand);
|
|
154
|
+
program
|
|
155
|
+
.command("view:pull [name]")
|
|
156
|
+
.description("Descargar vista para editar localmente")
|
|
157
|
+
.action(pullCommand);
|
|
158
|
+
program
|
|
159
|
+
.command("view:push")
|
|
160
|
+
.description("Subir cambios locales a Gufi")
|
|
161
|
+
.action(pushCommand);
|
|
162
|
+
program
|
|
163
|
+
.command("view:watch [dir]")
|
|
164
|
+
.description("Auto-sync al guardar archivos")
|
|
165
|
+
.action(watchCommand);
|
|
166
|
+
program
|
|
167
|
+
.command("view:status")
|
|
168
|
+
.description("Ver estado de sincronización")
|
|
169
|
+
.action(statusCommand);
|
|
170
|
+
program
|
|
171
|
+
.command("view:logs [dir]")
|
|
172
|
+
.description("Ver console.log del LivePreview")
|
|
173
|
+
.action(logsCommand);
|
|
117
174
|
program.parse();
|