gufi-cli 0.1.13 β 0.1.16
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
|
@@ -85,6 +85,190 @@ async function apiRequest(path, options = {}, retry = true) {
|
|
|
85
85
|
}
|
|
86
86
|
return res.json();
|
|
87
87
|
}
|
|
88
|
+
// π Cache for automation name β company mapping
|
|
89
|
+
const automationCompanyCache = new Map();
|
|
90
|
+
// π Cache for module ID β company mapping
|
|
91
|
+
const moduleCompanyCache = new Map();
|
|
92
|
+
// π Cache for entity ID β company mapping
|
|
93
|
+
const entityCompanyCache = new Map();
|
|
94
|
+
// π Detect company from entity ID (searches all user's companies)
|
|
95
|
+
async function detectCompanyFromEntity(entityId) {
|
|
96
|
+
const searchId = parseInt(entityId, 10);
|
|
97
|
+
// Must be a valid numeric ID
|
|
98
|
+
if (isNaN(searchId)) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
// Check cache first
|
|
102
|
+
if (entityCompanyCache.has(entityId)) {
|
|
103
|
+
const companyId = entityCompanyCache.get(entityId);
|
|
104
|
+
try {
|
|
105
|
+
const data = await apiRequest("/api/company/schema", {
|
|
106
|
+
headers: { "X-Company-ID": companyId },
|
|
107
|
+
});
|
|
108
|
+
const modules = data.modules || data.data?.modules || [];
|
|
109
|
+
for (const mod of modules) {
|
|
110
|
+
for (const sub of mod.submodules || []) {
|
|
111
|
+
for (const ent of sub.entities || []) {
|
|
112
|
+
if (ent.id === searchId) {
|
|
113
|
+
return { companyId, entity: ent };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch { }
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
// Get all companies the user has access to
|
|
123
|
+
const companiesData = await apiRequest("/api/companies");
|
|
124
|
+
const companies = companiesData.items || companiesData.data || companiesData || [];
|
|
125
|
+
// Search through each company's schema for the entity
|
|
126
|
+
for (const company of companies) {
|
|
127
|
+
try {
|
|
128
|
+
const data = await apiRequest("/api/company/schema", {
|
|
129
|
+
headers: { "X-Company-ID": String(company.id) },
|
|
130
|
+
});
|
|
131
|
+
const modules = data.modules || data.data?.modules || [];
|
|
132
|
+
// Search by entity ID
|
|
133
|
+
for (const mod of modules) {
|
|
134
|
+
for (const sub of mod.submodules || []) {
|
|
135
|
+
for (const ent of sub.entities || []) {
|
|
136
|
+
if (ent.id === searchId) {
|
|
137
|
+
// Found! Cache it
|
|
138
|
+
entityCompanyCache.set(entityId, String(company.id));
|
|
139
|
+
return { companyId: String(company.id), entity: ent };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Skip companies we can't access
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
// π Detect company from module ID (searches all user's companies)
|
|
157
|
+
async function detectCompanyFromModule(moduleId) {
|
|
158
|
+
const searchId = parseInt(moduleId, 10);
|
|
159
|
+
// Must be a valid numeric ID
|
|
160
|
+
if (isNaN(searchId)) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
// Check cache first
|
|
164
|
+
if (moduleCompanyCache.has(moduleId)) {
|
|
165
|
+
const companyId = moduleCompanyCache.get(moduleId);
|
|
166
|
+
try {
|
|
167
|
+
const data = await apiRequest("/api/company/schema", {
|
|
168
|
+
headers: { "X-Company-ID": companyId },
|
|
169
|
+
});
|
|
170
|
+
const modules = data.modules || data.data?.modules || [];
|
|
171
|
+
for (const mod of modules) {
|
|
172
|
+
for (const sub of mod.submodules || []) {
|
|
173
|
+
for (const ent of sub.entities || []) {
|
|
174
|
+
if (ent.ui?.moduleId === searchId) {
|
|
175
|
+
mod._moduleId = searchId;
|
|
176
|
+
return { companyId, module: mod };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch { }
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
// Get all companies the user has access to
|
|
186
|
+
const companiesData = await apiRequest("/api/companies");
|
|
187
|
+
const companies = companiesData.items || companiesData.data || companiesData || [];
|
|
188
|
+
// Search through each company for the module
|
|
189
|
+
for (const company of companies) {
|
|
190
|
+
try {
|
|
191
|
+
const data = await apiRequest("/api/company/schema", {
|
|
192
|
+
headers: { "X-Company-ID": String(company.id) },
|
|
193
|
+
});
|
|
194
|
+
const modules = data.modules || data.data?.modules || [];
|
|
195
|
+
// Search by moduleId in entities
|
|
196
|
+
for (const mod of modules) {
|
|
197
|
+
for (const sub of mod.submodules || []) {
|
|
198
|
+
for (const ent of sub.entities || []) {
|
|
199
|
+
if (ent.ui?.moduleId === searchId) {
|
|
200
|
+
// Found! Cache it
|
|
201
|
+
moduleCompanyCache.set(moduleId, String(company.id));
|
|
202
|
+
mod._moduleId = searchId;
|
|
203
|
+
return { companyId: String(company.id), module: mod };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Skip companies we can't access
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
// π Detect company from automation ID (searches all user's companies)
|
|
221
|
+
// Only searches by ID to avoid ambiguity with duplicate names
|
|
222
|
+
async function detectCompanyFromAutomation(automationId) {
|
|
223
|
+
const searchId = parseInt(automationId, 10);
|
|
224
|
+
// Must be a valid numeric ID
|
|
225
|
+
if (isNaN(searchId)) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
// Check cache first
|
|
229
|
+
if (automationCompanyCache.has(automationId)) {
|
|
230
|
+
const companyId = automationCompanyCache.get(automationId);
|
|
231
|
+
try {
|
|
232
|
+
const data = await apiRequest("/api/automation-scripts", {
|
|
233
|
+
headers: { "X-Company-ID": companyId },
|
|
234
|
+
});
|
|
235
|
+
const automations = Array.isArray(data) ? data : data.data || [];
|
|
236
|
+
const automation = automations.find((a) => a.id === searchId);
|
|
237
|
+
if (automation)
|
|
238
|
+
return { companyId, automation };
|
|
239
|
+
}
|
|
240
|
+
catch { }
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
// Get all companies the user has access to
|
|
244
|
+
const companiesData = await apiRequest("/api/companies");
|
|
245
|
+
const companies = companiesData.items || companiesData.data || companiesData || [];
|
|
246
|
+
// Search through each company for the automation by ID
|
|
247
|
+
for (const company of companies) {
|
|
248
|
+
try {
|
|
249
|
+
const data = await apiRequest("/api/automation-scripts", {
|
|
250
|
+
headers: { "X-Company-ID": String(company.id) },
|
|
251
|
+
});
|
|
252
|
+
const automations = Array.isArray(data) ? data : data.data || [];
|
|
253
|
+
// π Search by ID only
|
|
254
|
+
const automation = automations.find((a) => a.id === searchId);
|
|
255
|
+
if (automation) {
|
|
256
|
+
// Found! Cache by ID
|
|
257
|
+
automationCompanyCache.set(String(automation.id), String(company.id));
|
|
258
|
+
return { companyId: String(company.id), automation };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Skip companies we can't access
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
88
272
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
89
273
|
// gufi companies - List user's companies
|
|
90
274
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -157,7 +341,7 @@ export async function modulesCommand(companyId) {
|
|
|
157
341
|
const label = (mod.displayName || mod.label || mod.name || "").substring(0, 28).padEnd(28);
|
|
158
342
|
console.log(` ${chalk.cyan(id)}\t${label}\t${entityCount} entities`);
|
|
159
343
|
}
|
|
160
|
-
console.log(chalk.gray("\n π‘ Usa: gufi module <module_id>
|
|
344
|
+
console.log(chalk.gray("\n π‘ Usa: gufi module <module_id> para ver/editar\n"));
|
|
161
345
|
}
|
|
162
346
|
catch (err) {
|
|
163
347
|
console.log(chalk.red(`\n β Error: ${err.message}\n`));
|
|
@@ -204,6 +388,7 @@ async function getModuleFromSchema(moduleId, companyId) {
|
|
|
204
388
|
}
|
|
205
389
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
206
390
|
// gufi module <module_id> [--edit] [--company <id>] - View/edit module JSON
|
|
391
|
+
// π Auto-detects company if not provided (searches by module ID)
|
|
207
392
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
208
393
|
export async function moduleCommand(moduleId, options) {
|
|
209
394
|
if (!isLoggedIn()) {
|
|
@@ -211,14 +396,26 @@ export async function moduleCommand(moduleId, options) {
|
|
|
211
396
|
process.exit(1);
|
|
212
397
|
}
|
|
213
398
|
if (!moduleId) {
|
|
214
|
-
console.log(chalk.red("\n β Uso: gufi module <module_id> [--edit]
|
|
399
|
+
console.log(chalk.red("\n β Uso: gufi module <module_id> [--edit]\n"));
|
|
215
400
|
process.exit(1);
|
|
216
401
|
}
|
|
217
|
-
const companyId = options?.company;
|
|
218
402
|
console.log(chalk.magenta(`\n π£ MΓ³dulo ${moduleId}\n`));
|
|
403
|
+
let companyId;
|
|
404
|
+
let module;
|
|
219
405
|
try {
|
|
220
|
-
//
|
|
221
|
-
|
|
406
|
+
// π Auto-detect company
|
|
407
|
+
console.log(chalk.gray(" Buscando en todas las companies..."));
|
|
408
|
+
const result = await detectCompanyFromModule(moduleId);
|
|
409
|
+
if (result) {
|
|
410
|
+
module = result.module;
|
|
411
|
+
companyId = result.companyId;
|
|
412
|
+
console.log(chalk.gray(` [gufi] Auto-detected company: ${companyId}\n`));
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
console.log(chalk.red(` β MΓ³dulo ${moduleId} no encontrado en ninguna company\n`));
|
|
416
|
+
console.log(chalk.gray(" π‘ Usa: gufi modules <company_id> para ver IDs de mΓ³dulos\n"));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
222
419
|
const actualModuleId = module._moduleId || moduleId;
|
|
223
420
|
// Show module info
|
|
224
421
|
console.log(chalk.white(` ID: ${actualModuleId}`));
|
|
@@ -353,7 +550,7 @@ export async function moduleUpdateCommand(moduleId, jsonFile, options) {
|
|
|
353
550
|
process.exit(1);
|
|
354
551
|
}
|
|
355
552
|
if (!moduleId || !jsonFile) {
|
|
356
|
-
console.log(chalk.red("\n β Uso: gufi module:update <module_id> <json_file> [--
|
|
553
|
+
console.log(chalk.red("\n β Uso: gufi module:update <module_id> <json_file> [--dry-run]\n"));
|
|
357
554
|
process.exit(1);
|
|
358
555
|
}
|
|
359
556
|
const fs = await import("fs");
|
|
@@ -372,10 +569,18 @@ export async function moduleUpdateCommand(moduleId, jsonFile, options) {
|
|
|
372
569
|
console.log(chalk.yellow(" [DRY RUN] Solo validando, no se guardarΓ‘n cambios.\n"));
|
|
373
570
|
}
|
|
374
571
|
try {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
572
|
+
// π Auto-detect company
|
|
573
|
+
console.log(chalk.gray(" Detectando company..."));
|
|
574
|
+
const detected = await detectCompanyFromModule(moduleId);
|
|
575
|
+
if (!detected) {
|
|
576
|
+
console.log(chalk.red(" β MΓ³dulo no encontrado\n"));
|
|
577
|
+
process.exit(1);
|
|
378
578
|
}
|
|
579
|
+
const companyId = detected.companyId;
|
|
580
|
+
console.log(chalk.gray(` Company ${companyId} (auto-detected)\n`));
|
|
581
|
+
const headers = {
|
|
582
|
+
"X-Company-ID": companyId,
|
|
583
|
+
};
|
|
379
584
|
// Validate JSON structure locally
|
|
380
585
|
console.log(chalk.gray(" Validando JSON..."));
|
|
381
586
|
if (!newJson.name && !newJson.displayName) {
|
|
@@ -562,50 +767,58 @@ options) {
|
|
|
562
767
|
const desc = (auto.description || "-").substring(0, 30);
|
|
563
768
|
console.log(` ${chalk.cyan(id)}\t${name}\t${desc}`);
|
|
564
769
|
}
|
|
565
|
-
console.log(chalk.gray("\n π‘ Usa: gufi automation <
|
|
770
|
+
console.log(chalk.gray("\n π‘ Usa: gufi automation <id> para ver/editar el cΓ³digo\n"));
|
|
566
771
|
}
|
|
567
772
|
catch (err) {
|
|
568
773
|
console.log(chalk.red(`\n β Error: ${err.message}\n`));
|
|
569
774
|
}
|
|
570
775
|
}
|
|
571
776
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
572
|
-
// gufi automation <
|
|
777
|
+
// gufi automation <id> [--edit] - View/edit automation code by ID
|
|
778
|
+
// π Auto-detects company if not provided (searches by ID only)
|
|
573
779
|
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
574
|
-
export async function automationCommand(
|
|
780
|
+
export async function automationCommand(automationId, options) {
|
|
575
781
|
if (!isLoggedIn()) {
|
|
576
782
|
console.log(chalk.red("\n β No estΓ‘s logueado. Usa: gufi login\n"));
|
|
577
783
|
process.exit(1);
|
|
578
784
|
}
|
|
579
|
-
if (!
|
|
580
|
-
console.log(chalk.red("\n β Uso: gufi automation <
|
|
581
|
-
console.log(chalk.gray(" Tip: Usa 'gufi automations' para ver
|
|
785
|
+
if (!automationId) {
|
|
786
|
+
console.log(chalk.red("\n β Uso: gufi automation <id> [--edit]\n"));
|
|
787
|
+
console.log(chalk.gray(" Tip: Usa 'gufi automations' para ver IDs\n"));
|
|
788
|
+
process.exit(1);
|
|
789
|
+
}
|
|
790
|
+
// π Validate that it's a numeric ID
|
|
791
|
+
const isNumericId = /^\d+$/.test(automationId);
|
|
792
|
+
if (!isNumericId && !options?.company) {
|
|
793
|
+
console.log(chalk.red(`\n β Usa el ID numΓ©rico, no el nombre\n`));
|
|
794
|
+
console.log(chalk.gray(" Ejemplo: gufi automation 15"));
|
|
795
|
+
console.log(chalk.gray(" Tip: Usa 'gufi automations' para ver IDs\n"));
|
|
582
796
|
process.exit(1);
|
|
583
797
|
}
|
|
584
|
-
console.log(chalk.magenta(`\n π£ Automation: ${
|
|
798
|
+
console.log(chalk.magenta(`\n π£ Automation: ${automationId}\n`));
|
|
585
799
|
try {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
const automations = Array.isArray(data) ? data : data.data || [];
|
|
593
|
-
const automation = automations.find((a) => a.name === automationName || String(a.id) === automationName);
|
|
594
|
-
if (!automation) {
|
|
595
|
-
console.log(chalk.red(` β Automation "${automationName}" no encontrada\n`));
|
|
596
|
-
console.log(chalk.gray(" π‘ Usa: gufi automations para ver la lista\n"));
|
|
800
|
+
// π Auto-detect company
|
|
801
|
+
console.log(chalk.gray(" Buscando en todas las companies..."));
|
|
802
|
+
const result = await detectCompanyFromAutomation(automationId);
|
|
803
|
+
if (!result) {
|
|
804
|
+
console.log(chalk.red(` β Automation ID ${automationId} no encontrada\n`));
|
|
805
|
+
console.log(chalk.gray(" π‘ Usa: gufi automations -c <company> para ver IDs\n"));
|
|
597
806
|
return;
|
|
598
807
|
}
|
|
808
|
+
const automation = result.automation;
|
|
809
|
+
const companyId = result.companyId;
|
|
810
|
+
console.log(chalk.gray(` [gufi] Auto-detected company: ${companyId}\n`));
|
|
599
811
|
// Show info
|
|
600
812
|
console.log(chalk.white(` Nombre: ${automation.name}`));
|
|
601
813
|
console.log(chalk.white(` ID: ${automation.id}`));
|
|
814
|
+
console.log(chalk.white(` Company: ${companyId}`));
|
|
602
815
|
if (automation.description) {
|
|
603
816
|
console.log(chalk.white(` DescripciΓ³n: ${automation.description}`));
|
|
604
817
|
}
|
|
605
818
|
console.log();
|
|
606
819
|
const jsCode = automation.code || "";
|
|
607
820
|
if (options?.edit) {
|
|
608
|
-
await editAutomationCode(automation.name, jsCode,
|
|
821
|
+
await editAutomationCode(automation.name, jsCode, companyId);
|
|
609
822
|
}
|
|
610
823
|
else if (options?.file) {
|
|
611
824
|
const fs = await import("fs");
|
|
@@ -616,7 +829,7 @@ export async function automationCommand(automationName, options) {
|
|
|
616
829
|
console.log(chalk.gray(" CΓ³digo JavaScript:"));
|
|
617
830
|
console.log(chalk.gray(" β".repeat(30)));
|
|
618
831
|
console.log(jsCode || "(vacΓo)");
|
|
619
|
-
console.log(chalk.gray("\n π‘ Usa: gufi automation <
|
|
832
|
+
console.log(chalk.gray("\n π‘ Usa: gufi automation <id> --edit para editar\n"));
|
|
620
833
|
}
|
|
621
834
|
}
|
|
622
835
|
catch (err) {
|
|
@@ -662,7 +875,7 @@ export async function automationCreateCommand(name, jsFile, options) {
|
|
|
662
875
|
console.log(chalk.green("\n β Automation creada!\n"));
|
|
663
876
|
console.log(chalk.white(` Nombre: ${result.name || name}`));
|
|
664
877
|
console.log(chalk.white(` AcciΓ³n: ${result.action || "created/updated"}`));
|
|
665
|
-
console.log(chalk.gray("\n π‘ Usa: gufi automations
|
|
878
|
+
console.log(chalk.gray("\n π‘ Usa: gufi automations para ver la lista\n"));
|
|
666
879
|
}
|
|
667
880
|
catch (err) {
|
|
668
881
|
console.log(chalk.red(`\n β Error: ${err.message}\n`));
|
|
@@ -721,16 +934,24 @@ export async function entityAutomationsCommand(entityId, options) {
|
|
|
721
934
|
process.exit(1);
|
|
722
935
|
}
|
|
723
936
|
if (!entityId) {
|
|
724
|
-
console.log(chalk.red("\n β Uso: gufi entity:automations <entityId> [--edit]
|
|
937
|
+
console.log(chalk.red("\n β Uso: gufi entity:automations <entityId> [--edit]\n"));
|
|
725
938
|
console.log(chalk.gray(" Tip: El entityId lo encuentras en el schema o en la URL de la tabla\n"));
|
|
726
939
|
process.exit(1);
|
|
727
940
|
}
|
|
728
941
|
console.log(chalk.magenta(`\n π£ Automations de Entity ${entityId}\n`));
|
|
729
942
|
try {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
943
|
+
// π Auto-detect company
|
|
944
|
+
console.log(chalk.gray(" Detectando company..."));
|
|
945
|
+
const result = await detectCompanyFromEntity(entityId);
|
|
946
|
+
if (!result) {
|
|
947
|
+
console.log(chalk.red(" β Entity no encontrada\n"));
|
|
948
|
+
process.exit(1);
|
|
733
949
|
}
|
|
950
|
+
const companyId = result.companyId;
|
|
951
|
+
console.log(chalk.gray(` Company ${companyId} (auto-detected)\n`));
|
|
952
|
+
const headers = {
|
|
953
|
+
"X-Company-ID": companyId,
|
|
954
|
+
};
|
|
734
955
|
const data = await apiRequest(`/api/entities/${entityId}/automations`, { headers });
|
|
735
956
|
const automations = data.automations || [];
|
|
736
957
|
const availableScripts = data.availableScripts || [];
|
|
@@ -753,7 +974,7 @@ export async function entityAutomationsCommand(entityId, options) {
|
|
|
753
974
|
}
|
|
754
975
|
}
|
|
755
976
|
if (options?.edit) {
|
|
756
|
-
await editEntityAutomations(entityId, automations, availableScripts,
|
|
977
|
+
await editEntityAutomations(entityId, automations, availableScripts, companyId);
|
|
757
978
|
}
|
|
758
979
|
else if (options?.file) {
|
|
759
980
|
const fs = await import("fs");
|
|
@@ -788,7 +1009,7 @@ export async function entityAutomationsUpdateCommand(entityId, jsonFile, options
|
|
|
788
1009
|
process.exit(1);
|
|
789
1010
|
}
|
|
790
1011
|
if (!entityId || !jsonFile) {
|
|
791
|
-
console.log(chalk.red("\n β Uso: gufi entity:automations:update <entityId> <json_file
|
|
1012
|
+
console.log(chalk.red("\n β Uso: gufi entity:automations:update <entityId> <json_file>\n"));
|
|
792
1013
|
process.exit(1);
|
|
793
1014
|
}
|
|
794
1015
|
const fs = await import("fs");
|
|
@@ -808,10 +1029,18 @@ export async function entityAutomationsUpdateCommand(entityId, jsonFile, options
|
|
|
808
1029
|
console.log(chalk.gray(` Archivo: ${jsonFile}`));
|
|
809
1030
|
console.log(chalk.gray(` Automations: ${automations.length}`));
|
|
810
1031
|
try {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
1032
|
+
// π Auto-detect company
|
|
1033
|
+
console.log(chalk.gray(" Detectando company..."));
|
|
1034
|
+
const detected = await detectCompanyFromEntity(entityId);
|
|
1035
|
+
if (!detected) {
|
|
1036
|
+
console.log(chalk.red(" β Entity no encontrada\n"));
|
|
1037
|
+
process.exit(1);
|
|
814
1038
|
}
|
|
1039
|
+
const companyId = detected.companyId;
|
|
1040
|
+
console.log(chalk.gray(` Company ${companyId} (auto-detected)\n`));
|
|
1041
|
+
const headers = {
|
|
1042
|
+
"X-Company-ID": companyId,
|
|
1043
|
+
};
|
|
815
1044
|
const result = await apiRequest(`/api/entities/${entityId}/automations`, {
|
|
816
1045
|
method: "PUT",
|
|
817
1046
|
headers,
|
|
@@ -830,6 +1059,92 @@ export async function entityAutomationsUpdateCommand(entityId, jsonFile, options
|
|
|
830
1059
|
/**
|
|
831
1060
|
* Interactive editor for entity automations
|
|
832
1061
|
*/
|
|
1062
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1063
|
+
// gufi automations:meta - View automation_meta index (debugging)
|
|
1064
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1065
|
+
export async function automationsMetaCommand(options) {
|
|
1066
|
+
if (!isLoggedIn()) {
|
|
1067
|
+
console.log(chalk.red("\n β No estΓ‘s logueado. Usa: gufi login\n"));
|
|
1068
|
+
process.exit(1);
|
|
1069
|
+
}
|
|
1070
|
+
console.log(chalk.magenta("\n π£ Automation Meta (Worker Index)\n"));
|
|
1071
|
+
console.log(chalk.gray(" π‘ Esta tabla se sincroniza automΓ‘ticamente desde entities.automations\n"));
|
|
1072
|
+
try {
|
|
1073
|
+
const headers = {};
|
|
1074
|
+
if (options?.company) {
|
|
1075
|
+
headers["X-Company-ID"] = options.company;
|
|
1076
|
+
}
|
|
1077
|
+
const data = await apiRequest("/api/automation-meta", { headers });
|
|
1078
|
+
const metas = Array.isArray(data) ? data : data.data || [];
|
|
1079
|
+
if (!metas.length) {
|
|
1080
|
+
console.log(chalk.gray(" Sin automations indexadas en esta company.\n"));
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
console.log(chalk.gray(" Entity\t\tTrigger\t\tScript\t\t\tEstado"));
|
|
1084
|
+
console.log(chalk.gray(" β".repeat(50)));
|
|
1085
|
+
for (const meta of metas) {
|
|
1086
|
+
const entity = String(meta.entity_id).padEnd(8);
|
|
1087
|
+
const trigger = (meta.trigger || "").padEnd(12);
|
|
1088
|
+
const script = (meta.function_name || "").substring(0, 24).padEnd(24);
|
|
1089
|
+
const status = meta.enabled !== false ? chalk.green("β") : chalk.gray("β");
|
|
1090
|
+
console.log(` ${chalk.cyan(entity)}\t${trigger}\t${script}\t${status}`);
|
|
1091
|
+
}
|
|
1092
|
+
console.log(chalk.gray(`\n Total: ${metas.length} automations indexadas`));
|
|
1093
|
+
console.log(chalk.gray(" π‘ Usa: gufi entity:automations <entityId> para editar triggers\n"));
|
|
1094
|
+
}
|
|
1095
|
+
catch (err) {
|
|
1096
|
+
console.log(chalk.red(`\n β Error: ${err.message}\n`));
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1100
|
+
// gufi automations:executions - View automation execution history
|
|
1101
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1102
|
+
export async function automationsExecutionsCommand(options) {
|
|
1103
|
+
if (!isLoggedIn()) {
|
|
1104
|
+
console.log(chalk.red("\n β No estΓ‘s logueado. Usa: gufi login\n"));
|
|
1105
|
+
process.exit(1);
|
|
1106
|
+
}
|
|
1107
|
+
console.log(chalk.magenta("\n π£ Automation Executions (Historial)\n"));
|
|
1108
|
+
try {
|
|
1109
|
+
const headers = {};
|
|
1110
|
+
if (options?.company) {
|
|
1111
|
+
headers["X-Company-ID"] = options.company;
|
|
1112
|
+
}
|
|
1113
|
+
const limit = options?.limit || "20";
|
|
1114
|
+
let url = `/api/automation-executions?limit=${limit}`;
|
|
1115
|
+
if (options?.script) {
|
|
1116
|
+
url += `&script=${encodeURIComponent(options.script)}`;
|
|
1117
|
+
}
|
|
1118
|
+
const data = await apiRequest(url, { headers });
|
|
1119
|
+
const executions = Array.isArray(data) ? data : data.data || [];
|
|
1120
|
+
if (!executions.length) {
|
|
1121
|
+
console.log(chalk.gray(" Sin ejecuciones recientes.\n"));
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
console.log(chalk.gray(" Fecha\t\t\t\tScript\t\t\t\tEstado\tDuraciΓ³n"));
|
|
1125
|
+
console.log(chalk.gray(" β".repeat(55)));
|
|
1126
|
+
for (const exec of executions) {
|
|
1127
|
+
const date = exec.created_at
|
|
1128
|
+
? new Date(exec.created_at).toLocaleString("es-ES", {
|
|
1129
|
+
day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit"
|
|
1130
|
+
})
|
|
1131
|
+
: "-";
|
|
1132
|
+
const script = (exec.function_name || exec.script_name || "").substring(0, 28).padEnd(28);
|
|
1133
|
+
const status = exec.status === "success" || exec.success
|
|
1134
|
+
? chalk.green("β ok")
|
|
1135
|
+
: exec.status === "error" || exec.error
|
|
1136
|
+
? chalk.red("β error")
|
|
1137
|
+
: chalk.yellow("β³");
|
|
1138
|
+
const duration = exec.duration_ms ? `${exec.duration_ms}ms` : "-";
|
|
1139
|
+
console.log(` ${date.padEnd(16)}\t${script}\t${status}\t${duration}`);
|
|
1140
|
+
}
|
|
1141
|
+
console.log(chalk.gray(`\n Mostrando ΓΊltimas ${executions.length} ejecuciones`));
|
|
1142
|
+
console.log(chalk.gray(" π‘ Usa: gufi automations:executions --limit 50 para ver mΓ‘s\n"));
|
|
1143
|
+
}
|
|
1144
|
+
catch (err) {
|
|
1145
|
+
console.log(chalk.red(`\n β Error: ${err.message}\n`));
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
833
1148
|
async function editEntityAutomations(entityId, currentAutomations, availableScripts, companyId) {
|
|
834
1149
|
const fs = await import("fs");
|
|
835
1150
|
const os = await import("os");
|
|
@@ -839,7 +1154,7 @@ async function editEntityAutomations(entityId, currentAutomations, availableScri
|
|
|
839
1154
|
const helpContent = {
|
|
840
1155
|
_help: [
|
|
841
1156
|
"Edita este array de automations y guarda el archivo.",
|
|
842
|
-
"Triggers:
|
|
1157
|
+
"Triggers: insert, update, delete, click, scheduled",
|
|
843
1158
|
"function_name: nombre del script en automation_scripts",
|
|
844
1159
|
"enabled: true/false para activar/pausar",
|
|
845
1160
|
"cron_pattern: solo para scheduled (ej: '0 9 * * *')",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gufi packages - List and manage marketplace packages
|
|
3
|
+
* gufi package <id> - View package details
|
|
4
|
+
* gufi package:create <name> - Create new package
|
|
5
|
+
* gufi package:add-module <packageId> - Add module to package
|
|
6
|
+
* gufi package:publish <id> - Publish package
|
|
7
|
+
*/
|
|
8
|
+
export declare function packagesCommand(): Promise<void>;
|
|
9
|
+
export declare function packageCommand(packageId?: string): Promise<void>;
|
|
10
|
+
export declare function packageCreateCommand(name?: string, options?: {
|
|
11
|
+
description?: string;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
export declare function packageDeleteCommand(packageId?: string): Promise<void>;
|
|
14
|
+
export declare function packageAddModuleCommand(packageId?: string, options?: {
|
|
15
|
+
company?: string;
|
|
16
|
+
module?: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function packageRemoveModuleCommand(packageId?: string, moduleId?: string): Promise<void>;
|
|
19
|
+
export declare function packagePublishCommand(packageId?: string): Promise<void>;
|
|
20
|
+
export declare function packageUnpublishCommand(packageId?: string): Promise<void>;
|
|
21
|
+
export declare function packageSyncCommand(packageId?: string): Promise<void>;
|
|
22
|
+
export declare function packageCheckCommand(packageId?: string): Promise<void>;
|
|
23
|
+
export declare function packageViewsCommand(packageId?: string): Promise<void>;
|
|
24
|
+
export declare function packageAddViewCommand(packageId?: string, viewId?: string): Promise<void>;
|
|
25
|
+
export declare function packageRemoveViewCommand(packageId?: string, packageViewId?: string): Promise<void>;
|