@v1ct0rbr/minivault-web 0.8.0 → 0.9.0

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.
@@ -1,4 +1,4 @@
1
- import { AllStorageConfig, Backup, BackupType, ConnectionCheck, DatabaseCredentials, DbInfo, DumpOptions, ImportResult, OriginStorageConfig, PageResponse, RelationshipInfo, StorageFileItem, StorageTarget, StorageZipRequest, TableDetail, TableInfo, VerifyResult, ZipJobStatus } from '../types/minivault';
1
+ import { AllStorageConfig, Backup, BackupType, ConnectionCheck, DatabaseCredentials, DbInfo, DumpOptions, ImportResult, OriginStorageConfig, PageResponse, RelationshipInfo, RestoreStorageRequest, StorageFileItem, StorageRestoreResult, StorageTarget, StorageZipRequest, TableDetail, TableInfo, VerifyResult, ZipJobStatus } from '../types/minivault';
2
2
  export interface MinivaultApiOptions {
3
3
  /**
4
4
  * URL base da API. Exemplos:
@@ -36,6 +36,8 @@ export declare class MinivaultApi {
36
36
  createBackup(database?: DatabaseCredentials, originStorage?: OriginStorageConfig, dumpOptions?: DumpOptions, backupType?: BackupType, scheduled?: boolean): Promise<Backup>;
37
37
  restoreBackup(id: number, database?: DatabaseCredentials, originStorage?: OriginStorageConfig): Promise<void>;
38
38
  deleteBackup(id: number): Promise<void>;
39
+ /** Liga/desliga a re-execução deste backup no agendamento (scheduler noturno). */
40
+ updateBackupScheduled(id: number, scheduled: boolean): Promise<Backup>;
39
41
  verifyBackup(id: number): Promise<VerifyResult>;
40
42
  downloadBackup(id: number): Promise<Blob>;
41
43
  importDump(file: File, database?: DatabaseCredentials): Promise<ImportResult>;
@@ -50,6 +52,8 @@ export declare class MinivaultApi {
50
52
  listStorageFiles(type: string, prefix?: string, storageConfig?: OriginStorageConfig, storage?: StorageTarget): Promise<StorageFileItem[]>;
51
53
  downloadStorageFile(key: string, type: string, storageConfig?: OriginStorageConfig, storage?: StorageTarget): Promise<Blob>;
52
54
  deleteStorageFile(key: string, type: string, storageConfig?: OriginStorageConfig, storage?: StorageTarget): Promise<void>;
55
+ /** Restaura itens do storage (destino) de volta para o storage de origem. */
56
+ restoreStorageItems(request: RestoreStorageRequest): Promise<StorageRestoreResult>;
53
57
  createStorageZip(request: StorageZipRequest): Promise<ZipJobStatus>;
54
58
  getStorageZipStatus(jobId: string): Promise<ZipJobStatus>;
55
59
  downloadStorageZip(jobId: string): Promise<Blob>;
@@ -24,6 +24,10 @@ export declare function useRestoreBackup(): import('@tanstack/react-query').UseM
24
24
  }, unknown>;
25
25
  export declare function useDeleteBackup(): import('@tanstack/react-query').UseMutationResult<void, Error, number, unknown>;
26
26
  export declare function useVerifyBackup(): import('@tanstack/react-query').UseMutationResult<import('../types/minivault').VerifyResult, Error, number, unknown>;
27
+ export declare function useUpdateBackupScheduled(): import('@tanstack/react-query').UseMutationResult<import('../types/minivault').Backup, Error, {
28
+ id: number;
29
+ scheduled: boolean;
30
+ }, unknown>;
27
31
  export declare function useDownloadBackup(): import('@tanstack/react-query').UseMutationResult<Blob, Error, {
28
32
  id: number;
29
33
  filename: string;
@@ -73,6 +73,12 @@ var h = class extends Error {
73
73
  deleteBackup(e) {
74
74
  return this.request(`/api/backups/${e}`, { method: "DELETE" });
75
75
  }
76
+ updateBackupScheduled(e, t) {
77
+ return this.request(`/api/backups/${e}/schedule`, {
78
+ method: "PATCH",
79
+ body: JSON.stringify({ scheduled: t })
80
+ });
81
+ }
76
82
  verifyBackup(e) {
77
83
  return this.request(`/api/backups/${e}/verify`, { method: "POST" });
78
84
  }
@@ -171,6 +177,12 @@ var h = class extends Error {
171
177
  let i = this.storageQuery(r, n);
172
178
  i.set("key", e), i.set("type", t), await this.request(`/api/storage/files?${i.toString()}`, { method: "DELETE" });
173
179
  }
180
+ restoreStorageItems(e) {
181
+ return this.request("/api/storage/restore", {
182
+ method: "POST",
183
+ body: JSON.stringify(e)
184
+ });
185
+ }
174
186
  createStorageZip(e) {
175
187
  return this.request("/api/storage/download/zip", {
176
188
  method: "POST",
@@ -324,45 +336,52 @@ function P() {
324
336
  });
325
337
  }
326
338
  function F() {
339
+ let e = b(), t = d();
340
+ return l({
341
+ mutationFn: (t) => e.updateBackupScheduled(t.id, t.scheduled),
342
+ onSuccess: () => t.invalidateQueries({ queryKey: S.all })
343
+ });
344
+ }
345
+ function I() {
327
346
  let e = b();
328
347
  return l({ mutationFn: (t) => e.downloadBackup(t.id) });
329
348
  }
330
- function I() {
349
+ function L() {
331
350
  let e = b();
332
351
  return l({ mutationFn: (t) => e.importDump(t.file, t.database) });
333
352
  }
334
- function L() {
353
+ function R() {
335
354
  let e = b();
336
355
  return l({ mutationFn: (t) => e.importFromStorage(t.storageType, t.storagePath, t.database, t.storageConfig) });
337
356
  }
338
357
  //#endregion
339
358
  //#region src/utils/format.ts
340
- var R = new Intl.DateTimeFormat("pt-BR", {
359
+ var z = new Intl.DateTimeFormat("pt-BR", {
341
360
  day: "2-digit",
342
361
  month: "2-digit",
343
362
  year: "numeric",
344
363
  hour: "2-digit",
345
364
  minute: "2-digit"
346
- }), z = [
365
+ }), B = [
347
366
  "B",
348
367
  "KB",
349
368
  "MB",
350
369
  "GB",
351
370
  "TB"
352
371
  ];
353
- function B(e) {
372
+ function V(e) {
354
373
  if (e == null || e < 0) return "—";
355
374
  if (e < 1024) return `${e} B`;
356
375
  let t = e, n = 0;
357
- for (; t >= 1024 && n < z.length - 1;) t /= 1024, n += 1;
358
- return `${Number.isInteger(t) ? t : Number(t.toFixed(1))} ${z[n]}`;
376
+ for (; t >= 1024 && n < B.length - 1;) t /= 1024, n += 1;
377
+ return `${Number.isInteger(t) ? t : Number(t.toFixed(1))} ${B[n]}`;
359
378
  }
360
- function V(e) {
379
+ function H(e) {
361
380
  if (!e) return "—";
362
381
  let t = new Date(e);
363
- return Number.isNaN(t.getTime()) ? "—" : R.format(t);
382
+ return Number.isNaN(t.getTime()) ? "—" : z.format(t);
364
383
  }
365
- var H = {
384
+ var U = {
366
385
  PENDING: "Pendente",
367
386
  IN_PROGRESS: "Em andamento",
368
387
  COMPLETED: "Concluído",
@@ -370,7 +389,7 @@ var H = {
370
389
  RESTORING: "Restaurando",
371
390
  RESTORED: "Restaurado",
372
391
  RESTORE_FAILED: "Falha na restauração"
373
- }, U = {
392
+ }, ee = {
374
393
  PENDING: "text-bg-secondary",
375
394
  IN_PROGRESS: "text-bg-primary",
376
395
  COMPLETED: "text-bg-success",
@@ -396,7 +415,7 @@ var H = {
396
415
  //#endregion
397
416
  //#region src/components/StatusBadge.tsx
398
417
  function q({ status: e }) {
399
- let t = U[e] ?? "text-bg-secondary", n = H[e] ?? e;
418
+ let t = ee[e] ?? "text-bg-secondary", n = U[e] ?? e;
400
419
  return /* @__PURE__ */ p("span", {
401
420
  className: `badge rounded-pill ${t}`,
402
421
  children: n
@@ -423,7 +442,7 @@ function J({ dbInfo: e, isLoading: t, error: n, label: r, compact: i = !1 }) {
423
442
  "aria-hidden": !0
424
443
  }),
425
444
  "Não foi possível consultar o banco configurado: ",
426
- X(n)
445
+ Y(n)
427
446
  ]
428
447
  });
429
448
  if (!e || !e.configured) return i ? /* @__PURE__ */ m("div", {
@@ -563,7 +582,7 @@ function J({ dbInfo: e, isLoading: t, error: n, label: r, compact: i = !1 }) {
563
582
  }
564
583
  //#endregion
565
584
  //#region src/components/RestoreModal.tsx
566
- function Y({ backup: e, onClose: t }) {
585
+ function te({ backup: e, onClose: t }) {
567
586
  let n = M(), r = D(), i = () => {
568
587
  n.mutate({ id: e.id });
569
588
  }, a = n.isPending, o = e.backupType === "STORAGE";
@@ -625,7 +644,7 @@ function Y({ backup: e, onClose: t }) {
625
644
  children: [/* @__PURE__ */ p("i", {
626
645
  className: "bi bi-x-circle me-2",
627
646
  "aria-hidden": !0
628
- }), X(n.error)]
647
+ }), Y(n.error)]
629
648
  }),
630
649
  n.isSuccess && /* @__PURE__ */ m("div", {
631
650
  className: "alert alert-success mt-3 mb-0",
@@ -660,19 +679,19 @@ function Y({ backup: e, onClose: t }) {
660
679
  })
661
680
  })] });
662
681
  }
663
- function X(e) {
682
+ function Y(e) {
664
683
  return e instanceof Error ? e.message : String(e);
665
684
  }
666
685
  //#endregion
667
686
  //#region src/components/BackupsTab.tsx
668
- function Z() {
669
- let [e, t] = o(0), [n, a] = o(null), [s, c] = o(null), [l, u] = o({}), { data: d, isLoading: f, isError: h, error: g, refetch: _, isFetching: v } = E(e, 10, !0), y = F(), b = N(), x = P();
687
+ function X() {
688
+ let [e, t] = o(0), [n, a] = o(null), [s, c] = o(null), [l, u] = o({}), { data: d, isLoading: f, isError: h, error: g, refetch: _, isFetching: v } = E(e, 10, !0), y = I(), b = N(), x = P(), S = F();
670
689
  r(() => {
671
690
  if (!y.data || !y.variables) return;
672
691
  let e = URL.createObjectURL(y.data), t = document.createElement("a");
673
692
  t.href = e, t.download = y.variables.filename, document.body.appendChild(t), t.click(), t.remove(), setTimeout(() => URL.revokeObjectURL(e), 1e4);
674
693
  }, [y.data, y.variables]);
675
- let S = i(() => d?.content ?? [], [d]), C = d?.totalPages ?? 0;
694
+ let C = i(() => d?.content ?? [], [d]), w = d?.totalPages ?? 0;
676
695
  return /* @__PURE__ */ m("div", { children: [
677
696
  /* @__PURE__ */ m("div", {
678
697
  className: "d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3",
@@ -744,6 +763,17 @@ function Z() {
744
763
  Q(x.error)
745
764
  ]
746
765
  }),
766
+ S.isError && /* @__PURE__ */ m("div", {
767
+ className: "alert alert-danger",
768
+ children: [
769
+ /* @__PURE__ */ p("i", {
770
+ className: "bi bi-x-circle me-2",
771
+ "aria-hidden": !0
772
+ }),
773
+ "Falha ao atualizar o agendamento: ",
774
+ Q(S.error)
775
+ ]
776
+ }),
747
777
  Object.entries(l).map(([e, t]) => /* @__PURE__ */ m("div", {
748
778
  className: `alert alert-${t.valid ? "success" : "warning"} d-flex align-items-center justify-content-between`,
749
779
  children: [/* @__PURE__ */ m("span", { children: [
@@ -801,6 +831,10 @@ function Z() {
801
831
  scope: "col",
802
832
  children: "Status"
803
833
  }),
834
+ /* @__PURE__ */ p("th", {
835
+ scope: "col",
836
+ children: "Agendado"
837
+ }),
804
838
  /* @__PURE__ */ p("th", {
805
839
  scope: "col",
806
840
  children: "Checksum"
@@ -818,11 +852,11 @@ function Z() {
818
852
  className: "text-end",
819
853
  children: "Ações"
820
854
  })
821
- ] }) }), /* @__PURE__ */ m("tbody", { children: [S.length === 0 && /* @__PURE__ */ p("tr", { children: /* @__PURE__ */ p("td", {
822
- colSpan: 10,
855
+ ] }) }), /* @__PURE__ */ m("tbody", { children: [C.length === 0 && /* @__PURE__ */ p("tr", { children: /* @__PURE__ */ p("td", {
856
+ colSpan: 11,
823
857
  className: "text-center text-muted py-4",
824
858
  children: "Nenhum backup cadastrado."
825
- }) }), S.map((e) => /* @__PURE__ */ m("tr", { children: [
859
+ }) }), C.map((e) => /* @__PURE__ */ m("tr", { children: [
826
860
  /* @__PURE__ */ p("td", { children: e.id }),
827
861
  /* @__PURE__ */ m("td", {
828
862
  className: "text-truncate",
@@ -854,9 +888,24 @@ function Z() {
854
888
  /* @__PURE__ */ p("td", { children: W[e.databaseType] ?? e.databaseType }),
855
889
  /* @__PURE__ */ p("td", {
856
890
  className: "text-end",
857
- children: B(e.fileSize)
891
+ children: V(e.fileSize)
858
892
  }),
859
893
  /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p(q, { status: e.status }) }),
894
+ /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p("div", {
895
+ className: "form-check form-switch d-inline-block mb-0",
896
+ title: e.scheduled ? "Desligar execução deste backup no agendamento noturno" : "Ligar execução deste backup no agendamento noturno",
897
+ children: /* @__PURE__ */ p("input", {
898
+ className: "form-check-input",
899
+ type: "checkbox",
900
+ role: "switch",
901
+ checked: !!e.scheduled,
902
+ disabled: S.isPending && S.variables?.id === e.id,
903
+ onChange: () => S.mutate({
904
+ id: e.id,
905
+ scheduled: !e.scheduled
906
+ })
907
+ })
908
+ }) }),
860
909
  /* @__PURE__ */ p("td", { children: e.sha256 ? /* @__PURE__ */ m("code", {
861
910
  title: e.sha256,
862
911
  style: { fontSize: "0.8em" },
@@ -879,7 +928,7 @@ function Z() {
879
928
  className: "text-muted",
880
929
  children: "—"
881
930
  }) }),
882
- /* @__PURE__ */ p("td", { children: V(e.createdAt) }),
931
+ /* @__PURE__ */ p("td", { children: H(e.createdAt) }),
883
932
  /* @__PURE__ */ m("td", {
884
933
  className: "text-end text-nowrap",
885
934
  children: [
@@ -947,7 +996,7 @@ function Z() {
947
996
  "Página ",
948
997
  e + 1,
949
998
  " de ",
950
- Math.max(C, 1)
999
+ Math.max(w, 1)
951
1000
  ]
952
1001
  }), /* @__PURE__ */ m("div", {
953
1002
  className: "btn-group",
@@ -963,7 +1012,7 @@ function Z() {
963
1012
  }), /* @__PURE__ */ p("button", {
964
1013
  type: "button",
965
1014
  className: "btn btn-outline-secondary btn-sm",
966
- disabled: e + 1 >= C,
1015
+ disabled: e + 1 >= w,
967
1016
  onClick: () => t((e) => e + 1),
968
1017
  children: /* @__PURE__ */ p("i", {
969
1018
  className: "bi bi-chevron-right",
@@ -972,11 +1021,11 @@ function Z() {
972
1021
  })]
973
1022
  })]
974
1023
  }),
975
- n && /* @__PURE__ */ p(Y, {
1024
+ n && /* @__PURE__ */ p(te, {
976
1025
  backup: n,
977
1026
  onClose: () => a(null)
978
1027
  }),
979
- s && /* @__PURE__ */ p(ee, {
1028
+ s && /* @__PURE__ */ p(Z, {
980
1029
  backup: s,
981
1030
  busy: b.isPending,
982
1031
  onCancel: () => c(null),
@@ -986,7 +1035,7 @@ function Z() {
986
1035
  })
987
1036
  ] });
988
1037
  }
989
- function ee(e) {
1038
+ function Z(e) {
990
1039
  let { backup: t, busy: n, onCancel: r, onConfirm: i } = e;
991
1040
  return /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", { className: "modal-backdrop show" }), /* @__PURE__ */ p("div", {
992
1041
  className: "modal show d-block",
@@ -1057,7 +1106,7 @@ function Q(e) {
1057
1106
  }
1058
1107
  //#endregion
1059
1108
  //#region src/components/CreateBackupTab.tsx
1060
- function te() {
1109
+ function ne() {
1061
1110
  let e = j(), t = D(), n = O(t.data?.configured), [r, a] = o(!0), [s, c] = o({
1062
1111
  format: "plain",
1063
1112
  includeData: !0,
@@ -1066,7 +1115,7 @@ function te() {
1066
1115
  includeIndexes: !0,
1067
1116
  includeConstraints: !0,
1068
1117
  includeRelatedTables: !1
1069
- }), [l, u] = o(() => /* @__PURE__ */ new Set()), [d, f] = o(null), [h, g] = o({}), [_, v] = o(""), [y, b] = o(!1), x = k(d, t.data?.configured), S = i(() => new Set((t.data?.exportExcludedTables ?? []).map(re)), [t.data?.exportExcludedTables]), C = i(() => {
1118
+ }), [l, u] = o(() => /* @__PURE__ */ new Set()), [d, f] = o(null), [h, g] = o({}), [_, v] = o(""), [y, b] = o(!1), x = k(d, t.data?.configured), S = i(() => new Set((t.data?.exportExcludedTables ?? []).map(ie)), [t.data?.exportExcludedTables]), C = i(() => {
1070
1119
  let e = n.data ?? [], t = _.trim().toLowerCase();
1071
1120
  return t ? e.filter((e) => e.fullName.toLowerCase().includes(t)) : e;
1072
1121
  }, [n.data, _]), w = i(() => Object.values(h).reduce((e, t) => e + t.length, 0), [h]), T = (e) => {
@@ -1167,7 +1216,7 @@ function te() {
1167
1216
  "aria-hidden": !0
1168
1217
  }),
1169
1218
  "Falha ao listar tabelas: ",
1170
- X(n.error)
1219
+ Y(n.error)
1171
1220
  ]
1172
1221
  }),
1173
1222
  C.length === 0 && !n.isLoading && /* @__PURE__ */ p("div", {
@@ -1183,7 +1232,7 @@ function te() {
1183
1232
  maxHeight: 420,
1184
1233
  overflow: "auto"
1185
1234
  },
1186
- children: C.map((e) => /* @__PURE__ */ p(ne, {
1235
+ children: C.map((e) => /* @__PURE__ */ p(re, {
1187
1236
  table: e,
1188
1237
  disabled: S.has(e.fullName),
1189
1238
  selected: l.has(e.fullName),
@@ -1344,7 +1393,7 @@ function te() {
1344
1393
  "aria-hidden": !0
1345
1394
  }),
1346
1395
  "Falha ao criar backup: ",
1347
- X(e.error)
1396
+ Y(e.error)
1348
1397
  ]
1349
1398
  }),
1350
1399
  e.isSuccess && /* @__PURE__ */ m("div", {
@@ -1404,7 +1453,7 @@ function te() {
1404
1453
  })
1405
1454
  ] });
1406
1455
  }
1407
- function ne({ table: e, disabled: t, selected: n, expanded: r, excluded: i, detail: a, onToggleTable: o, onToggleExpand: s, onToggleColumn: c }) {
1456
+ function re({ table: e, disabled: t, selected: n, expanded: r, excluded: i, detail: a, onToggleTable: o, onToggleExpand: s, onToggleColumn: c }) {
1408
1457
  return /* @__PURE__ */ p("div", {
1409
1458
  className: `card h-100 ${n ? "border-primary" : ""}`,
1410
1459
  style: { minWidth: 0 },
@@ -1468,7 +1517,7 @@ function ne({ table: e, disabled: t, selected: n, expanded: r, excluded: i, deta
1468
1517
  }),
1469
1518
  a?.isError && /* @__PURE__ */ m("small", {
1470
1519
  className: "text-danger",
1471
- children: ["Erro: ", X(a.error)]
1520
+ children: ["Erro: ", Y(a.error)]
1472
1521
  }),
1473
1522
  a?.data && /* @__PURE__ */ m(f, { children: [a.data.columns.map((e) => /* @__PURE__ */ m("div", {
1474
1523
  className: "d-flex align-items-center gap-2 py-1",
@@ -1519,13 +1568,13 @@ function ne({ table: e, disabled: t, selected: n, expanded: r, excluded: i, deta
1519
1568
  })
1520
1569
  });
1521
1570
  }
1522
- function re(e) {
1571
+ function ie(e) {
1523
1572
  let t = e.trim();
1524
1573
  return t.includes(".") ? t : `public.${t}`;
1525
1574
  }
1526
1575
  //#endregion
1527
1576
  //#region src/components/DiagnosticsTab.tsx
1528
- function ie() {
1577
+ function ae() {
1529
1578
  let { data: e, isLoading: t, isError: n, error: r, refetch: a, isFetching: o } = T(), s = i(() => e ? {
1530
1579
  total: e.length,
1531
1580
  okCount: e.filter((e) => e.ok).length,
@@ -1566,7 +1615,7 @@ function ie() {
1566
1615
  "aria-hidden": !0
1567
1616
  }),
1568
1617
  "Não foi possível executar as checagens: ",
1569
- X(r)
1618
+ Y(r)
1570
1619
  ]
1571
1620
  }),
1572
1621
  s && /* @__PURE__ */ m("div", {
@@ -1603,7 +1652,7 @@ function ie() {
1603
1652
  className: "card",
1604
1653
  children: /* @__PURE__ */ m("ul", {
1605
1654
  className: "list-group list-group-flush",
1606
- children: [(e ?? []).map((e) => /* @__PURE__ */ p(ae, { check: e }, e.name)), e && e.length === 0 && /* @__PURE__ */ p("li", {
1655
+ children: [(e ?? []).map((e) => /* @__PURE__ */ p(oe, { check: e }, e.name)), e && e.length === 0 && /* @__PURE__ */ p("li", {
1607
1656
  className: "list-group-item text-center text-muted py-4",
1608
1657
  children: "Nenhuma checagem retornada."
1609
1658
  })]
@@ -1611,7 +1660,7 @@ function ie() {
1611
1660
  })
1612
1661
  ] });
1613
1662
  }
1614
- function ae({ check: e }) {
1663
+ function oe({ check: e }) {
1615
1664
  let t = e.configured ? e.ok ? "bi-check-circle-fill text-success" : "bi-x-octagon-fill text-danger" : "bi-dash-circle text-secondary", n = e.configured ? e.ok ? "text-bg-success" : "text-bg-danger" : "text-bg-secondary", r = e.configured ? e.ok ? "OK" : "Falha" : "Não configurado";
1616
1665
  return /* @__PURE__ */ m("li", {
1617
1666
  className: "list-group-item d-flex align-items-start gap-3",
@@ -1647,80 +1696,92 @@ function ae({ check: e }) {
1647
1696
  }
1648
1697
  //#endregion
1649
1698
  //#region src/components/StorageExplorerTab.tsx
1650
- var oe = 1500;
1699
+ var se = 1500;
1651
1700
  function $({ target: e = "origin", title: n = "Explorador de Storage", storageType: a = "LOCAL", storageConfig: s }) {
1652
- let c = b(), h = d(), [g, _] = o(""), [v, y] = o([]), [x, S] = o(/* @__PURE__ */ new Set()), [C, w] = o(null), [T, E] = o(null), [D, O] = o(null), [k, A] = o(!1), j = e === "destination" ? "Destino" : "Origem", { data: M, isPending: N } = u({
1701
+ let c = b(), h = d(), [g, _] = o(""), [v, y] = o([]), [x, S] = o(/* @__PURE__ */ new Set()), [C, w] = o(null), [T, E] = o(!1), [D, O] = o(null), [k, A] = o(null), [j, M] = o(null), [N, P] = o(!1), F = e === "destination" ? "Destino" : "Origem", { data: I, isPending: L } = u({
1653
1702
  queryKey: ["storage-config"],
1654
1703
  queryFn: () => c.getStorageConfig(),
1655
1704
  retry: !1
1656
- }), P = M?.[e], F = i(() => P?.configured ? {
1657
- type: P.type,
1658
- ...P.localPath ? { localPath: P.localPath } : {},
1659
- ...P.endpoint ? { endpoint: P.endpoint } : {},
1660
- ...P.bucketName ? { bucketName: P.bucketName } : {},
1661
- ...P.region ? { region: P.region } : {},
1662
- ...P.pathStyleEnabled ? { pathStyleEnabled: !0 } : {}
1663
- } : s, [P, s]), I = F?.type ?? a, { data: L, isLoading: R } = u({
1705
+ }), R = I?.[e], z = i(() => R?.configured ? {
1706
+ type: R.type,
1707
+ ...R.localPath ? { localPath: R.localPath } : {},
1708
+ ...R.endpoint ? { endpoint: R.endpoint } : {},
1709
+ ...R.bucketName ? { bucketName: R.bucketName } : {},
1710
+ ...R.region ? { region: R.region } : {},
1711
+ ...R.pathStyleEnabled ? { pathStyleEnabled: !0 } : {}
1712
+ } : s, [R, s]), B = z?.type ?? a, { data: U, isLoading: ee } = u({
1664
1713
  queryKey: [
1665
1714
  "storage-files",
1666
1715
  e,
1667
- I,
1716
+ B,
1668
1717
  g,
1669
- F
1718
+ z
1670
1719
  ],
1671
- queryFn: () => c.listStorageFiles(I, g || void 0, F, e),
1672
- enabled: !N
1673
- }), z = l({
1674
- mutationFn: (t) => c.deleteStorageFile(t, I, F, e),
1720
+ queryFn: () => c.listStorageFiles(B, g || void 0, z, e),
1721
+ enabled: !L
1722
+ }), W = l({
1723
+ mutationFn: (t) => c.deleteStorageFile(t, B, z, e),
1675
1724
  onSuccess: () => {
1676
1725
  h.invalidateQueries({ queryKey: ["storage-files"] }), w(null);
1677
1726
  }
1678
- }), H = t((e) => {
1727
+ }), G = l({
1728
+ mutationFn: (t) => {
1729
+ let n = {
1730
+ keys: t,
1731
+ storage: e,
1732
+ type: B
1733
+ };
1734
+ return z?.localPath && (n.localPath = z.localPath), z?.endpoint && (n.endpoint = z.endpoint), z?.bucketName && (n.bucketName = z.bucketName), z?.accessKey && (n.accessKey = z.accessKey), z?.secretKey && (n.secretKey = z.secretKey), z?.region && (n.region = z.region), z?.pathStyleEnabled && (n.pathStyleEnabled = !0), c.restoreStorageItems(n);
1735
+ },
1736
+ onSuccess: (e) => {
1737
+ E(!1), O(e), h.invalidateQueries({ queryKey: ["storage-files"] });
1738
+ }
1739
+ }), K = t((e) => {
1679
1740
  _(e), y(e ? e.split("/").filter(Boolean) : []), S(/* @__PURE__ */ new Set());
1680
- }, []), U = t((e) => {
1741
+ }, []), q = t((e) => {
1681
1742
  let t = v.slice(0, e + 1).join("/");
1682
- H(t);
1683
- }, [v, H]);
1743
+ K(t);
1744
+ }, [v, K]);
1684
1745
  r(() => {
1685
1746
  y(g ? g.split("/").filter(Boolean) : []);
1686
1747
  }, [g]);
1687
- let W = (e) => {
1748
+ let J = (e) => {
1688
1749
  S((t) => {
1689
1750
  let n = new Set(t);
1690
1751
  return n.has(e) ? n.delete(e) : n.add(e), n;
1691
1752
  });
1692
- }, G = () => {
1693
- L && S((e) => e.size === L.length ? /* @__PURE__ */ new Set() : new Set(L.map((e) => e.path)));
1694
- }, K = (e, t) => {
1753
+ }, te = () => {
1754
+ U && S((e) => e.size === U.length ? /* @__PURE__ */ new Set() : new Set(U.map((e) => e.path)));
1755
+ }, Y = (e, t) => {
1695
1756
  let n = window.URL.createObjectURL(e), r = document.createElement("a");
1696
1757
  r.href = n, r.download = t, document.body.appendChild(r), r.click(), r.remove(), window.URL.revokeObjectURL(n);
1697
- }, q = async (t, n) => {
1758
+ }, X = async (t, n) => {
1698
1759
  let r = {
1699
1760
  storage: e,
1700
- type: I,
1761
+ type: B,
1701
1762
  mode: t,
1702
1763
  keys: n
1703
1764
  };
1704
- F?.localPath && (r.localPath = F.localPath), F?.endpoint && (r.endpoint = F.endpoint), F?.bucketName && (r.bucketName = F.bucketName), F?.accessKey && (r.accessKey = F.accessKey), F?.secretKey && (r.secretKey = F.secretKey), F?.region && (r.region = F.region), F?.pathStyleEnabled && (r.pathStyleEnabled = !0), O(null);
1765
+ z?.localPath && (r.localPath = z.localPath), z?.endpoint && (r.endpoint = z.endpoint), z?.bucketName && (r.bucketName = z.bucketName), z?.accessKey && (r.accessKey = z.accessKey), z?.secretKey && (r.secretKey = z.secretKey), z?.region && (r.region = z.region), z?.pathStyleEnabled && (r.pathStyleEnabled = !0), M(null);
1705
1766
  let i = await c.createStorageZip(r);
1706
- E(i);
1707
- }, J = async (e) => {
1708
- await q("file", [e]);
1709
- }, Y = async () => {
1710
- await q("zip", [...x]);
1711
- }, X = async (e) => {
1767
+ A(i);
1768
+ }, Z = async (e) => {
1769
+ await X("file", [e]);
1770
+ }, Q = async () => {
1771
+ await X("zip", [...x]);
1772
+ }, ne = async (e) => {
1712
1773
  try {
1713
- A(!0);
1774
+ P(!0);
1714
1775
  let t = await c.downloadStorageZip(e.jobId);
1715
- K(t, e.fileName ?? `storage_${j.toLowerCase()}.zip`);
1776
+ Y(t, e.fileName ?? `storage_${F.toLowerCase()}.zip`);
1716
1777
  } catch (e) {
1717
- O(e instanceof Error ? e.message : String(e));
1778
+ M(e instanceof Error ? e.message : String(e));
1718
1779
  } finally {
1719
- A(!1), E(null);
1780
+ P(!1), A(null);
1720
1781
  }
1721
1782
  };
1722
1783
  r(() => {
1723
- let e = T?.jobId;
1784
+ let e = k?.jobId;
1724
1785
  if (!e) return;
1725
1786
  let t = !1, n;
1726
1787
  return n = window.setInterval(async () => {
@@ -1729,17 +1790,17 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1729
1790
  r = await c.getStorageZipStatus(e);
1730
1791
  } catch (e) {
1731
1792
  if (window.clearInterval(n), t) return;
1732
- O(e instanceof Error ? e.message : String(e)), E(null);
1793
+ M(e instanceof Error ? e.message : String(e)), A(null);
1733
1794
  return;
1734
1795
  }
1735
- t || (E(r), r.status === "DONE" ? (window.clearInterval(n), await X(r)) : r.status === "FAILED" && (window.clearInterval(n), O(r.message)));
1736
- }, oe), () => {
1796
+ t || (A(r), r.status === "DONE" ? (window.clearInterval(n), await ne(r)) : r.status === "FAILED" && (window.clearInterval(n), M(r.message)));
1797
+ }, se), () => {
1737
1798
  t = !0, window.clearInterval(n);
1738
1799
  };
1739
- }, [T?.jobId]);
1740
- let Z = () => {
1741
- E(null), O(null);
1742
- }, ee = (e) => e ? V(e) : "-";
1800
+ }, [k?.jobId]);
1801
+ let re = () => {
1802
+ A(null), M(null);
1803
+ }, ie = (e) => e ? H(e) : "-";
1743
1804
  return /* @__PURE__ */ m("div", {
1744
1805
  className: "space-y-3",
1745
1806
  children: [
@@ -1752,37 +1813,51 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1752
1813
  n,
1753
1814
  /* @__PURE__ */ p("span", {
1754
1815
  className: "badge bg-secondary ms-2",
1755
- children: j
1816
+ children: F
1756
1817
  }),
1757
1818
  /* @__PURE__ */ p("span", {
1758
1819
  className: "badge bg-light text-dark border ms-1",
1759
- children: I
1820
+ children: B
1760
1821
  })
1761
1822
  ]
1762
1823
  }), /* @__PURE__ */ p("div", {
1763
1824
  className: "d-flex gap-2",
1764
- children: x.size > 0 && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("button", {
1765
- className: "btn btn-sm btn-outline-primary",
1766
- onClick: Y,
1767
- children: [
1768
- /* @__PURE__ */ p("i", { className: "bi bi-download me-1" }),
1769
- "Baixar seleção (",
1770
- x.size,
1771
- ")"
1772
- ]
1773
- }), /* @__PURE__ */ m("button", {
1774
- className: "btn btn-sm btn-outline-danger",
1775
- onClick: () => w("multiple"),
1776
- children: [
1777
- /* @__PURE__ */ p("i", { className: "bi bi-trash me-1" }),
1778
- "Excluir (",
1779
- x.size,
1780
- ")"
1781
- ]
1782
- })] })
1825
+ children: x.size > 0 && /* @__PURE__ */ m(f, { children: [
1826
+ /* @__PURE__ */ m("button", {
1827
+ className: "btn btn-sm btn-outline-primary",
1828
+ onClick: Q,
1829
+ children: [
1830
+ /* @__PURE__ */ p("i", { className: "bi bi-download me-1" }),
1831
+ "Baixar seleção (",
1832
+ x.size,
1833
+ ")"
1834
+ ]
1835
+ }),
1836
+ e === "destination" && /* @__PURE__ */ m("button", {
1837
+ className: "btn btn-sm btn-outline-success",
1838
+ onClick: () => E(!0),
1839
+ disabled: G.isPending,
1840
+ children: [
1841
+ G.isPending ? /* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }) : /* @__PURE__ */ p("i", { className: "bi bi-arrow-counterclockwise me-1" }),
1842
+ "Restaurar (",
1843
+ x.size,
1844
+ ")"
1845
+ ]
1846
+ }),
1847
+ /* @__PURE__ */ m("button", {
1848
+ className: "btn btn-sm btn-outline-danger",
1849
+ onClick: () => w("multiple"),
1850
+ children: [
1851
+ /* @__PURE__ */ p("i", { className: "bi bi-trash me-1" }),
1852
+ "Excluir (",
1853
+ x.size,
1854
+ ")"
1855
+ ]
1856
+ })
1857
+ ] })
1783
1858
  })]
1784
1859
  }),
1785
- !N && !P?.configured && !s && /* @__PURE__ */ m("div", {
1860
+ !L && !R?.configured && !s && /* @__PURE__ */ m("div", {
1786
1861
  className: "alert alert-warning small py-1 mb-2",
1787
1862
  children: [
1788
1863
  /* @__PURE__ */ p("i", {
@@ -1803,17 +1878,17 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1803
1878
  children: [/* @__PURE__ */ p("li", {
1804
1879
  className: `breadcrumb-item ${v.length === 0 ? "active" : ""}`,
1805
1880
  style: { cursor: v.length > 0 ? "pointer" : "default" },
1806
- onClick: () => H(""),
1881
+ onClick: () => K(""),
1807
1882
  children: /* @__PURE__ */ p("i", { className: "bi bi-house" })
1808
1883
  }), v.map((e, t) => /* @__PURE__ */ p("li", {
1809
1884
  className: `breadcrumb-item ${t === v.length - 1 ? "active" : ""}`,
1810
1885
  style: { cursor: t < v.length - 1 ? "pointer" : "default" },
1811
- onClick: () => t < v.length - 1 && U(t),
1886
+ onClick: () => t < v.length - 1 && q(t),
1812
1887
  children: e
1813
1888
  }, t))]
1814
1889
  })
1815
1890
  }),
1816
- R || N ? /* @__PURE__ */ m("div", {
1891
+ ee || L ? /* @__PURE__ */ m("div", {
1817
1892
  className: "text-center py-5",
1818
1893
  children: [/* @__PURE__ */ p("div", {
1819
1894
  className: "spinner-border text-primary",
@@ -1822,14 +1897,14 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1822
1897
  className: "mt-2 small text-muted",
1823
1898
  children: "Carregando arquivos..."
1824
1899
  })]
1825
- }) : !L || L.length === 0 ? /* @__PURE__ */ m("div", {
1900
+ }) : !U || U.length === 0 ? /* @__PURE__ */ m("div", {
1826
1901
  className: "text-center py-5 text-muted",
1827
1902
  children: [
1828
1903
  /* @__PURE__ */ p("i", { className: "bi bi-folder-x fs-1 d-block mb-2" }),
1829
1904
  "Nenhum arquivo encontrado",
1830
1905
  g && /* @__PURE__ */ p("button", {
1831
1906
  className: "btn btn-sm btn-link mt-2",
1832
- onClick: () => H(""),
1907
+ onClick: () => K(""),
1833
1908
  children: "Voltar ao inicio"
1834
1909
  })
1835
1910
  ]
@@ -1837,11 +1912,11 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1837
1912
  className: "d-flex align-items-center gap-2 mb-2",
1838
1913
  children: [/* @__PURE__ */ m("button", {
1839
1914
  className: "btn btn-sm btn-outline-secondary",
1840
- onClick: G,
1841
- children: [x.size === L.length ? "Desmarcar" : "Selecionar", " Todos"]
1915
+ onClick: te,
1916
+ children: [x.size === U.length ? "Desmarcar" : "Selecionar", " Todos"]
1842
1917
  }), /* @__PURE__ */ m("span", {
1843
1918
  className: "small text-muted",
1844
- children: [L.length, " item(ns)"]
1919
+ children: [U.length, " item(ns)"]
1845
1920
  })]
1846
1921
  }), /* @__PURE__ */ p("div", {
1847
1922
  className: "table-responsive",
@@ -1865,53 +1940,73 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1865
1940
  children: "Acoes"
1866
1941
  })
1867
1942
  ] })
1868
- }), /* @__PURE__ */ p("tbody", { children: L.map((e) => /* @__PURE__ */ m("tr", {
1869
- className: x.has(e.path) ? "table-active" : "",
1943
+ }), /* @__PURE__ */ p("tbody", { children: U.map((t) => /* @__PURE__ */ m("tr", {
1944
+ className: x.has(t.path) ? "table-active" : "",
1870
1945
  children: [
1871
1946
  /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p("input", {
1872
1947
  type: "checkbox",
1873
1948
  className: "form-check-input",
1874
- checked: x.has(e.path),
1875
- onChange: () => W(e.path)
1949
+ checked: x.has(t.path),
1950
+ onChange: () => J(t.path)
1876
1951
  }) }),
1877
- /* @__PURE__ */ p("td", { children: e.directory ? /* @__PURE__ */ m("button", {
1952
+ /* @__PURE__ */ p("td", { children: t.directory ? /* @__PURE__ */ m("button", {
1878
1953
  className: "btn btn-sm btn-link text-decoration-none p-0 text-start",
1879
- onClick: () => H(e.path),
1954
+ onClick: () => K(t.path),
1880
1955
  children: [/* @__PURE__ */ p("i", { className: "bi bi-folder-fill text-warning me-2" }), /* @__PURE__ */ p("span", {
1881
1956
  className: "font-monospace",
1882
- children: e.name
1957
+ children: t.name
1883
1958
  })]
1884
1959
  }) : /* @__PURE__ */ m("span", {
1885
1960
  className: "font-monospace small",
1886
- children: [/* @__PURE__ */ p("i", { className: "bi bi-file-earmark me-2 text-primary" }), e.name]
1961
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-file-earmark me-2 text-primary" }), t.name]
1887
1962
  }) }),
1888
1963
  /* @__PURE__ */ p("td", {
1889
1964
  className: "text-muted small",
1890
- children: e.directory ? "-" : B(e.size)
1965
+ children: t.directory ? "-" : V(t.size)
1891
1966
  }),
1892
1967
  /* @__PURE__ */ p("td", {
1893
1968
  className: "text-muted small",
1894
- children: ee(e.lastModified)
1969
+ children: ie(t.lastModified)
1895
1970
  }),
1896
- /* @__PURE__ */ p("td", { children: !e.directory && /* @__PURE__ */ m("div", {
1971
+ /* @__PURE__ */ p("td", { children: e === "destination" ? /* @__PURE__ */ m("div", {
1897
1972
  className: "d-flex gap-1",
1898
1973
  children: [/* @__PURE__ */ p("button", {
1974
+ className: "btn btn-sm btn-outline-success py-0",
1975
+ title: "Restaurar para a origem",
1976
+ onClick: () => {
1977
+ S(/* @__PURE__ */ new Set([t.path])), E(!0);
1978
+ },
1979
+ children: /* @__PURE__ */ p("i", { className: "bi bi-arrow-counterclockwise" })
1980
+ }), !t.directory && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("button", {
1899
1981
  className: "btn btn-sm btn-outline-primary py-0",
1900
1982
  title: "Baixar",
1901
- onClick: () => J(e.path),
1983
+ onClick: () => Z(t.path),
1902
1984
  children: /* @__PURE__ */ p("i", { className: "bi bi-download" })
1903
1985
  }), /* @__PURE__ */ p("button", {
1904
1986
  className: "btn btn-sm btn-outline-danger py-0",
1905
1987
  title: "Excluir",
1906
- onClick: () => w(e.path),
1988
+ onClick: () => w(t.path),
1989
+ children: /* @__PURE__ */ p("i", { className: "bi bi-trash" })
1990
+ })] })]
1991
+ }) : t.directory ? null : /* @__PURE__ */ m("div", {
1992
+ className: "d-flex gap-1",
1993
+ children: [/* @__PURE__ */ p("button", {
1994
+ className: "btn btn-sm btn-outline-primary py-0",
1995
+ title: "Baixar",
1996
+ onClick: () => Z(t.path),
1997
+ children: /* @__PURE__ */ p("i", { className: "bi bi-download" })
1998
+ }), /* @__PURE__ */ p("button", {
1999
+ className: "btn btn-sm btn-outline-danger py-0",
2000
+ title: "Excluir",
2001
+ onClick: () => w(t.path),
1907
2002
  children: /* @__PURE__ */ p("i", { className: "bi bi-trash" })
1908
2003
  })]
1909
2004
  }) })
1910
2005
  ]
1911
- }, e.path)) })]
2006
+ }, t.path)) })]
1912
2007
  })
1913
2008
  })] }),
1914
- T && /* @__PURE__ */ p("div", {
2009
+ k && /* @__PURE__ */ p("div", {
1915
2010
  className: "modal d-block",
1916
2011
  tabIndex: -1,
1917
2012
  style: { background: "rgba(0,0,0,.5)" },
@@ -1924,10 +2019,10 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1924
2019
  className: "modal-header",
1925
2020
  children: [/* @__PURE__ */ m("h6", {
1926
2021
  className: "modal-title",
1927
- children: [/* @__PURE__ */ p("i", { className: "bi bi-box-arrow-down me-2" }), T.mode === "ZIP" ? "Compactando e baixando" : "Baixando arquivo"]
2022
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-box-arrow-down me-2" }), k.mode === "ZIP" ? "Compactando e baixando" : "Baixando arquivo"]
1928
2023
  }), /* @__PURE__ */ p("button", {
1929
2024
  className: "btn-close",
1930
- onClick: Z
2025
+ onClick: re
1931
2026
  })]
1932
2027
  }),
1933
2028
  /* @__PURE__ */ m("div", {
@@ -1946,9 +2041,9 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1946
2041
  className: "w-100",
1947
2042
  children: [/* @__PURE__ */ m("div", {
1948
2043
  className: "d-flex justify-content-between small mb-1",
1949
- children: [/* @__PURE__ */ p("span", { children: ((e) => e.mode === "FILE" ? e.phase === "DOWNLOADING" ? e.totalBytes > 0 ? `Baixando arquivo... ${B(e.processedBytes)} / ${B(e.totalBytes)}` : "Baixando arquivo..." : e.message || "Preparando download..." : e.phase === "PREPARING" ? `Preparando ${e.processedItems}/${e.totalItems} arquivo(s)...` : e.phase === "COMPRESSING" ? `Compactando... ${e.percent}%` : e.message || "Processando...")(T) }), /* @__PURE__ */ m("span", {
2044
+ children: [/* @__PURE__ */ p("span", { children: ((e) => e.mode === "FILE" ? e.phase === "DOWNLOADING" ? e.totalBytes > 0 ? `Baixando arquivo... ${V(e.processedBytes)} / ${V(e.totalBytes)}` : "Baixando arquivo..." : e.message || "Preparando download..." : e.phase === "PREPARING" ? `Preparando ${e.processedItems}/${e.totalItems} arquivo(s)...` : e.phase === "COMPRESSING" ? `Compactando... ${e.percent}%` : e.message || "Processando...")(k) }), /* @__PURE__ */ m("span", {
1950
2045
  className: "text-muted",
1951
- children: [T.percent, "%"]
2046
+ children: [k.percent, "%"]
1952
2047
  })]
1953
2048
  }), /* @__PURE__ */ p("div", {
1954
2049
  className: "progress",
@@ -1956,39 +2051,39 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1956
2051
  children: /* @__PURE__ */ p("div", {
1957
2052
  className: "progress-bar progress-bar-striped progress-bar-animated",
1958
2053
  role: "progressbar",
1959
- style: { width: `${Math.max(T.percent, 3)}%` }
2054
+ style: { width: `${Math.max(k.percent, 3)}%` }
1960
2055
  })
1961
2056
  })]
1962
2057
  })]
1963
2058
  }),
1964
- T.currentItem && /* @__PURE__ */ m("div", {
2059
+ k.currentItem && /* @__PURE__ */ m("div", {
1965
2060
  className: "small text-muted",
1966
- title: T.currentItem,
2061
+ title: k.currentItem,
1967
2062
  children: [/* @__PURE__ */ p("i", {
1968
2063
  className: "bi bi-file-earmark-text me-1",
1969
2064
  "aria-hidden": !0
1970
2065
  }), /* @__PURE__ */ p("span", {
1971
2066
  className: "font-monospace",
1972
- children: T.currentItem
2067
+ children: k.currentItem
1973
2068
  })]
1974
2069
  }),
1975
- T.mode === "FILE" && T.totalBytes > 0 || T.mode === "ZIP" ? /* @__PURE__ */ m("div", {
2070
+ k.mode === "FILE" && k.totalBytes > 0 || k.mode === "ZIP" ? /* @__PURE__ */ m("div", {
1976
2071
  className: "small text-muted mt-1",
1977
2072
  children: [
1978
2073
  /* @__PURE__ */ p("i", {
1979
2074
  className: "bi bi-hdd me-1",
1980
2075
  "aria-hidden": !0
1981
2076
  }),
1982
- B(T.processedBytes),
1983
- T.totalBytes > 0 ? ` / ${B(T.totalBytes)}` : ""
2077
+ V(k.processedBytes),
2078
+ k.totalBytes > 0 ? ` / ${V(k.totalBytes)}` : ""
1984
2079
  ]
1985
2080
  }) : null,
1986
- T.status === "FAILED" && /* @__PURE__ */ m("div", {
2081
+ k.status === "FAILED" && /* @__PURE__ */ m("div", {
1987
2082
  className: "alert alert-danger small mt-2 mb-0 py-1",
1988
2083
  children: [/* @__PURE__ */ p("i", {
1989
2084
  className: "bi bi-exclamation-triangle me-1",
1990
2085
  "aria-hidden": !0
1991
- }), T.message || "Falha ao preparar o download."]
2086
+ }), k.message || "Falha ao preparar o download."]
1992
2087
  })
1993
2088
  ]
1994
2089
  }),
@@ -1996,16 +2091,16 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1996
2091
  className: "modal-footer",
1997
2092
  children: /* @__PURE__ */ p("button", {
1998
2093
  className: "btn btn-sm btn-secondary",
1999
- onClick: Z,
2000
- disabled: k,
2001
- children: k ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Baixando..."] }) : T.status === "DONE" || T.status === "FAILED" ? "Fechar" : "Fechar (continua em 2º plano)"
2094
+ onClick: re,
2095
+ disabled: N,
2096
+ children: N ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Baixando..."] }) : k.status === "DONE" || k.status === "FAILED" ? "Fechar" : "Fechar (continua em 2º plano)"
2002
2097
  })
2003
2098
  })
2004
2099
  ]
2005
2100
  })
2006
2101
  })
2007
2102
  }),
2008
- D && !T && /* @__PURE__ */ p("div", {
2103
+ j && !k && /* @__PURE__ */ p("div", {
2009
2104
  className: "modal d-block",
2010
2105
  tabIndex: -1,
2011
2106
  style: { background: "rgba(0,0,0,.5)" },
@@ -2021,21 +2116,21 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
2021
2116
  children: [/* @__PURE__ */ p("i", { className: "bi bi-exclamation-triangle me-2 text-danger" }), "Falha no download"]
2022
2117
  }), /* @__PURE__ */ p("button", {
2023
2118
  className: "btn-close",
2024
- onClick: () => O(null)
2119
+ onClick: () => M(null)
2025
2120
  })]
2026
2121
  }),
2027
2122
  /* @__PURE__ */ p("div", {
2028
2123
  className: "modal-body",
2029
2124
  children: /* @__PURE__ */ p("p", {
2030
2125
  className: "mb-0 text-danger small",
2031
- children: D
2126
+ children: j
2032
2127
  })
2033
2128
  }),
2034
2129
  /* @__PURE__ */ p("div", {
2035
2130
  className: "modal-footer",
2036
2131
  children: /* @__PURE__ */ p("button", {
2037
2132
  className: "btn btn-sm btn-secondary",
2038
- onClick: () => O(null),
2133
+ onClick: () => M(null),
2039
2134
  children: "Fechar"
2040
2135
  })
2041
2136
  })
@@ -2078,7 +2173,7 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
2078
2173
  className: "text-danger small mb-0",
2079
2174
  children: "Esta acao nao pode ser desfeita."
2080
2175
  }),
2081
- z.isError && /* @__PURE__ */ m("div", {
2176
+ W.isError && /* @__PURE__ */ m("div", {
2082
2177
  className: "alert alert-danger small mt-2 mb-0 py-1",
2083
2178
  children: [
2084
2179
  /* @__PURE__ */ p("i", {
@@ -2087,7 +2182,7 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
2087
2182
  }),
2088
2183
  "Falha ao excluir:",
2089
2184
  " ",
2090
- z.error instanceof Error ? z.error.message : String(z.error)
2185
+ W.error instanceof Error ? W.error.message : String(W.error)
2091
2186
  ]
2092
2187
  })
2093
2188
  ]
@@ -2100,25 +2195,145 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
2100
2195
  children: "Cancelar"
2101
2196
  }), /* @__PURE__ */ p("button", {
2102
2197
  className: "btn btn-sm btn-danger",
2103
- disabled: z.isPending,
2198
+ disabled: W.isPending,
2104
2199
  onClick: async () => {
2105
- if (C === "multiple") for (let e of x) await z.mutateAsync(e);
2106
- else await z.mutateAsync(C);
2200
+ if (C === "multiple") for (let e of x) await W.mutateAsync(e);
2201
+ else await W.mutateAsync(C);
2107
2202
  },
2108
- children: z.isPending ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Excluindo..."] }) : "Excluir"
2203
+ children: W.isPending ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Excluindo..."] }) : "Excluir"
2204
+ })]
2205
+ })
2206
+ ]
2207
+ })
2208
+ })
2209
+ }),
2210
+ T && /* @__PURE__ */ p("div", {
2211
+ className: "modal d-block",
2212
+ tabIndex: -1,
2213
+ style: { background: "rgba(0,0,0,.5)" },
2214
+ children: /* @__PURE__ */ p("div", {
2215
+ className: "modal-dialog modal-dialog-centered",
2216
+ children: /* @__PURE__ */ m("div", {
2217
+ className: "modal-content",
2218
+ children: [
2219
+ /* @__PURE__ */ m("div", {
2220
+ className: "modal-header",
2221
+ children: [/* @__PURE__ */ m("h6", {
2222
+ className: "modal-title",
2223
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-arrow-counterclockwise me-2 text-success" }), "Restaurar para a origem"]
2224
+ }), /* @__PURE__ */ p("button", {
2225
+ className: "btn-close",
2226
+ onClick: () => E(!1)
2227
+ })]
2228
+ }),
2229
+ /* @__PURE__ */ m("div", {
2230
+ className: "modal-body",
2231
+ children: [
2232
+ /* @__PURE__ */ m("p", {
2233
+ className: "mb-2",
2234
+ children: [
2235
+ "Copiar ",
2236
+ /* @__PURE__ */ p("strong", { children: x.size }),
2237
+ " arquivo(s)/pasta(s) do storage",
2238
+ " ",
2239
+ /* @__PURE__ */ p("strong", { children: F }),
2240
+ " para o storage de origem?"
2241
+ ]
2242
+ }),
2243
+ /* @__PURE__ */ m("p", {
2244
+ className: "small text-muted",
2245
+ children: [
2246
+ "Pastas são expandidas recursivamente e arquivos ",
2247
+ /* @__PURE__ */ p("code", { children: ".zip" }),
2248
+ " são extraídos na origem preservando a estrutura de pastas."
2249
+ ]
2250
+ }),
2251
+ G.isError && /* @__PURE__ */ m("div", {
2252
+ className: "alert alert-danger small mt-2 mb-0 py-1",
2253
+ children: [
2254
+ /* @__PURE__ */ p("i", {
2255
+ className: "bi bi-exclamation-triangle me-1",
2256
+ "aria-hidden": !0
2257
+ }),
2258
+ "Falha ao restaurar:",
2259
+ " ",
2260
+ G.error instanceof Error ? G.error.message : String(G.error)
2261
+ ]
2262
+ })
2263
+ ]
2264
+ }),
2265
+ /* @__PURE__ */ m("div", {
2266
+ className: "modal-footer",
2267
+ children: [/* @__PURE__ */ p("button", {
2268
+ className: "btn btn-sm btn-secondary",
2269
+ onClick: () => E(!1),
2270
+ children: "Cancelar"
2271
+ }), /* @__PURE__ */ p("button", {
2272
+ className: "btn btn-sm btn-success",
2273
+ disabled: G.isPending,
2274
+ onClick: () => G.mutate([...x]),
2275
+ children: G.isPending ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Restaurando..."] }) : "Restaurar"
2109
2276
  })]
2110
2277
  })
2111
2278
  ]
2112
2279
  })
2113
2280
  })
2281
+ }),
2282
+ D && /* @__PURE__ */ p("div", {
2283
+ className: "modal d-block",
2284
+ tabIndex: -1,
2285
+ style: { background: "rgba(0,0,0,.5)" },
2286
+ children: /* @__PURE__ */ p("div", {
2287
+ className: "modal-dialog modal-dialog-centered",
2288
+ children: /* @__PURE__ */ m("div", {
2289
+ className: "modal-content",
2290
+ children: [
2291
+ /* @__PURE__ */ m("div", {
2292
+ className: "modal-header",
2293
+ children: [/* @__PURE__ */ m("h6", {
2294
+ className: "modal-title",
2295
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-check-circle me-2 text-success" }), "Restauração concluída"]
2296
+ }), /* @__PURE__ */ p("button", {
2297
+ className: "btn-close",
2298
+ onClick: () => O(null)
2299
+ })]
2300
+ }),
2301
+ /* @__PURE__ */ m("div", {
2302
+ className: "modal-body",
2303
+ children: [/* @__PURE__ */ p("p", {
2304
+ className: "mb-2",
2305
+ children: D.message
2306
+ }), D.restoredItems.length > 0 && /* @__PURE__ */ m("ul", {
2307
+ className: "list-unstyled small mb-0",
2308
+ children: [D.restoredItems.slice(0, 10).map((e) => /* @__PURE__ */ p("li", { children: /* @__PURE__ */ p("code", { children: e }) }, e)), D.restoredItems.length > 10 && /* @__PURE__ */ m("li", {
2309
+ className: "text-muted",
2310
+ children: [
2311
+ "... e mais ",
2312
+ D.restoredItems.length - 10,
2313
+ " item(ns)"
2314
+ ]
2315
+ })]
2316
+ })]
2317
+ }),
2318
+ /* @__PURE__ */ p("div", {
2319
+ className: "modal-footer",
2320
+ children: /* @__PURE__ */ p("button", {
2321
+ className: "btn btn-sm btn-secondary",
2322
+ onClick: () => O(null),
2323
+ children: "Fechar"
2324
+ })
2325
+ })
2326
+ ]
2327
+ })
2328
+ })
2114
2329
  })
2115
2330
  ]
2116
2331
  });
2117
2332
  }
2118
2333
  //#endregion
2119
2334
  //#region src/components/ImportDumpTab.tsx
2120
- function se() {
2121
- let e = I(), t = L(), n = D(), r = a(null), [i, s] = o("upload"), [c, l] = o(null), [u, d] = o(""), [f, h] = o(!1), g = () => {
2335
+ function ce() {
2336
+ let e = L(), t = R(), n = D(), r = a(null), [i, s] = o("upload"), [c, l] = o(null), [u, d] = o(""), [f, h] = o(!1), g = () => {
2122
2337
  i === "upload" && c ? e.mutate({ file: c }) : i === "storage" && u && t.mutate({
2123
2338
  storageType: "LOCAL",
2124
2339
  storagePath: u
@@ -2279,7 +2494,7 @@ function se() {
2279
2494
  "aria-hidden": !0
2280
2495
  }),
2281
2496
  "Falha na importacao: ",
2282
- X(y)
2497
+ Y(y)
2283
2498
  ]
2284
2499
  }),
2285
2500
  v && /* @__PURE__ */ m("div", {
@@ -2321,7 +2536,7 @@ function se() {
2321
2536
  }
2322
2537
  //#endregion
2323
2538
  //#region src/components/StorageBackupTab.tsx
2324
- function ce() {
2539
+ function le() {
2325
2540
  let e = j(), t = T(), n = t.data?.find((e) => e.name === "ORIGIN_STORAGE"), r = t.data?.find((e) => e.name === "OUTPUT_STORAGE"), i = e.isPending, [a, s] = o(!1);
2326
2541
  return /* @__PURE__ */ m("div", { children: [
2327
2542
  /* @__PURE__ */ m("div", {
@@ -2364,12 +2579,12 @@ function ce() {
2364
2579
  }),
2365
2580
  t.data && /* @__PURE__ */ m("div", {
2366
2581
  className: "d-flex flex-column gap-2",
2367
- children: [/* @__PURE__ */ p(le, {
2582
+ children: [/* @__PURE__ */ p(ue, {
2368
2583
  label: n?.label ?? "Storage de origem",
2369
2584
  configured: n?.configured,
2370
2585
  ok: n?.ok,
2371
2586
  message: n?.message
2372
- }), /* @__PURE__ */ p(le, {
2587
+ }), /* @__PURE__ */ p(ue, {
2373
2588
  label: r?.label ?? "Storage de destino",
2374
2589
  configured: r?.configured,
2375
2590
  ok: r?.ok,
@@ -2387,7 +2602,7 @@ function ce() {
2387
2602
  "aria-hidden": !0
2388
2603
  }),
2389
2604
  "Falha ao criar backup de storage: ",
2390
- X(e.error)
2605
+ Y(e.error)
2391
2606
  ]
2392
2607
  }),
2393
2608
  e.isSuccess && /* @__PURE__ */ m("div", {
@@ -2452,7 +2667,7 @@ function ce() {
2452
2667
  })
2453
2668
  ] });
2454
2669
  }
2455
- function le({ label: e, configured: t, ok: n, message: r }) {
2670
+ function ue({ label: e, configured: t, ok: n, message: r }) {
2456
2671
  return t === !1 ? /* @__PURE__ */ m("div", {
2457
2672
  className: "d-flex align-items-center gap-2 small text-muted",
2458
2673
  children: [/* @__PURE__ */ p("i", {
@@ -2473,13 +2688,13 @@ function le({ label: e, configured: t, ok: n, message: r }) {
2473
2688
  }
2474
2689
  //#endregion
2475
2690
  //#region src/hooks/useAutoTheme.ts
2476
- function ue() {
2691
+ function de() {
2477
2692
  return typeof document < "u" && document.documentElement.classList.contains("dark");
2478
2693
  }
2479
- function de(e) {
2480
- let [t, n] = o(ue), [i, a] = o(() => typeof window < "u" && window.matchMedia?.("(prefers-color-scheme: dark)")?.matches === !0);
2694
+ function fe(e) {
2695
+ let [t, n] = o(de), [i, a] = o(() => typeof window < "u" && window.matchMedia?.("(prefers-color-scheme: dark)")?.matches === !0);
2481
2696
  return r(() => {
2482
- let e = document.documentElement, t = new MutationObserver(() => n(ue()));
2697
+ let e = document.documentElement, t = new MutationObserver(() => n(de()));
2483
2698
  return t.observe(e, {
2484
2699
  attributes: !0,
2485
2700
  attributeFilter: ["class"]
@@ -2492,8 +2707,8 @@ function de(e) {
2492
2707
  }
2493
2708
  //#endregion
2494
2709
  //#region src/components/MinivaultModule.tsx
2495
- function fe(e) {
2496
- let { companyAcronym: t = "Minivault", theme: n, refetchIntervalMs: r = 15e3, storageType: i = "LOCAL", ...a } = e, l = de(n), [u] = o(() => new s({ defaultOptions: { queries: {
2710
+ function pe(e) {
2711
+ let { companyAcronym: t = "Minivault", theme: n, refetchIntervalMs: r = 15e3, storageType: i = "LOCAL", ...a } = e, l = fe(n), [u] = o(() => new s({ defaultOptions: { queries: {
2497
2712
  refetchInterval: r,
2498
2713
  retry: 1
2499
2714
  } } }));
@@ -2504,15 +2719,15 @@ function fe(e) {
2504
2719
  children: /* @__PURE__ */ m("div", {
2505
2720
  className: "minivault-module h-full w-full overflow-auto",
2506
2721
  "data-minivault-theme": l,
2507
- children: [/* @__PURE__ */ p(pe, {
2722
+ children: [/* @__PURE__ */ p(me, {
2508
2723
  companyAcronym: t,
2509
2724
  theme: l
2510
- }), /* @__PURE__ */ p(me, { storageType: i })]
2725
+ }), /* @__PURE__ */ p(he, { storageType: i })]
2511
2726
  })
2512
2727
  })
2513
2728
  });
2514
2729
  }
2515
- function pe({ companyAcronym: e, theme: t }) {
2730
+ function me({ companyAcronym: e, theme: t }) {
2516
2731
  return /* @__PURE__ */ m("div", {
2517
2732
  className: "d-flex align-items-center justify-content-between flex-wrap gap-2 px-3 py-2 border-bottom",
2518
2733
  style: {
@@ -2541,7 +2756,7 @@ function pe({ companyAcronym: e, theme: t }) {
2541
2756
  })]
2542
2757
  });
2543
2758
  }
2544
- function me({ storageType: e }) {
2759
+ function he({ storageType: e }) {
2545
2760
  let [t, n] = o("backups");
2546
2761
  return /* @__PURE__ */ m("div", {
2547
2762
  className: "p-3",
@@ -2623,10 +2838,10 @@ function me({ storageType: e }) {
2623
2838
  })
2624
2839
  ]
2625
2840
  }),
2626
- t === "backups" && /* @__PURE__ */ p(Z, {}),
2627
- t === "create" && /* @__PURE__ */ p(te, {}),
2628
- t === "createStorage" && /* @__PURE__ */ p(ce, {}),
2629
- t === "import" && /* @__PURE__ */ p(se, {}),
2841
+ t === "backups" && /* @__PURE__ */ p(X, {}),
2842
+ t === "create" && /* @__PURE__ */ p(ne, {}),
2843
+ t === "createStorage" && /* @__PURE__ */ p(le, {}),
2844
+ t === "import" && /* @__PURE__ */ p(ce, {}),
2630
2845
  t === "storage" && /* @__PURE__ */ m("div", {
2631
2846
  className: "row g-3",
2632
2847
  children: [/* @__PURE__ */ p("div", {
@@ -2645,18 +2860,18 @@ function me({ storageType: e }) {
2645
2860
  })
2646
2861
  })]
2647
2862
  }),
2648
- t === "diagnostics" && /* @__PURE__ */ p(ie, {})
2863
+ t === "diagnostics" && /* @__PURE__ */ p(ae, {})
2649
2864
  ]
2650
2865
  });
2651
2866
  }
2652
2867
  //#endregion
2653
2868
  //#region src/components/CredentialsFields.tsx
2654
- var he = [
2869
+ var ge = [
2655
2870
  "postgresql",
2656
2871
  "mysql",
2657
2872
  "sqlserver"
2658
2873
  ];
2659
- function ge() {
2874
+ function _e() {
2660
2875
  return {
2661
2876
  host: "localhost",
2662
2877
  port: 5432,
@@ -2666,19 +2881,19 @@ function ge() {
2666
2881
  databaseType: "postgresql"
2667
2882
  };
2668
2883
  }
2669
- function _e(e) {
2884
+ function ve(e) {
2670
2885
  return e === "postgresql" || e === "postgres" ? 5432 : e === "mysql" ? 3306 : 1433;
2671
2886
  }
2672
- function ve({ value: e, onChange: t, onValidatedChange: n }) {
2887
+ function ye({ value: e, onChange: t, onValidatedChange: n }) {
2673
2888
  let r = {
2674
- ...ge(),
2889
+ ..._e(),
2675
2890
  ...e
2676
2891
  }, i = (e) => {
2677
2892
  let n = {
2678
2893
  ...r,
2679
2894
  databaseType: e
2680
2895
  };
2681
- (r.port === _e(r.databaseType) || !r.port) && (n.port = _e(e)), t(n);
2896
+ (r.port === ve(r.databaseType) || !r.port) && (n.port = ve(e)), t(n);
2682
2897
  }, a = (e) => {
2683
2898
  let i = {
2684
2899
  ...r,
@@ -2700,7 +2915,7 @@ function ve({ value: e, onChange: t, onValidatedChange: n }) {
2700
2915
  className: "form-select",
2701
2916
  value: r.databaseType,
2702
2917
  onChange: (e) => i(e.target.value),
2703
- children: he.map((e) => /* @__PURE__ */ p("option", {
2918
+ children: ge.map((e) => /* @__PURE__ */ p("option", {
2704
2919
  value: e,
2705
2920
  children: W[e] ?? e
2706
2921
  }, e))
@@ -2774,4 +2989,4 @@ function ve({ value: e, onChange: t, onValidatedChange: n }) {
2774
2989
  });
2775
2990
  }
2776
2991
  //#endregion
2777
- export { Z as BackupsTab, te as CreateBackupTab, ve as CredentialsFields, W as DATABASE_TYPE_LABELS, J as DatabaseBanner, ie as DiagnosticsTab, se as ImportDumpTab, g as MinivaultApi, h as MinivaultApiError, y as MinivaultApiProvider, fe as MinivaultModule, Y as RestoreModal, U as STATUS_BADGE, H as STATUS_LABELS, q as StatusBadge, ce as StorageBackupTab, $ as StorageExplorerTab, V as formatDate, B as formatFileSize, E as useBackups, j as useCreateBackup, D as useDbInfo, A as useDbRelationships, k as useDbTableDetail, O as useDbTables, N as useDeleteBackup, T as useDiagnostics, F as useDownloadBackup, I as useImportDump, L as useImportFromStorage, b as useMinivaultApi, M as useRestoreBackup };
2992
+ export { X as BackupsTab, ne as CreateBackupTab, ye as CredentialsFields, W as DATABASE_TYPE_LABELS, J as DatabaseBanner, ae as DiagnosticsTab, ce as ImportDumpTab, g as MinivaultApi, h as MinivaultApiError, y as MinivaultApiProvider, pe as MinivaultModule, te as RestoreModal, ee as STATUS_BADGE, U as STATUS_LABELS, q as StatusBadge, le as StorageBackupTab, $ as StorageExplorerTab, H as formatDate, V as formatFileSize, E as useBackups, j as useCreateBackup, D as useDbInfo, A as useDbRelationships, k as useDbTableDetail, O as useDbTables, N as useDeleteBackup, T as useDiagnostics, I as useDownloadBackup, L as useImportDump, R as useImportFromStorage, b as useMinivaultApi, M as useRestoreBackup };
@@ -197,6 +197,29 @@ export interface StorageZipRequest {
197
197
  secretKey?: string;
198
198
  pathStyleEnabled?: boolean;
199
199
  }
200
+ /**
201
+ * Restaura arquivos/pastas do storage (normalmente o destino) de volta para o
202
+ * storage de origem, preservando pastas e extraindo arquivos .zip.
203
+ */
204
+ export interface RestoreStorageRequest {
205
+ keys: string[];
206
+ storage?: StorageTarget;
207
+ type?: string;
208
+ endpoint?: string;
209
+ bucketName?: string;
210
+ accessKey?: string;
211
+ secretKey?: string;
212
+ region?: string;
213
+ localPath?: string;
214
+ pathStyleEnabled?: boolean;
215
+ /** Storage de destino da restauração (origin). Quando ausente, usa ORIGIN_STORAGE_* do servidor. */
216
+ origin?: OriginStorageConfig;
217
+ }
218
+ export interface StorageRestoreResult {
219
+ restoredCount: number;
220
+ restoredItems: string[];
221
+ message: string;
222
+ }
200
223
  export interface ApiErrorBody {
201
224
  timestamp?: string;
202
225
  status?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v1ct0rbr/minivault-web",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Módulo independente de gerenciamento de backups (minivault). Consumível como pacote npm em qualquer app React. Cliente do minivault REST API (acesso tipicamente via proxy autenticado).",
5
5
  "author": "Victor Queiroga (https://www.linkedin.com/in/victor-queiroga)",
6
6
  "license": "MIT",