gufi-cli 0.1.13 β 0.1.17
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 +298 -40
- package/dist/commands/companies.d.ts +12 -1
- package/dist/commands/companies.js +355 -40
- package/dist/commands/packages.d.ts +25 -0
- package/dist/commands/packages.js +518 -0
- package/dist/commands/rows.d.ts +2 -0
- package/dist/commands/rows.js +143 -33
- package/dist/index.d.ts +30 -22
- package/dist/index.js +109 -41
- package/dist/lib/api.js +10 -2
- package/dist/lib/config.js +2 -2
- package/package.json +1 -1
package/dist/commands/rows.js
CHANGED
|
@@ -6,6 +6,8 @@ import chalk from "chalk";
|
|
|
6
6
|
import ora from "ora";
|
|
7
7
|
import fs from "fs";
|
|
8
8
|
import { getToken, getApiUrl, loadConfig, getRefreshToken, setToken } from "../lib/config.js";
|
|
9
|
+
// π Cache for module β company mapping (avoid repeated lookups)
|
|
10
|
+
const moduleCompanyCache = new Map();
|
|
9
11
|
// π Auto-login with saved credentials
|
|
10
12
|
async function autoLogin() {
|
|
11
13
|
const config = loadConfig();
|
|
@@ -48,7 +50,7 @@ async function refreshOrLogin() {
|
|
|
48
50
|
return autoLogin();
|
|
49
51
|
}
|
|
50
52
|
// π API request with auto-login and refresh
|
|
51
|
-
async function apiRequest(endpoint, options = {}, retry = true) {
|
|
53
|
+
async function apiRequest(endpoint, options = {}, companyId, retry = true) {
|
|
52
54
|
let token = getToken();
|
|
53
55
|
if (!token) {
|
|
54
56
|
token = await autoLogin();
|
|
@@ -56,19 +58,26 @@ async function apiRequest(endpoint, options = {}, retry = true) {
|
|
|
56
58
|
throw new Error("No estΓ‘s logueado. Ejecuta: gufi login");
|
|
57
59
|
}
|
|
58
60
|
const url = `${getApiUrl()}${endpoint}`;
|
|
61
|
+
const headers = {
|
|
62
|
+
"Content-Type": "application/json",
|
|
63
|
+
Authorization: `Bearer ${token}`,
|
|
64
|
+
"X-Client": "cli",
|
|
65
|
+
};
|
|
66
|
+
// Add company header if specified
|
|
67
|
+
if (companyId) {
|
|
68
|
+
headers["X-Company-ID"] = companyId;
|
|
69
|
+
}
|
|
59
70
|
const response = await fetch(url, {
|
|
60
71
|
...options,
|
|
61
72
|
headers: {
|
|
62
|
-
|
|
63
|
-
Authorization: `Bearer ${token}`,
|
|
64
|
-
"X-Client": "cli",
|
|
73
|
+
...headers,
|
|
65
74
|
...options.headers,
|
|
66
75
|
},
|
|
67
76
|
});
|
|
68
77
|
if ((response.status === 401 || response.status === 403) && retry) {
|
|
69
78
|
const newToken = await refreshOrLogin();
|
|
70
79
|
if (newToken)
|
|
71
|
-
return apiRequest(endpoint, options, false);
|
|
80
|
+
return apiRequest(endpoint, options, companyId, false);
|
|
72
81
|
}
|
|
73
82
|
if (!response.ok) {
|
|
74
83
|
const text = await response.text();
|
|
@@ -76,35 +85,109 @@ async function apiRequest(endpoint, options = {}, retry = true) {
|
|
|
76
85
|
}
|
|
77
86
|
return response.json();
|
|
78
87
|
}
|
|
88
|
+
// π Parse module ID from table name (e.g., "m308_t4136" β 308)
|
|
89
|
+
function parseModuleId(table) {
|
|
90
|
+
const match = table.match(/^m(\d+)_t\d+$/);
|
|
91
|
+
return match ? parseInt(match[1], 10) : null;
|
|
92
|
+
}
|
|
93
|
+
// π Detect company from table/module name (auto-switch company)
|
|
94
|
+
async function detectCompanyFromTable(table) {
|
|
95
|
+
const moduleId = parseModuleId(table);
|
|
96
|
+
if (!moduleId)
|
|
97
|
+
return undefined;
|
|
98
|
+
// Check cache first
|
|
99
|
+
if (moduleCompanyCache.has(moduleId)) {
|
|
100
|
+
return moduleCompanyCache.get(moduleId);
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
// Get all companies the user has access to
|
|
104
|
+
const companiesData = await apiRequest("/api/companies");
|
|
105
|
+
const companies = companiesData.items || companiesData.data || companiesData || [];
|
|
106
|
+
// Search through each company's schema for the module
|
|
107
|
+
for (const company of companies) {
|
|
108
|
+
try {
|
|
109
|
+
const schemaData = await apiRequest("/api/company/schema", {
|
|
110
|
+
headers: { "X-Company-ID": String(company.id) },
|
|
111
|
+
});
|
|
112
|
+
const modules = schemaData.modules || schemaData.data?.modules || [];
|
|
113
|
+
// Check if any entity in any submodule has this moduleId
|
|
114
|
+
for (const mod of modules) {
|
|
115
|
+
for (const sub of mod.submodules || []) {
|
|
116
|
+
for (const ent of sub.entities || []) {
|
|
117
|
+
if (ent.ui?.moduleId === moduleId) {
|
|
118
|
+
// Found! Cache and return
|
|
119
|
+
const companyIdStr = String(company.id);
|
|
120
|
+
moduleCompanyCache.set(moduleId, companyIdStr);
|
|
121
|
+
return companyIdStr;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Skip companies we can't access
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// If we can't get companies, return undefined
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
// π Get company ID - use provided or auto-detect from table
|
|
140
|
+
async function resolveCompanyId(table, providedCompanyId) {
|
|
141
|
+
if (providedCompanyId)
|
|
142
|
+
return providedCompanyId;
|
|
143
|
+
const detected = await detectCompanyFromTable(table);
|
|
144
|
+
if (detected) {
|
|
145
|
+
console.log(chalk.gray(` [gufi] Auto-detected company: ${detected} (from module ${parseModuleId(table)})`));
|
|
146
|
+
}
|
|
147
|
+
return detected;
|
|
148
|
+
}
|
|
79
149
|
/**
|
|
80
150
|
* gufi rows <table> - List rows from a table
|
|
151
|
+
* Uses POST /api/tables/:table/list
|
|
81
152
|
*/
|
|
82
153
|
export async function rowsListCommand(table, options) {
|
|
83
|
-
const spinner = ora("
|
|
154
|
+
const spinner = ora("Detectando company...").start();
|
|
84
155
|
try {
|
|
85
|
-
|
|
86
|
-
const
|
|
156
|
+
// π Auto-detect company from table name if not provided
|
|
157
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
158
|
+
spinner.text = "Cargando registros...";
|
|
159
|
+
const limit = parseInt(options.limit || "20");
|
|
160
|
+
const offset = parseInt(options.offset || "0");
|
|
87
161
|
const sort = options.sort || "id";
|
|
88
|
-
const order = options.order || "
|
|
89
|
-
|
|
162
|
+
const order = options.order || "desc";
|
|
163
|
+
// Build request body for POST /api/tables/:table/list
|
|
164
|
+
const body = {
|
|
165
|
+
pagination: { current: Math.floor(offset / limit) + 1, pageSize: limit },
|
|
166
|
+
sorters: [{ field: sort, order }],
|
|
167
|
+
filters: [],
|
|
168
|
+
};
|
|
90
169
|
if (options.filter) {
|
|
91
170
|
// Parse filter like "estado=pendiente"
|
|
92
171
|
const [field, value] = options.filter.split("=");
|
|
93
172
|
if (field && value) {
|
|
94
|
-
|
|
173
|
+
body.filters.push({ field, operator: "eq", value });
|
|
95
174
|
}
|
|
96
175
|
}
|
|
97
|
-
const
|
|
176
|
+
const result = await apiRequest(`/api/tables/${table}/list`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
body: JSON.stringify(body),
|
|
179
|
+
}, companyId);
|
|
98
180
|
spinner.stop();
|
|
99
181
|
console.log(chalk.magenta(`\n π ${table}\n`));
|
|
100
|
-
|
|
182
|
+
const rows = result.data || [];
|
|
183
|
+
if (rows.length === 0) {
|
|
101
184
|
console.log(chalk.gray(" No hay registros\n"));
|
|
102
185
|
return;
|
|
103
186
|
}
|
|
104
|
-
//
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
187
|
+
// Get columns from first row (max 6, skip __display fields)
|
|
188
|
+
const columns = Object.keys(rows[0])
|
|
189
|
+
.filter(k => !k.includes("__"))
|
|
190
|
+
.slice(0, 6);
|
|
108
191
|
// Header
|
|
109
192
|
console.log(chalk.gray(" " + columns.map((c) => c.padEnd(15)).join(" ")));
|
|
110
193
|
console.log(chalk.gray(" " + "β".repeat(columns.length * 16)));
|
|
@@ -120,7 +203,7 @@ export async function rowsListCommand(table, options) {
|
|
|
120
203
|
});
|
|
121
204
|
console.log(" " + values.join(" "));
|
|
122
205
|
}
|
|
123
|
-
console.log(chalk.gray(`\n Total: ${rows.length} registros\n`));
|
|
206
|
+
console.log(chalk.gray(`\n Total: ${rows.length} registros (de ${result.total || "?"})\n`));
|
|
124
207
|
}
|
|
125
208
|
catch (error) {
|
|
126
209
|
spinner.fail(chalk.red(error.message));
|
|
@@ -129,12 +212,20 @@ export async function rowsListCommand(table, options) {
|
|
|
129
212
|
}
|
|
130
213
|
/**
|
|
131
214
|
* gufi row <table> <id> - Get a single row
|
|
215
|
+
* Uses POST /api/tables/:table/getOne
|
|
132
216
|
*/
|
|
133
217
|
export async function rowGetCommand(table, id, options) {
|
|
134
|
-
const spinner = ora("
|
|
218
|
+
const spinner = ora("Detectando company...").start();
|
|
135
219
|
try {
|
|
136
|
-
|
|
220
|
+
// π Auto-detect company from table name if not provided
|
|
221
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
222
|
+
spinner.text = "Cargando registro...";
|
|
223
|
+
const result = await apiRequest(`/api/tables/${table}/getOne`, {
|
|
224
|
+
method: "POST",
|
|
225
|
+
body: JSON.stringify({ id: parseInt(id) }),
|
|
226
|
+
}, companyId);
|
|
137
227
|
spinner.stop();
|
|
228
|
+
const data = result.data || result;
|
|
138
229
|
console.log(chalk.magenta(`\n π ${table} #${id}\n`));
|
|
139
230
|
console.log(JSON.stringify(data, null, 2));
|
|
140
231
|
console.log();
|
|
@@ -148,8 +239,11 @@ export async function rowGetCommand(table, id, options) {
|
|
|
148
239
|
* gufi row:create <table> --data '{...}' - Create a row
|
|
149
240
|
*/
|
|
150
241
|
export async function rowCreateCommand(table, options) {
|
|
151
|
-
const spinner = ora("
|
|
242
|
+
const spinner = ora("Detectando company...").start();
|
|
152
243
|
try {
|
|
244
|
+
// π Auto-detect company from table name if not provided
|
|
245
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
246
|
+
spinner.text = "Creando registro...";
|
|
153
247
|
let data;
|
|
154
248
|
if (options.file) {
|
|
155
249
|
const content = fs.readFileSync(options.file, "utf-8");
|
|
@@ -165,7 +259,7 @@ export async function rowCreateCommand(table, options) {
|
|
|
165
259
|
const result = await apiRequest(`/api/tables/${table}`, {
|
|
166
260
|
method: "POST",
|
|
167
261
|
body: JSON.stringify(data),
|
|
168
|
-
});
|
|
262
|
+
}, companyId);
|
|
169
263
|
spinner.succeed(chalk.green(`Registro creado: ID ${result.id || result.data?.id}`));
|
|
170
264
|
console.log(chalk.gray(JSON.stringify(result.data || result, null, 2)));
|
|
171
265
|
console.log();
|
|
@@ -179,8 +273,11 @@ export async function rowCreateCommand(table, options) {
|
|
|
179
273
|
* gufi row:update <table> <id> --data '{...}' - Update a row
|
|
180
274
|
*/
|
|
181
275
|
export async function rowUpdateCommand(table, id, options) {
|
|
182
|
-
const spinner = ora("
|
|
276
|
+
const spinner = ora("Detectando company...").start();
|
|
183
277
|
try {
|
|
278
|
+
// π Auto-detect company from table name if not provided
|
|
279
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
280
|
+
spinner.text = "Actualizando registro...";
|
|
184
281
|
let data;
|
|
185
282
|
if (options.file) {
|
|
186
283
|
const content = fs.readFileSync(options.file, "utf-8");
|
|
@@ -196,7 +293,7 @@ export async function rowUpdateCommand(table, id, options) {
|
|
|
196
293
|
const result = await apiRequest(`/api/tables/${table}/${id}`, {
|
|
197
294
|
method: "PUT",
|
|
198
295
|
body: JSON.stringify(data),
|
|
199
|
-
});
|
|
296
|
+
}, companyId);
|
|
200
297
|
spinner.succeed(chalk.green(`Registro #${id} actualizado`));
|
|
201
298
|
console.log(chalk.gray(JSON.stringify(result.data || result, null, 2)));
|
|
202
299
|
console.log();
|
|
@@ -210,11 +307,14 @@ export async function rowUpdateCommand(table, id, options) {
|
|
|
210
307
|
* gufi row:delete <table> <id> - Delete a row
|
|
211
308
|
*/
|
|
212
309
|
export async function rowDeleteCommand(table, id, options) {
|
|
213
|
-
const spinner = ora("
|
|
310
|
+
const spinner = ora("Detectando company...").start();
|
|
214
311
|
try {
|
|
312
|
+
// π Auto-detect company from table name if not provided
|
|
313
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
314
|
+
spinner.text = "Eliminando registro...";
|
|
215
315
|
await apiRequest(`/api/tables/${table}/${id}`, {
|
|
216
316
|
method: "DELETE",
|
|
217
|
-
});
|
|
317
|
+
}, companyId);
|
|
218
318
|
spinner.succeed(chalk.green(`Registro #${id} eliminado`));
|
|
219
319
|
console.log();
|
|
220
320
|
}
|
|
@@ -227,17 +327,24 @@ export async function rowDeleteCommand(table, id, options) {
|
|
|
227
327
|
* gufi row:duplicate <table> <id> - Duplicate a row
|
|
228
328
|
*/
|
|
229
329
|
export async function rowDuplicateCommand(table, id, options) {
|
|
230
|
-
const spinner = ora("
|
|
330
|
+
const spinner = ora("Detectando company...").start();
|
|
231
331
|
try {
|
|
232
|
-
//
|
|
233
|
-
const
|
|
332
|
+
// π Auto-detect company from table name if not provided
|
|
333
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
334
|
+
spinner.text = "Duplicando registro...";
|
|
335
|
+
// Get original row using getOne
|
|
336
|
+
const originalResult = await apiRequest(`/api/tables/${table}/getOne`, {
|
|
337
|
+
method: "POST",
|
|
338
|
+
body: JSON.stringify({ id: parseInt(id) }),
|
|
339
|
+
}, companyId);
|
|
340
|
+
const original = originalResult.data || originalResult;
|
|
234
341
|
// Remove id and timestamps
|
|
235
|
-
const { id:
|
|
342
|
+
const { id: _id, created_at, updated_at, ...data } = original;
|
|
236
343
|
// Create new row
|
|
237
344
|
const result = await apiRequest(`/api/tables/${table}`, {
|
|
238
345
|
method: "POST",
|
|
239
346
|
body: JSON.stringify(data),
|
|
240
|
-
});
|
|
347
|
+
}, companyId);
|
|
241
348
|
spinner.succeed(chalk.green(`Registro duplicado: #${id} β #${result.id || result.data?.id}`));
|
|
242
349
|
console.log();
|
|
243
350
|
}
|
|
@@ -254,8 +361,11 @@ export async function rowsBulkCreateCommand(table, options) {
|
|
|
254
361
|
console.log(chalk.red("\n β Usa --file datos.json\n"));
|
|
255
362
|
process.exit(1);
|
|
256
363
|
}
|
|
257
|
-
const spinner = ora("
|
|
364
|
+
const spinner = ora("Detectando company...").start();
|
|
258
365
|
try {
|
|
366
|
+
// π Auto-detect company from table name if not provided
|
|
367
|
+
const companyId = await resolveCompanyId(table, options.company);
|
|
368
|
+
spinner.text = "Creando registros...";
|
|
259
369
|
const content = fs.readFileSync(options.file, "utf-8");
|
|
260
370
|
const rows = JSON.parse(content);
|
|
261
371
|
if (!Array.isArray(rows)) {
|
|
@@ -269,7 +379,7 @@ export async function rowsBulkCreateCommand(table, options) {
|
|
|
269
379
|
await apiRequest(`/api/tables/${table}`, {
|
|
270
380
|
method: "POST",
|
|
271
381
|
body: JSON.stringify(row),
|
|
272
|
-
});
|
|
382
|
+
}, companyId);
|
|
273
383
|
created++;
|
|
274
384
|
spinner.text = `Creando registros... ${created}/${rows.length}`;
|
|
275
385
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,33 +2,41 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Gufi Dev CLI - Main Entry Point
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* gufi login Login
|
|
7
|
-
* gufi logout Logout
|
|
5
|
+
* Auth:
|
|
6
|
+
* gufi login Login (credentials saved for auto-login)
|
|
7
|
+
* gufi logout Logout (keeps credentials)
|
|
8
8
|
* gufi whoami Show current user
|
|
9
|
-
* gufi pull [view] Download view files
|
|
10
|
-
* gufi push Upload local changes
|
|
11
|
-
* gufi watch Auto-sync file changes
|
|
12
|
-
* gufi status Show sync status
|
|
13
|
-
* gufi logs [dir] Stream console logs from LivePreview
|
|
14
9
|
*
|
|
15
|
-
*
|
|
10
|
+
* Companies & Modules:
|
|
16
11
|
* gufi companies List your companies
|
|
17
12
|
* gufi modules <id> List modules of a company
|
|
18
|
-
* gufi module <id> View/edit module JSON (
|
|
13
|
+
* gufi module <id> View/edit module JSON (auto-detects company)
|
|
19
14
|
* gufi module:update Update module from JSON file
|
|
20
|
-
* gufi module:create Create module from JSON file
|
|
21
|
-
* gufi company:create Create a new company
|
|
22
|
-
* gufi automations List automation scripts
|
|
23
|
-
* gufi automation <name> View/edit automation code (--edit, --file)
|
|
24
15
|
*
|
|
25
|
-
*
|
|
26
|
-
* gufi
|
|
27
|
-
* gufi
|
|
28
|
-
* gufi
|
|
29
|
-
* gufi
|
|
30
|
-
* gufi
|
|
31
|
-
*
|
|
32
|
-
*
|
|
16
|
+
* Automations:
|
|
17
|
+
* gufi automations List automation scripts
|
|
18
|
+
* gufi automation <id> View/edit automation code
|
|
19
|
+
* gufi automations:meta View worker index (debugging)
|
|
20
|
+
* gufi automations:executions View execution history
|
|
21
|
+
* gufi entity:automations View/edit entity triggers
|
|
22
|
+
*
|
|
23
|
+
* Row CRUD:
|
|
24
|
+
* gufi rows <table> List rows (auto-detects company)
|
|
25
|
+
* gufi row <table> <id> Get/update/delete a row
|
|
26
|
+
*
|
|
27
|
+
* Packages (Marketplace):
|
|
28
|
+
* gufi packages List my packages (with views)
|
|
29
|
+
* gufi package <id> View package details
|
|
30
|
+
* gufi package:create Create new package
|
|
31
|
+
* gufi package:add-module Add module to package
|
|
32
|
+
* gufi package:add-view Add view to package
|
|
33
|
+
* gufi package:publish Publish to Marketplace
|
|
34
|
+
* gufi package:sync Sync version
|
|
35
|
+
*
|
|
36
|
+
* View Development:
|
|
37
|
+
* gufi pull <viewId> Download view for local editing
|
|
38
|
+
* gufi push Upload local changes
|
|
39
|
+
* gufi watch Auto-sync on save
|
|
40
|
+
* gufi logs Console.log from LivePreview
|
|
33
41
|
*/
|
|
34
42
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -2,45 +2,56 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Gufi Dev CLI - Main Entry Point
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* gufi login Login
|
|
7
|
-
* gufi logout Logout
|
|
5
|
+
* Auth:
|
|
6
|
+
* gufi login Login (credentials saved for auto-login)
|
|
7
|
+
* gufi logout Logout (keeps credentials)
|
|
8
8
|
* gufi whoami Show current user
|
|
9
|
-
* gufi pull [view] Download view files
|
|
10
|
-
* gufi push Upload local changes
|
|
11
|
-
* gufi watch Auto-sync file changes
|
|
12
|
-
* gufi status Show sync status
|
|
13
|
-
* gufi logs [dir] Stream console logs from LivePreview
|
|
14
9
|
*
|
|
15
|
-
*
|
|
10
|
+
* Companies & Modules:
|
|
16
11
|
* gufi companies List your companies
|
|
17
12
|
* gufi modules <id> List modules of a company
|
|
18
|
-
* gufi module <id> View/edit module JSON (
|
|
13
|
+
* gufi module <id> View/edit module JSON (auto-detects company)
|
|
19
14
|
* gufi module:update Update module from JSON file
|
|
20
|
-
* gufi module:create Create module from JSON file
|
|
21
|
-
* gufi company:create Create a new company
|
|
22
|
-
* gufi automations List automation scripts
|
|
23
|
-
* gufi automation <name> View/edit automation code (--edit, --file)
|
|
24
15
|
*
|
|
25
|
-
*
|
|
26
|
-
* gufi
|
|
27
|
-
* gufi
|
|
28
|
-
* gufi
|
|
29
|
-
* gufi
|
|
30
|
-
* gufi
|
|
31
|
-
*
|
|
32
|
-
*
|
|
16
|
+
* Automations:
|
|
17
|
+
* gufi automations List automation scripts
|
|
18
|
+
* gufi automation <id> View/edit automation code
|
|
19
|
+
* gufi automations:meta View worker index (debugging)
|
|
20
|
+
* gufi automations:executions View execution history
|
|
21
|
+
* gufi entity:automations View/edit entity triggers
|
|
22
|
+
*
|
|
23
|
+
* Row CRUD:
|
|
24
|
+
* gufi rows <table> List rows (auto-detects company)
|
|
25
|
+
* gufi row <table> <id> Get/update/delete a row
|
|
26
|
+
*
|
|
27
|
+
* Packages (Marketplace):
|
|
28
|
+
* gufi packages List my packages (with views)
|
|
29
|
+
* gufi package <id> View package details
|
|
30
|
+
* gufi package:create Create new package
|
|
31
|
+
* gufi package:add-module Add module to package
|
|
32
|
+
* gufi package:add-view Add view to package
|
|
33
|
+
* gufi package:publish Publish to Marketplace
|
|
34
|
+
* gufi package:sync Sync version
|
|
35
|
+
*
|
|
36
|
+
* View Development:
|
|
37
|
+
* gufi pull <viewId> Download view for local editing
|
|
38
|
+
* gufi push Upload local changes
|
|
39
|
+
* gufi watch Auto-sync on save
|
|
40
|
+
* gufi logs Console.log from LivePreview
|
|
33
41
|
*/
|
|
34
42
|
import { Command } from "commander";
|
|
35
43
|
import { loginCommand, logoutCommand, whoamiCommand } from "./commands/login.js";
|
|
36
44
|
import { pullCommand } from "./commands/pull.js";
|
|
37
45
|
import { pushCommand, statusCommand } from "./commands/push.js";
|
|
38
46
|
import { watchCommand } from "./commands/watch.js";
|
|
39
|
-
|
|
47
|
+
// listCommand removed - use 'gufi packages' instead
|
|
40
48
|
import { logsCommand } from "./commands/logs.js";
|
|
41
|
-
import { companiesCommand, modulesCommand, moduleCommand, moduleUpdateCommand, moduleCreateCommand, companyCreateCommand, automationsCommand, automationCommand, automationCreateCommand, entityAutomationsCommand, entityAutomationsUpdateCommand, } from "./commands/companies.js";
|
|
49
|
+
import { companiesCommand, modulesCommand, moduleCommand, moduleUpdateCommand, moduleCreateCommand, companyCreateCommand, automationsCommand, automationCommand, automationCreateCommand, entityAutomationsCommand, entityAutomationsUpdateCommand, automationsMetaCommand, automationsExecutionsCommand, } from "./commands/companies.js";
|
|
42
50
|
import { rowsListCommand, rowGetCommand, rowCreateCommand, rowUpdateCommand, rowDeleteCommand, rowDuplicateCommand, rowsBulkCreateCommand, } from "./commands/rows.js";
|
|
43
51
|
import { envListCommand, envSetCommand, envDeleteCommand, schemaCommand, } from "./commands/env.js";
|
|
52
|
+
import { packagesCommand, packageCommand, packageCreateCommand, packageDeleteCommand, packageAddModuleCommand, packageRemoveModuleCommand, packagePublishCommand, packageUnpublishCommand, packageSyncCommand, packageCheckCommand,
|
|
53
|
+
// packageViewsCommand removed - use 'gufi package <id>' instead
|
|
54
|
+
packageAddViewCommand, packageRemoveViewCommand, } from "./commands/packages.js";
|
|
44
55
|
const program = new Command();
|
|
45
56
|
program
|
|
46
57
|
.name("gufi")
|
|
@@ -86,13 +97,11 @@ program
|
|
|
86
97
|
.command("module <module_id>")
|
|
87
98
|
.description("Ver/editar JSON de un mΓ³dulo")
|
|
88
99
|
.option("-e, --edit", "Abrir en editor")
|
|
89
|
-
.option("-c, --company <id>", "ID de company")
|
|
90
100
|
.option("-f, --file <path>", "Exportar a archivo")
|
|
91
101
|
.action(moduleCommand);
|
|
92
102
|
program
|
|
93
103
|
.command("module:update <module_id> <json_file>")
|
|
94
104
|
.description("Actualizar mΓ³dulo desde archivo JSON")
|
|
95
|
-
.option("-c, --company <id>", "ID de company")
|
|
96
105
|
.option("--dry-run", "Validar sin guardar")
|
|
97
106
|
.action(moduleUpdateCommand);
|
|
98
107
|
program
|
|
@@ -109,10 +118,9 @@ program
|
|
|
109
118
|
.option("-c, --company <id>", "ID de company")
|
|
110
119
|
.action(automationsCommand);
|
|
111
120
|
program
|
|
112
|
-
.command("automation <
|
|
121
|
+
.command("automation <id>")
|
|
113
122
|
.description("Ver/editar cΓ³digo de automation")
|
|
114
123
|
.option("-e, --edit", "Abrir en editor")
|
|
115
|
-
.option("-c, --company <id>", "ID de company")
|
|
116
124
|
.option("-f, --file <path>", "Exportar a archivo")
|
|
117
125
|
.action(automationCommand);
|
|
118
126
|
program
|
|
@@ -120,6 +128,18 @@ program
|
|
|
120
128
|
.description("Crear/actualizar automation desde archivo JS")
|
|
121
129
|
.option("-c, --company <id>", "ID de company (requerido)")
|
|
122
130
|
.action(automationCreateCommand);
|
|
131
|
+
program
|
|
132
|
+
.command("automations:meta")
|
|
133
|
+
.description("Ver Γndice del worker (debugging)")
|
|
134
|
+
.option("-c, --company <id>", "ID de company")
|
|
135
|
+
.action(automationsMetaCommand);
|
|
136
|
+
program
|
|
137
|
+
.command("automations:executions")
|
|
138
|
+
.description("Ver historial de ejecuciones")
|
|
139
|
+
.option("-c, --company <id>", "ID de company")
|
|
140
|
+
.option("-l, --limit <n>", "Cantidad de registros", "20")
|
|
141
|
+
.option("-s, --script <name>", "Filtrar por script")
|
|
142
|
+
.action(automationsExecutionsCommand);
|
|
123
143
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
124
144
|
// π Entity Automations (automations linked to entities)
|
|
125
145
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -127,13 +147,11 @@ program
|
|
|
127
147
|
.command("entity:automations <entity_id>")
|
|
128
148
|
.description("Ver/editar automations de una entidad")
|
|
129
149
|
.option("-e, --edit", "Abrir en editor")
|
|
130
|
-
.option("-c, --company <id>", "ID de company")
|
|
131
150
|
.option("-f, --file <path>", "Exportar a archivo")
|
|
132
151
|
.action(entityAutomationsCommand);
|
|
133
152
|
program
|
|
134
153
|
.command("entity:automations:update <entity_id> <json_file>")
|
|
135
|
-
.description("Actualizar automations de entidad desde archivo
|
|
136
|
-
.option("-c, --company <id>", "ID de company")
|
|
154
|
+
.description("Actualizar automations de entidad desde archivo")
|
|
137
155
|
.action(entityAutomationsUpdateCommand);
|
|
138
156
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
139
157
|
// π Environment Variables
|
|
@@ -192,30 +210,80 @@ program
|
|
|
192
210
|
.option("-f, --file <path>", "Archivo con array de objetos")
|
|
193
211
|
.action(rowsBulkCreateCommand);
|
|
194
212
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
195
|
-
// π¨
|
|
213
|
+
// π¨ View Development - Desarrollo local de vistas
|
|
196
214
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
197
215
|
program
|
|
198
|
-
.command("
|
|
199
|
-
.description("Ver mis views del Marketplace")
|
|
200
|
-
.action(listCommand);
|
|
201
|
-
program
|
|
202
|
-
.command("view:pull [name]")
|
|
216
|
+
.command("pull [viewId]")
|
|
203
217
|
.description("Descargar vista para editar localmente")
|
|
204
218
|
.action(pullCommand);
|
|
205
219
|
program
|
|
206
|
-
.command("
|
|
220
|
+
.command("push [path]")
|
|
207
221
|
.description("Subir cambios locales a Gufi")
|
|
208
222
|
.action(pushCommand);
|
|
209
223
|
program
|
|
210
|
-
.command("
|
|
224
|
+
.command("watch [path]")
|
|
211
225
|
.description("Auto-sync al guardar archivos")
|
|
212
226
|
.action(watchCommand);
|
|
213
227
|
program
|
|
214
|
-
.command("
|
|
228
|
+
.command("status [path]")
|
|
215
229
|
.description("Ver estado de sincronizaciΓ³n")
|
|
216
230
|
.action(statusCommand);
|
|
217
231
|
program
|
|
218
|
-
.command("
|
|
232
|
+
.command("logs [dir]")
|
|
219
233
|
.description("Ver console.log del LivePreview")
|
|
220
234
|
.action(logsCommand);
|
|
235
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
236
|
+
// π¦ Packages (Marketplace)
|
|
237
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
238
|
+
program
|
|
239
|
+
.command("packages")
|
|
240
|
+
.description("Ver mis packages del Marketplace")
|
|
241
|
+
.action(packagesCommand);
|
|
242
|
+
program
|
|
243
|
+
.command("package <id>")
|
|
244
|
+
.description("Ver detalles de un package")
|
|
245
|
+
.action(packageCommand);
|
|
246
|
+
program
|
|
247
|
+
.command("package:create <name>")
|
|
248
|
+
.description("Crear nuevo package")
|
|
249
|
+
.option("-d, --description <desc>", "DescripciΓ³n del package")
|
|
250
|
+
.action(packageCreateCommand);
|
|
251
|
+
program
|
|
252
|
+
.command("package:delete <id>")
|
|
253
|
+
.description("Eliminar package")
|
|
254
|
+
.action(packageDeleteCommand);
|
|
255
|
+
program
|
|
256
|
+
.command("package:add-module <packageId>")
|
|
257
|
+
.description("AΓ±adir mΓ³dulo a package")
|
|
258
|
+
.option("-c, --company <id>", "ID de company")
|
|
259
|
+
.option("-m, --module <id>", "ID de mΓ³dulo")
|
|
260
|
+
.action(packageAddModuleCommand);
|
|
261
|
+
program
|
|
262
|
+
.command("package:remove-module <packageId> <moduleId>")
|
|
263
|
+
.description("Eliminar mΓ³dulo de package")
|
|
264
|
+
.action(packageRemoveModuleCommand);
|
|
265
|
+
program
|
|
266
|
+
.command("package:publish <id>")
|
|
267
|
+
.description("Publicar package al Marketplace")
|
|
268
|
+
.action(packagePublishCommand);
|
|
269
|
+
program
|
|
270
|
+
.command("package:unpublish <id>")
|
|
271
|
+
.description("Despublicar package")
|
|
272
|
+
.action(packageUnpublishCommand);
|
|
273
|
+
program
|
|
274
|
+
.command("package:sync <id>")
|
|
275
|
+
.description("Sincronizar versiΓ³n del package")
|
|
276
|
+
.action(packageSyncCommand);
|
|
277
|
+
program
|
|
278
|
+
.command("package:check <id>")
|
|
279
|
+
.description("Verificar cambios pendientes")
|
|
280
|
+
.action(packageCheckCommand);
|
|
281
|
+
program
|
|
282
|
+
.command("package:add-view <packageId> <viewId>")
|
|
283
|
+
.description("AΓ±adir view a package")
|
|
284
|
+
.action(packageAddViewCommand);
|
|
285
|
+
program
|
|
286
|
+
.command("package:remove-view <packageId> <packageViewId>")
|
|
287
|
+
.description("Eliminar view de package")
|
|
288
|
+
.action(packageRemoveViewCommand);
|
|
221
289
|
program.parse();
|
package/dist/lib/api.js
CHANGED
|
@@ -119,10 +119,18 @@ export async function listViews(packageId) {
|
|
|
119
119
|
return request(`/api/marketplace/packages/${packageId}/views`);
|
|
120
120
|
}
|
|
121
121
|
export async function getView(viewId) {
|
|
122
|
-
|
|
122
|
+
// π Backend returns { data: View }, unwrap it
|
|
123
|
+
const response = await request(`/api/marketplace/views/${viewId}`);
|
|
124
|
+
return response.data;
|
|
123
125
|
}
|
|
124
126
|
export async function getViewFiles(viewId) {
|
|
125
|
-
|
|
127
|
+
// π Backend returns { data: ViewFile[], total: number }, unwrap it
|
|
128
|
+
const response = await request(`/api/marketplace/views/${viewId}/files`);
|
|
129
|
+
// Handle both formats: { data: [...] } or direct array
|
|
130
|
+
if (Array.isArray(response)) {
|
|
131
|
+
return response;
|
|
132
|
+
}
|
|
133
|
+
return response.data || [];
|
|
126
134
|
}
|
|
127
135
|
export async function saveViewFiles(viewId, files) {
|
|
128
136
|
await request(`/api/marketplace/views/${viewId}/files/bulk`, {
|
package/dist/lib/config.js
CHANGED
|
@@ -56,8 +56,8 @@ export function clearToken() {
|
|
|
56
56
|
const config = loadConfig();
|
|
57
57
|
delete config.token;
|
|
58
58
|
delete config.refreshToken;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// π Keep email and password for auto-login next time
|
|
60
|
+
// Only clear them if user explicitly wants to (not implemented yet)
|
|
61
61
|
saveConfig(config);
|
|
62
62
|
}
|
|
63
63
|
export function isLoggedIn() {
|