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.
@@ -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> -c " + companyId + " para ver/editar\n"));
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] [--company <id>]\n"));
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
- // Get module from company schema
221
- const module = await getModuleFromSchema(moduleId, companyId);
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> [--company <id>] [--dry-run]\n"));
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
- const headers = {};
376
- if (options?.company) {
377
- headers["X-Company-ID"] = options.company;
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 <nombre> para ver/editar el cΓ³digo\n"));
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 <name> [--edit] - View/edit automation code by name
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(automationName, options) {
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 (!automationName) {
580
- console.log(chalk.red("\n βœ— Uso: gufi automation <nombre> [--edit] [--company <id>]\n"));
581
- console.log(chalk.gray(" Tip: Usa 'gufi automations' para ver la lista\n"));
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: ${automationName}\n`));
798
+ console.log(chalk.magenta(`\n 🟣 Automation: ${automationId}\n`));
585
799
  try {
586
- const headers = {};
587
- if (options?.company) {
588
- headers["X-Company-ID"] = options.company;
589
- }
590
- // Get all scripts and find by name
591
- const data = await apiRequest("/api/automation-scripts", { headers });
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, options.company);
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 <nombre> --edit para editar\n"));
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 -c " + options.company + " para ver la lista\n"));
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] [--company <id>]\n"));
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
- const headers = {};
731
- if (options?.company) {
732
- headers["X-Company-ID"] = options.company;
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, options.company);
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> [--company <id>]\n"));
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
- const headers = {};
812
- if (options?.company) {
813
- headers["X-Company-ID"] = options.company;
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: on_insert, on_update, on_delete, on_click, scheduled",
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>;