@v1ct0rbr/minivault-web 0.7.0 → 0.8.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.
@@ -33,7 +33,7 @@ export declare class MinivaultApi {
33
33
  private request;
34
34
  listBackups(page?: number, size?: number): Promise<PageResponse<Backup>>;
35
35
  getBackup(id: number): Promise<Backup>;
36
- createBackup(database?: DatabaseCredentials, originStorage?: OriginStorageConfig, dumpOptions?: DumpOptions, backupType?: BackupType): Promise<Backup>;
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
39
  verifyBackup(id: number): Promise<VerifyResult>;
@@ -15,6 +15,7 @@ export declare function useCreateBackup(): import('@tanstack/react-query').UseMu
15
15
  originStorage?: OriginStorageConfig;
16
16
  dumpOptions?: DumpOptions;
17
17
  backupType?: BackupType;
18
+ scheduled?: boolean;
18
19
  }, unknown>;
19
20
  export declare function useRestoreBackup(): import('@tanstack/react-query').UseMutationResult<void, Error, {
20
21
  id: number;
@@ -56,11 +56,11 @@ var h = class extends Error {
56
56
  getBackup(e) {
57
57
  return this.request(`/api/backups/${e}`);
58
58
  }
59
- createBackup(e, t, n, r) {
60
- let i = {};
61
- return r && (i.backupType = r), e && (i.database = e), t && (i.originStorage = t), n && (i.dumpOptions = n), this.request("/api/backups", {
59
+ createBackup(e, t, n, r, i) {
60
+ let a = {};
61
+ return r && (a.backupType = r), i && (a.scheduled = !0), e && (a.database = e), t && (a.originStorage = t), n && (a.dumpOptions = n), this.request("/api/backups", {
62
62
  method: "POST",
63
- body: JSON.stringify(i)
63
+ body: JSON.stringify(a)
64
64
  });
65
65
  }
66
66
  restoreBackup(e, t, n) {
@@ -298,7 +298,7 @@ function A(e = !0) {
298
298
  function j() {
299
299
  let e = b(), t = d();
300
300
  return l({
301
- mutationFn: (t) => e.createBackup(t.database, t.originStorage, t.dumpOptions, t.backupType),
301
+ mutationFn: (t) => e.createBackup(t.database, t.originStorage, t.dumpOptions, t.backupType, t.scheduled),
302
302
  onSuccess: () => t.invalidateQueries({ queryKey: S.all })
303
303
  });
304
304
  }
@@ -828,10 +828,21 @@ function Z() {
828
828
  className: "text-truncate",
829
829
  style: { maxWidth: 260 },
830
830
  title: e.filename,
831
- children: [/* @__PURE__ */ p("i", {
832
- className: "bi bi-archive me-1 text-primary",
833
- "aria-hidden": !0
834
- }), e.filename]
831
+ children: [
832
+ /* @__PURE__ */ p("i", {
833
+ className: "bi bi-archive me-1 text-primary",
834
+ "aria-hidden": !0
835
+ }),
836
+ e.filename,
837
+ e.scheduled && /* @__PURE__ */ m("span", {
838
+ className: "badge text-bg-info ms-2",
839
+ title: "O scheduler re-executa este backup automaticamente no horário configurado",
840
+ children: [/* @__PURE__ */ p("i", {
841
+ className: "bi bi-clock-history me-1",
842
+ "aria-hidden": !0
843
+ }), "agendado"]
844
+ })
845
+ ]
835
846
  }),
836
847
  /* @__PURE__ */ p("td", { children: e.backupType ? /* @__PURE__ */ p("span", {
837
848
  className: `badge ${K[e.backupType] ?? "text-bg-secondary"}`,
@@ -1055,15 +1066,15 @@ function te() {
1055
1066
  includeIndexes: !0,
1056
1067
  includeConstraints: !0,
1057
1068
  includeRelatedTables: !1
1058
- }), [l, u] = o(() => /* @__PURE__ */ new Set()), [d, f] = o(null), [h, g] = o({}), [_, v] = o(""), y = k(d, t.data?.configured), b = i(() => new Set((t.data?.exportExcludedTables ?? []).map(re)), [t.data?.exportExcludedTables]), x = i(() => {
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(() => {
1059
1070
  let e = n.data ?? [], t = _.trim().toLowerCase();
1060
1071
  return t ? e.filter((e) => e.fullName.toLowerCase().includes(t)) : e;
1061
- }, [n.data, _]), S = i(() => Object.values(h).reduce((e, t) => e + t.length, 0), [h]), C = (e) => {
1072
+ }, [n.data, _]), w = i(() => Object.values(h).reduce((e, t) => e + t.length, 0), [h]), T = (e) => {
1062
1073
  u((t) => {
1063
1074
  let n = new Set(t);
1064
1075
  return n.has(e) ? n.delete(e) : n.add(e), n;
1065
1076
  });
1066
- }, w = (e, t) => {
1077
+ }, E = (e, t) => {
1067
1078
  g((n) => {
1068
1079
  let r = n[e] ?? [], i = r.includes(t) ? r.filter((e) => e !== t) : [...r, t];
1069
1080
  return {
@@ -1071,7 +1082,7 @@ function te() {
1071
1082
  [e]: i
1072
1083
  };
1073
1084
  });
1074
- }, T = () => {
1085
+ }, A = () => {
1075
1086
  let t;
1076
1087
  if (r) {
1077
1088
  t = { ...s }, l.size > 0 && (t.tables = [...l]);
@@ -1082,9 +1093,10 @@ function te() {
1082
1093
  }
1083
1094
  e.mutate({
1084
1095
  backupType: "DATABASE",
1085
- dumpOptions: t
1096
+ dumpOptions: t,
1097
+ scheduled: y
1086
1098
  });
1087
- }, E = e.isPending, A = t.data?.configured && !E;
1099
+ }, M = e.isPending, N = t.data?.configured && !M;
1088
1100
  return /* @__PURE__ */ m("div", { children: [
1089
1101
  /* @__PURE__ */ m("div", {
1090
1102
  className: "mb-3",
@@ -1115,7 +1127,7 @@ function te() {
1115
1127
  "aria-hidden": !0
1116
1128
  }),
1117
1129
  "Tabelas do banco (",
1118
- n.data?.filter((e) => !b.has(e.fullName)).length ?? 0,
1130
+ n.data?.filter((e) => !S.has(e.fullName)).length ?? 0,
1119
1131
  " disponíveis)"
1120
1132
  ]
1121
1133
  }), /* @__PURE__ */ m("div", {
@@ -1158,7 +1170,7 @@ function te() {
1158
1170
  X(n.error)
1159
1171
  ]
1160
1172
  }),
1161
- x.length === 0 && !n.isLoading && /* @__PURE__ */ p("div", {
1173
+ C.length === 0 && !n.isLoading && /* @__PURE__ */ p("div", {
1162
1174
  className: "p-3 text-muted small",
1163
1175
  children: "Nenhuma tabela encontrada."
1164
1176
  }),
@@ -1171,16 +1183,16 @@ function te() {
1171
1183
  maxHeight: 420,
1172
1184
  overflow: "auto"
1173
1185
  },
1174
- children: x.map((e) => /* @__PURE__ */ p(ne, {
1186
+ children: C.map((e) => /* @__PURE__ */ p(ne, {
1175
1187
  table: e,
1176
- disabled: b.has(e.fullName),
1188
+ disabled: S.has(e.fullName),
1177
1189
  selected: l.has(e.fullName),
1178
1190
  expanded: d === e.fullName,
1179
1191
  excluded: h[e.fullName] ?? [],
1180
- onToggleTable: () => C(e.fullName),
1192
+ onToggleTable: () => T(e.fullName),
1181
1193
  onToggleExpand: () => f(d === e.fullName ? null : e.fullName),
1182
- onToggleColumn: (t) => w(e.fullName, t),
1183
- detail: d === e.fullName ? y : void 0
1194
+ onToggleColumn: (t) => E(e.fullName, t),
1195
+ detail: d === e.fullName ? x : void 0
1184
1196
  }, e.fullName))
1185
1197
  }),
1186
1198
  /* @__PURE__ */ m("div", {
@@ -1191,14 +1203,14 @@ function te() {
1191
1203
  className: "bi bi-info-circle me-1",
1192
1204
  "aria-hidden": !0
1193
1205
  }), "Deixe tudo desmarcado para incluir todas as tabelas (exceto as bloqueadas por segurança)."]
1194
- }), S > 0 && s.format !== "plain" && /* @__PURE__ */ m("span", {
1206
+ }), w > 0 && s.format !== "plain" && /* @__PURE__ */ m("span", {
1195
1207
  className: "badge text-bg-warning ms-auto text-wrap text-start",
1196
1208
  children: [
1197
1209
  /* @__PURE__ */ p("i", {
1198
1210
  className: "bi bi-exclamation-triangle me-1",
1199
1211
  "aria-hidden": !0
1200
1212
  }),
1201
- S,
1213
+ w,
1202
1214
  " coluna(s) marcada(s) serão nulificadas apenas com formato Plain SQL (texto)"
1203
1215
  ]
1204
1216
  })]
@@ -1349,15 +1361,36 @@ function te() {
1349
1361
  "). O progresso é exibido na aba Backups."
1350
1362
  ]
1351
1363
  }),
1364
+ /* @__PURE__ */ m("div", {
1365
+ className: "form-check form-switch mb-3 d-flex align-items-center gap-2",
1366
+ children: [/* @__PURE__ */ p("input", {
1367
+ className: "form-check-input",
1368
+ type: "checkbox",
1369
+ role: "switch",
1370
+ id: "minivault-scheduled",
1371
+ checked: y,
1372
+ onChange: (e) => b(e.target.checked)
1373
+ }), /* @__PURE__ */ m("label", {
1374
+ className: "form-check-label",
1375
+ htmlFor: "minivault-scheduled",
1376
+ children: ["Executar em agendamento", /* @__PURE__ */ m("span", {
1377
+ className: "text-muted small ms-2",
1378
+ children: [/* @__PURE__ */ p("i", {
1379
+ className: "bi bi-clock-history me-1",
1380
+ "aria-hidden": !0
1381
+ }), "O scheduler re-executa este backup automaticamente no horário configurado."]
1382
+ })]
1383
+ })]
1384
+ }),
1352
1385
  /* @__PURE__ */ p("div", {
1353
1386
  className: "d-flex justify-content-end",
1354
1387
  children: /* @__PURE__ */ m("button", {
1355
1388
  type: "button",
1356
1389
  className: "btn btn-primary",
1357
- onClick: T,
1358
- disabled: !A,
1390
+ onClick: A,
1391
+ disabled: !N,
1359
1392
  children: [
1360
- E && /* @__PURE__ */ p("span", {
1393
+ M && /* @__PURE__ */ p("span", {
1361
1394
  className: "spinner-border spinner-border-sm me-2",
1362
1395
  "aria-hidden": !0
1363
1396
  }),
@@ -1780,7 +1813,7 @@ function $({ target: e = "origin", title: n = "Explorador de Storage", storageTy
1780
1813
  }, t))]
1781
1814
  })
1782
1815
  }),
1783
- R ? /* @__PURE__ */ m("div", {
1816
+ R || N ? /* @__PURE__ */ m("div", {
1784
1817
  className: "text-center py-5",
1785
1818
  children: [/* @__PURE__ */ p("div", {
1786
1819
  className: "spinner-border text-primary",
@@ -2289,7 +2322,7 @@ function se() {
2289
2322
  //#endregion
2290
2323
  //#region src/components/StorageBackupTab.tsx
2291
2324
  function ce() {
2292
- 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;
2325
+ 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);
2293
2326
  return /* @__PURE__ */ m("div", { children: [
2294
2327
  /* @__PURE__ */ m("div", {
2295
2328
  className: "mb-3",
@@ -2371,13 +2404,37 @@ function ce() {
2371
2404
  "). O progresso é exibido na aba Backups."
2372
2405
  ]
2373
2406
  }),
2407
+ /* @__PURE__ */ m("div", {
2408
+ className: "form-check form-switch mb-3 d-flex align-items-center gap-2",
2409
+ children: [/* @__PURE__ */ p("input", {
2410
+ className: "form-check-input",
2411
+ type: "checkbox",
2412
+ role: "switch",
2413
+ id: "minivault-storage-scheduled",
2414
+ checked: a,
2415
+ onChange: (e) => s(e.target.checked)
2416
+ }), /* @__PURE__ */ m("label", {
2417
+ className: "form-check-label",
2418
+ htmlFor: "minivault-storage-scheduled",
2419
+ children: ["Executar em agendamento", /* @__PURE__ */ m("span", {
2420
+ className: "text-muted small ms-2",
2421
+ children: [/* @__PURE__ */ p("i", {
2422
+ className: "bi bi-clock-history me-1",
2423
+ "aria-hidden": !0
2424
+ }), "O scheduler re-executa este backup automaticamente no horário configurado."]
2425
+ })]
2426
+ })]
2427
+ }),
2374
2428
  /* @__PURE__ */ p("div", {
2375
2429
  className: "d-flex justify-content-end",
2376
2430
  children: /* @__PURE__ */ m("button", {
2377
2431
  type: "button",
2378
2432
  className: "btn btn-primary",
2379
2433
  onClick: () => {
2380
- e.mutate({ backupType: "STORAGE" });
2434
+ e.mutate({
2435
+ backupType: "STORAGE",
2436
+ scheduled: a
2437
+ });
2381
2438
  },
2382
2439
  disabled: i || t.data != null && n?.configured === !1,
2383
2440
  children: [
@@ -15,6 +15,8 @@ export interface Backup {
15
15
  errorMessage: string | null;
16
16
  createdAt: string | null;
17
17
  completedAt: string | null;
18
+ /** Quando true, o scheduler re-executa este backup (definição) no agendamento. */
19
+ scheduled: boolean;
18
20
  }
19
21
  export interface VerifyResult {
20
22
  valid: boolean;
@@ -72,6 +74,8 @@ export interface DumpOptions {
72
74
  export interface BackupRequest {
73
75
  /** Tipo do backup: DATABASE (apenas banco), STORAGE (apenas arquivos) ou FULL (padrão legado). */
74
76
  backupType?: BackupType;
77
+ /** Quando true, o scheduler re-executa este backup no agendamento. */
78
+ scheduled?: boolean;
75
79
  /** Opcional: usa o banco padrão configurado no servidor (env) quando ausente. */
76
80
  database?: DatabaseCredentials;
77
81
  originStorage?: OriginStorageConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v1ct0rbr/minivault-web",
3
- "version": "0.7.0",
3
+ "version": "0.8.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",