@v1ct0rbr/minivault-web 0.1.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.
@@ -0,0 +1,1879 @@
1
+ import { createContext as e, useCallback as t, useContext as n, useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
2
+ import { QueryClient as s, QueryClientProvider as c, useMutation as l, useQuery as u, useQueryClient as d } from "@tanstack/react-query";
3
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
4
+ //#region src/api/MinivaultApi.ts
5
+ var h = class extends Error {
6
+ status;
7
+ body;
8
+ constructor(e, t, n) {
9
+ super(e), this.name = "MinivaultApiError", this.status = t, this.body = n;
10
+ }
11
+ }, g = class {
12
+ baseUrl;
13
+ token;
14
+ getToken;
15
+ fetchFn;
16
+ timeoutMs;
17
+ constructor(e) {
18
+ this.baseUrl = e.baseUrl.replace(/\/+$/, ""), this.token = e.token, this.getToken = e.getToken, this.fetchFn = e.fetch ?? globalThis.fetch.bind(globalThis), this.timeoutMs = e.timeoutMs ?? 3e4;
19
+ }
20
+ async resolveToken() {
21
+ return this.token ? this.token : this.getToken ? this.getToken() : null;
22
+ }
23
+ async request(e, t = {}) {
24
+ let n = await this.resolveToken(), r = typeof FormData < "u" && t.body instanceof FormData, i = {
25
+ Accept: "application/json",
26
+ ...t.headers
27
+ };
28
+ r || (i["Content-Type"] = i["Content-Type"] ?? "application/json"), n && (i.Authorization = `Bearer ${n}`);
29
+ let a = new AbortController(), o = setTimeout(() => a.abort(), this.timeoutMs);
30
+ try {
31
+ let n = await this.fetchFn(`${this.baseUrl}${e}`, {
32
+ ...t,
33
+ headers: i,
34
+ signal: a.signal
35
+ });
36
+ if (!n.ok) {
37
+ let r = await n.text().catch(() => void 0) ?? "";
38
+ throw new h(`Minivault API ${t.method ?? "GET"} ${e} falhou (HTTP ${n.status})${r ? `: ${_(r)}` : ""}`, n.status, r);
39
+ }
40
+ return await n.json();
41
+ } catch (t) {
42
+ throw t instanceof h || console.error(`[minivault-web] erro em ${this.baseUrl}${e}`, t), t;
43
+ } finally {
44
+ clearTimeout(o);
45
+ }
46
+ }
47
+ listBackups(e = 0, t = 10) {
48
+ let n = new URLSearchParams({
49
+ page: String(e),
50
+ size: String(t)
51
+ });
52
+ return this.request(`/api/backups?${n.toString()}`);
53
+ }
54
+ getBackup(e) {
55
+ return this.request(`/api/backups/${e}`);
56
+ }
57
+ createBackup(e, t, n) {
58
+ let r = { database: e };
59
+ return t && (r.originStorage = t), n && (r.dumpOptions = n), this.request("/api/backups", {
60
+ method: "POST",
61
+ body: JSON.stringify(r)
62
+ });
63
+ }
64
+ restoreBackup(e, t, n) {
65
+ let r = n ? {
66
+ database: t,
67
+ originStorage: n
68
+ } : { database: t };
69
+ return this.request(`/api/backups/${e}/restore`, {
70
+ method: "POST",
71
+ body: JSON.stringify(r)
72
+ });
73
+ }
74
+ deleteBackup(e) {
75
+ return this.request(`/api/backups/${e}`, { method: "DELETE" });
76
+ }
77
+ verifyBackup(e) {
78
+ return this.request(`/api/backups/${e}/verify`, { method: "POST" });
79
+ }
80
+ async downloadBackup(e) {
81
+ let t = await this.resolveToken(), n = { Accept: "application/octet-stream" };
82
+ t && (n.Authorization = `Bearer ${t}`);
83
+ let r = new AbortController(), i = setTimeout(() => r.abort(), this.timeoutMs);
84
+ try {
85
+ let t = await this.fetchFn(`${this.baseUrl}/api/backups/${e}/download`, {
86
+ method: "GET",
87
+ headers: n,
88
+ signal: r.signal
89
+ });
90
+ if (!t.ok) throw new h(`Minivault API GET /api/backups/${e}/download falhou (HTTP ${t.status})`, t.status);
91
+ return await t.blob();
92
+ } finally {
93
+ clearTimeout(i);
94
+ }
95
+ }
96
+ async importDump(e, t) {
97
+ let n = await this.resolveToken(), r = new FormData();
98
+ r.append("file", e), r.append("database", new Blob([JSON.stringify(t)], { type: "application/json" }));
99
+ let i = {};
100
+ n && (i.Authorization = `Bearer ${n}`);
101
+ let a = new AbortController(), o = setTimeout(() => a.abort(), this.timeoutMs);
102
+ try {
103
+ let e = await this.fetchFn(`${this.baseUrl}/api/backups/import`, {
104
+ method: "POST",
105
+ headers: i,
106
+ body: r,
107
+ signal: a.signal
108
+ }), t = await e.text();
109
+ if (!e.ok) throw new h(`Minivault API POST /api/backups/import falhou (HTTP ${e.status})${t ? `: ${_(t)}` : ""}`, e.status, t);
110
+ return JSON.parse(t || "{}");
111
+ } catch (e) {
112
+ throw e instanceof h || console.error(`[minivault-web] erro em ${this.baseUrl}/api/backups/import`, e), e;
113
+ } finally {
114
+ clearTimeout(o);
115
+ }
116
+ }
117
+ async importFromStorage(e, t, n, r) {
118
+ let i = {
119
+ storageType: e,
120
+ storagePath: t,
121
+ database: n
122
+ };
123
+ return r && (i.storageConfig = r), this.request("/api/backups/import-from-storage", {
124
+ method: "POST",
125
+ body: JSON.stringify(i)
126
+ });
127
+ }
128
+ listStorageFiles(e, t, n) {
129
+ let r = new URLSearchParams({ type: e });
130
+ return t && r.set("prefix", t), n && (n.endpoint && r.set("endpoint", n.endpoint), n.bucketName && r.set("bucketName", n.bucketName), n.accessKey && r.set("accessKey", n.accessKey), n.secretKey && r.set("secretKey", n.secretKey), n.region && r.set("region", n.region), n.pathStyleEnabled && r.set("pathStyleEnabled", "true"), n.localPath && r.set("localPath", n.localPath)), this.request(`/api/storage/files?${r.toString()}`);
131
+ }
132
+ async downloadStorageFile(e, t, n) {
133
+ let r = await this.resolveToken(), i = new URLSearchParams({
134
+ key: e,
135
+ type: t
136
+ });
137
+ n && (n.endpoint && i.set("endpoint", n.endpoint), n.bucketName && i.set("bucketName", n.bucketName), n.accessKey && i.set("accessKey", n.accessKey), n.secretKey && i.set("secretKey", n.secretKey), n.region && i.set("region", n.region), n.pathStyleEnabled && i.set("pathStyleEnabled", "true"), n.localPath && i.set("localPath", n.localPath));
138
+ let a = { Accept: "application/octet-stream" };
139
+ r && (a.Authorization = `Bearer ${r}`);
140
+ let o = new AbortController(), s = setTimeout(() => o.abort(), this.timeoutMs);
141
+ try {
142
+ let e = await this.fetchFn(`${this.baseUrl}/api/storage/files/download?${i.toString()}`, {
143
+ method: "GET",
144
+ headers: a,
145
+ signal: o.signal
146
+ });
147
+ if (!e.ok) throw new h(`Minivault API GET /api/storage/files/download falhou (HTTP ${e.status})`, e.status);
148
+ return await e.blob();
149
+ } finally {
150
+ clearTimeout(s);
151
+ }
152
+ }
153
+ async deleteStorageFile(e, t, n) {
154
+ let r = new URLSearchParams({
155
+ key: e,
156
+ type: t
157
+ });
158
+ n && (n.endpoint && r.set("endpoint", n.endpoint), n.bucketName && r.set("bucketName", n.bucketName), n.accessKey && r.set("accessKey", n.accessKey), n.secretKey && r.set("secretKey", n.secretKey), n.region && r.set("region", n.region), n.pathStyleEnabled && r.set("pathStyleEnabled", "true"), n.localPath && r.set("localPath", n.localPath)), await this.request(`/api/storage/files?${r.toString()}`, { method: "DELETE" });
159
+ }
160
+ };
161
+ function _(e) {
162
+ try {
163
+ let t = JSON.parse(e);
164
+ if (t.error) return t.error;
165
+ } catch {}
166
+ return e.slice(0, 300);
167
+ }
168
+ //#endregion
169
+ //#region src/components/MinivaultApiProvider.tsx
170
+ var v = e(null);
171
+ function y({ children: e, ...t }) {
172
+ let n = i(() => new g(t), [
173
+ t.baseUrl,
174
+ t.token,
175
+ t.getToken,
176
+ t.fetch
177
+ ]);
178
+ return /* @__PURE__ */ p(v.Provider, {
179
+ value: n,
180
+ children: e
181
+ });
182
+ }
183
+ function b() {
184
+ let e = n(v);
185
+ if (!e) throw Error("useMinivaultApi deve ser usado dentro de <MinivaultApiProvider>");
186
+ return e;
187
+ }
188
+ function x() {
189
+ return n(v);
190
+ }
191
+ //#endregion
192
+ //#region src/hooks/useBackups.ts
193
+ var S = { all: ["minivault", "backups"] };
194
+ function C(e = 0, t = 10, n = !0) {
195
+ let r = x();
196
+ return u({
197
+ queryKey: [
198
+ ...S.all,
199
+ e,
200
+ t
201
+ ],
202
+ queryFn: () => r.listBackups(e, t),
203
+ enabled: n && !!r
204
+ });
205
+ }
206
+ function w() {
207
+ let e = b(), t = d();
208
+ return l({
209
+ mutationFn: (t) => e.createBackup(t.database, t.originStorage, t.dumpOptions),
210
+ onSuccess: () => t.invalidateQueries({ queryKey: S.all })
211
+ });
212
+ }
213
+ function T() {
214
+ let e = b(), t = d();
215
+ return l({
216
+ mutationFn: (t) => e.restoreBackup(t.id, t.database, t.originStorage),
217
+ onSuccess: () => t.invalidateQueries({ queryKey: S.all })
218
+ });
219
+ }
220
+ function E() {
221
+ let e = b(), t = d();
222
+ return l({
223
+ mutationFn: (t) => e.deleteBackup(t),
224
+ onSuccess: () => t.invalidateQueries({ queryKey: S.all })
225
+ });
226
+ }
227
+ function D() {
228
+ let e = b(), t = d();
229
+ return l({
230
+ mutationFn: (t) => e.verifyBackup(t),
231
+ onSuccess: () => t.invalidateQueries({ queryKey: S.all })
232
+ });
233
+ }
234
+ function O() {
235
+ let e = b();
236
+ return l({ mutationFn: (t) => e.downloadBackup(t.id) });
237
+ }
238
+ function k() {
239
+ let e = b();
240
+ return l({ mutationFn: (t) => e.importDump(t.file, t.database) });
241
+ }
242
+ function A() {
243
+ let e = b();
244
+ return l({ mutationFn: (t) => e.importFromStorage(t.storageType, t.storagePath, t.database, t.storageConfig) });
245
+ }
246
+ //#endregion
247
+ //#region src/utils/format.ts
248
+ var j = new Intl.DateTimeFormat("pt-BR", {
249
+ day: "2-digit",
250
+ month: "2-digit",
251
+ year: "numeric",
252
+ hour: "2-digit",
253
+ minute: "2-digit"
254
+ }), M = [
255
+ "B",
256
+ "KB",
257
+ "MB",
258
+ "GB",
259
+ "TB"
260
+ ];
261
+ function N(e) {
262
+ if (e == null || e < 0) return "—";
263
+ if (e < 1024) return `${e} B`;
264
+ let t = e, n = 0;
265
+ for (; t >= 1024 && n < M.length - 1;) t /= 1024, n += 1;
266
+ return `${Number.isInteger(t) ? t : Number(t.toFixed(1))} ${M[n]}`;
267
+ }
268
+ function P(e) {
269
+ if (!e) return "—";
270
+ let t = new Date(e);
271
+ return Number.isNaN(t.getTime()) ? "—" : j.format(t);
272
+ }
273
+ var F = {
274
+ PENDING: "Pendente",
275
+ IN_PROGRESS: "Em andamento",
276
+ COMPLETED: "Concluído",
277
+ FAILED: "Falhou",
278
+ RESTORING: "Restaurando",
279
+ RESTORED: "Restaurado",
280
+ RESTORE_FAILED: "Falha na restauração"
281
+ }, I = {
282
+ PENDING: "text-bg-secondary",
283
+ IN_PROGRESS: "text-bg-primary",
284
+ COMPLETED: "text-bg-success",
285
+ FAILED: "text-bg-danger",
286
+ RESTORING: "text-bg-warning",
287
+ RESTORED: "text-bg-info",
288
+ RESTORE_FAILED: "text-bg-danger"
289
+ }, L = {
290
+ postgresql: "PostgreSQL",
291
+ postgres: "PostgreSQL",
292
+ mysql: "MySQL",
293
+ sqlserver: "SQL Server",
294
+ mssql: "SQL Server"
295
+ };
296
+ //#endregion
297
+ //#region src/components/StatusBadge.tsx
298
+ function R({ status: e }) {
299
+ let t = I[e] ?? "text-bg-secondary", n = F[e] ?? e;
300
+ return /* @__PURE__ */ p("span", {
301
+ className: `badge rounded-pill ${t}`,
302
+ children: n
303
+ });
304
+ }
305
+ //#endregion
306
+ //#region src/components/CredentialsFields.tsx
307
+ var z = [
308
+ "postgresql",
309
+ "mysql",
310
+ "sqlserver"
311
+ ];
312
+ function B() {
313
+ return {
314
+ host: "localhost",
315
+ port: 5432,
316
+ databaseName: "",
317
+ username: "",
318
+ password: "",
319
+ databaseType: "postgresql"
320
+ };
321
+ }
322
+ function V(e) {
323
+ return e === "postgresql" || e === "postgres" ? 5432 : e === "mysql" ? 3306 : 1433;
324
+ }
325
+ function H({ value: e, onChange: t, onValidatedChange: n }) {
326
+ let r = {
327
+ ...B(),
328
+ ...e
329
+ }, i = (e) => {
330
+ let n = {
331
+ ...r,
332
+ databaseType: e
333
+ };
334
+ (r.port === V(r.databaseType) || !r.port) && (n.port = V(e)), t(n);
335
+ }, a = (e) => {
336
+ let i = {
337
+ ...r,
338
+ ...e
339
+ };
340
+ t(i);
341
+ let a = !!(i.host.trim() && i.port > 0 && i.databaseName.trim() && i.username.trim() && i.password.length > 0);
342
+ n?.(a);
343
+ };
344
+ return /* @__PURE__ */ m("div", {
345
+ className: "row g-3",
346
+ children: [
347
+ /* @__PURE__ */ m("div", {
348
+ className: "col-md-6",
349
+ children: [/* @__PURE__ */ p("label", {
350
+ className: "form-label",
351
+ children: "Tipo de banco"
352
+ }), /* @__PURE__ */ p("select", {
353
+ className: "form-select",
354
+ value: r.databaseType,
355
+ onChange: (e) => i(e.target.value),
356
+ children: z.map((e) => /* @__PURE__ */ p("option", {
357
+ value: e,
358
+ children: L[e] ?? e
359
+ }, e))
360
+ })]
361
+ }),
362
+ /* @__PURE__ */ m("div", {
363
+ className: "col-md-6",
364
+ children: [/* @__PURE__ */ p("label", {
365
+ className: "form-label",
366
+ children: "Host"
367
+ }), /* @__PURE__ */ p("input", {
368
+ className: "form-control",
369
+ value: r.host,
370
+ placeholder: "localhost",
371
+ onChange: (e) => a({ host: e.target.value })
372
+ })]
373
+ }),
374
+ /* @__PURE__ */ m("div", {
375
+ className: "col-md-4",
376
+ children: [/* @__PURE__ */ p("label", {
377
+ className: "form-label",
378
+ children: "Porta"
379
+ }), /* @__PURE__ */ p("input", {
380
+ className: "form-control",
381
+ type: "number",
382
+ min: 1,
383
+ max: 65535,
384
+ value: r.port,
385
+ onChange: (e) => a({ port: Number(e.target.value) })
386
+ })]
387
+ }),
388
+ /* @__PURE__ */ m("div", {
389
+ className: "col-md-8",
390
+ children: [/* @__PURE__ */ p("label", {
391
+ className: "form-label",
392
+ children: "Nome do banco"
393
+ }), /* @__PURE__ */ p("input", {
394
+ className: "form-control",
395
+ value: r.databaseName,
396
+ placeholder: "sigamais",
397
+ onChange: (e) => a({ databaseName: e.target.value })
398
+ })]
399
+ }),
400
+ /* @__PURE__ */ m("div", {
401
+ className: "col-md-6",
402
+ children: [/* @__PURE__ */ p("label", {
403
+ className: "form-label",
404
+ children: "Usuário"
405
+ }), /* @__PURE__ */ p("input", {
406
+ className: "form-control",
407
+ value: r.username,
408
+ placeholder: "postgres",
409
+ autoComplete: "off",
410
+ onChange: (e) => a({ username: e.target.value })
411
+ })]
412
+ }),
413
+ /* @__PURE__ */ m("div", {
414
+ className: "col-md-6",
415
+ children: [/* @__PURE__ */ p("label", {
416
+ className: "form-label",
417
+ children: "Senha"
418
+ }), /* @__PURE__ */ p("input", {
419
+ className: "form-control",
420
+ type: "password",
421
+ value: r.password,
422
+ autoComplete: "new-password",
423
+ onChange: (e) => a({ password: e.target.value })
424
+ })]
425
+ })
426
+ ]
427
+ });
428
+ }
429
+ //#endregion
430
+ //#region src/components/RestoreModal.tsx
431
+ function U({ backup: e, onClose: t }) {
432
+ let n = T(), [r, i] = o(), [a, s] = o(!1), c = () => {
433
+ r && n.mutate({
434
+ id: e.id,
435
+ database: r
436
+ });
437
+ }, l = n.isPending;
438
+ return /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", { className: "modal-backdrop show" }), /* @__PURE__ */ p("div", {
439
+ className: "modal show d-block",
440
+ tabIndex: -1,
441
+ role: "dialog",
442
+ onClick: (e) => {
443
+ e.target === e.currentTarget && t();
444
+ },
445
+ children: /* @__PURE__ */ p("div", {
446
+ className: "modal-dialog modal-dialog-centered modal-lg",
447
+ role: "document",
448
+ children: /* @__PURE__ */ m("div", {
449
+ className: "modal-content",
450
+ children: [
451
+ /* @__PURE__ */ m("div", {
452
+ className: "modal-header",
453
+ children: [/* @__PURE__ */ m("h5", {
454
+ className: "modal-title",
455
+ children: [
456
+ /* @__PURE__ */ p("i", {
457
+ className: "bi bi-arrow-counterclockwise me-2",
458
+ "aria-hidden": !0
459
+ }),
460
+ "Restaurar backup #",
461
+ e.id
462
+ ]
463
+ }), /* @__PURE__ */ p("button", {
464
+ type: "button",
465
+ className: "btn-close",
466
+ "aria-label": "Fechar",
467
+ onClick: t
468
+ })]
469
+ }),
470
+ /* @__PURE__ */ m("div", {
471
+ className: "modal-body",
472
+ children: [
473
+ /* @__PURE__ */ m("p", {
474
+ className: "text-muted small mb-3",
475
+ children: [
476
+ "O arquivo ",
477
+ /* @__PURE__ */ p("code", { children: e.filename }),
478
+ " será aplicado no banco informado abaixo."
479
+ ]
480
+ }),
481
+ /* @__PURE__ */ p(H, {
482
+ onChange: i,
483
+ onValidatedChange: s
484
+ }),
485
+ n.isError && /* @__PURE__ */ m("div", {
486
+ className: "alert alert-danger mt-3 mb-0",
487
+ children: [/* @__PURE__ */ p("i", {
488
+ className: "bi bi-x-circle me-2",
489
+ "aria-hidden": !0
490
+ }), W(n.error)]
491
+ }),
492
+ n.isSuccess && /* @__PURE__ */ m("div", {
493
+ className: "alert alert-success mt-3 mb-0",
494
+ children: [/* @__PURE__ */ p("i", {
495
+ className: "bi bi-check-circle me-2",
496
+ "aria-hidden": !0
497
+ }), "Restauração iniciada com sucesso."]
498
+ })
499
+ ]
500
+ }),
501
+ /* @__PURE__ */ m("div", {
502
+ className: "modal-footer",
503
+ children: [/* @__PURE__ */ p("button", {
504
+ type: "button",
505
+ className: "btn btn-secondary",
506
+ onClick: t,
507
+ disabled: l,
508
+ children: "Fechar"
509
+ }), /* @__PURE__ */ m("button", {
510
+ type: "button",
511
+ className: "btn btn-primary",
512
+ onClick: c,
513
+ disabled: l || !a,
514
+ children: [l && /* @__PURE__ */ p(f, { children: /* @__PURE__ */ p("span", {
515
+ className: "spinner-border spinner-border-sm me-2",
516
+ "aria-hidden": !0
517
+ }) }), "Restaurar"]
518
+ })]
519
+ })
520
+ ]
521
+ })
522
+ })
523
+ })] });
524
+ }
525
+ function W(e) {
526
+ return e instanceof Error ? e.message : String(e);
527
+ }
528
+ //#endregion
529
+ //#region src/components/BackupsTab.tsx
530
+ function G() {
531
+ 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 } = C(e, 10, !0), y = O(), b = E(), x = D();
532
+ r(() => {
533
+ if (!y.data || !y.variables) return;
534
+ let e = URL.createObjectURL(y.data), t = document.createElement("a");
535
+ t.href = e, t.download = y.variables.filename, document.body.appendChild(t), t.click(), t.remove(), setTimeout(() => URL.revokeObjectURL(e), 1e4);
536
+ }, [y.data, y.variables]);
537
+ let S = i(() => d?.content ?? [], [d]), w = d?.totalPages ?? 0;
538
+ return /* @__PURE__ */ m("div", { children: [
539
+ /* @__PURE__ */ m("div", {
540
+ className: "d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3",
541
+ children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h5", {
542
+ className: "mb-0",
543
+ children: "Backups disponíveis"
544
+ }), /* @__PURE__ */ p("span", {
545
+ className: "text-muted small",
546
+ children: d ? `${d.totalElements} registro(s)` : "Carregando…"
547
+ })] }), /* @__PURE__ */ m("button", {
548
+ type: "button",
549
+ className: "btn btn-outline-secondary btn-sm",
550
+ onClick: () => _(),
551
+ disabled: v,
552
+ children: [
553
+ v && /* @__PURE__ */ p("span", {
554
+ className: "spinner-border spinner-border-sm me-2",
555
+ "aria-hidden": !0
556
+ }),
557
+ /* @__PURE__ */ p("i", {
558
+ className: "bi bi-arrow-repeat me-1",
559
+ "aria-hidden": !0
560
+ }),
561
+ "Atualizar"
562
+ ]
563
+ })]
564
+ }),
565
+ h && /* @__PURE__ */ m("div", {
566
+ className: "alert alert-danger",
567
+ children: [
568
+ /* @__PURE__ */ p("i", {
569
+ className: "bi bi-exclamation-triangle me-2",
570
+ "aria-hidden": !0
571
+ }),
572
+ "Não foi possível carregar os backups: ",
573
+ q(g)
574
+ ]
575
+ }),
576
+ y.isError && /* @__PURE__ */ m("div", {
577
+ className: "alert alert-danger",
578
+ children: [
579
+ /* @__PURE__ */ p("i", {
580
+ className: "bi bi-x-circle me-2",
581
+ "aria-hidden": !0
582
+ }),
583
+ "Falha no download: ",
584
+ q(y.error)
585
+ ]
586
+ }),
587
+ b.isError && /* @__PURE__ */ m("div", {
588
+ className: "alert alert-danger",
589
+ children: [
590
+ /* @__PURE__ */ p("i", {
591
+ className: "bi bi-x-circle me-2",
592
+ "aria-hidden": !0
593
+ }),
594
+ "Falha ao excluir: ",
595
+ q(b.error)
596
+ ]
597
+ }),
598
+ x.isError && /* @__PURE__ */ m("div", {
599
+ className: "alert alert-danger",
600
+ children: [
601
+ /* @__PURE__ */ p("i", {
602
+ className: "bi bi-x-circle me-2",
603
+ "aria-hidden": !0
604
+ }),
605
+ "Falha ao verificar: ",
606
+ q(x.error)
607
+ ]
608
+ }),
609
+ Object.entries(l).map(([e, t]) => /* @__PURE__ */ m("div", {
610
+ className: `alert alert-${t.valid ? "success" : "warning"} d-flex align-items-center justify-content-between`,
611
+ children: [/* @__PURE__ */ m("span", { children: [
612
+ /* @__PURE__ */ p("i", {
613
+ className: `bi ${t.valid ? "bi-check-circle" : "bi-exclamation-triangle"} me-2`,
614
+ "aria-hidden": !0
615
+ }),
616
+ "Backup ",
617
+ /* @__PURE__ */ m("strong", { children: ["#", e] }),
618
+ ": ",
619
+ t.message
620
+ ] }), /* @__PURE__ */ p("button", {
621
+ type: "button",
622
+ className: "btn-close",
623
+ "aria-label": "Fechar",
624
+ onClick: () => u((t) => {
625
+ let n = { ...t };
626
+ return delete n[Number(e)], n;
627
+ })
628
+ })]
629
+ }, e)),
630
+ f && !d ? /* @__PURE__ */ m("div", {
631
+ className: "text-center py-5 text-muted",
632
+ children: [/* @__PURE__ */ p("div", {
633
+ className: "spinner-border mb-2",
634
+ "aria-hidden": !0
635
+ }), /* @__PURE__ */ p("div", { children: "Carregando backups…" })]
636
+ }) : /* @__PURE__ */ p("div", {
637
+ className: "table-responsive",
638
+ children: /* @__PURE__ */ m("table", {
639
+ className: "table table-hover align-middle",
640
+ children: [/* @__PURE__ */ p("thead", { children: /* @__PURE__ */ m("tr", { children: [
641
+ /* @__PURE__ */ p("th", {
642
+ scope: "col",
643
+ children: "#"
644
+ }),
645
+ /* @__PURE__ */ p("th", {
646
+ scope: "col",
647
+ children: "Arquivo"
648
+ }),
649
+ /* @__PURE__ */ p("th", {
650
+ scope: "col",
651
+ children: "Banco"
652
+ }),
653
+ /* @__PURE__ */ p("th", {
654
+ scope: "col",
655
+ className: "text-end",
656
+ children: "Tamanho"
657
+ }),
658
+ /* @__PURE__ */ p("th", {
659
+ scope: "col",
660
+ children: "Status"
661
+ }),
662
+ /* @__PURE__ */ p("th", {
663
+ scope: "col",
664
+ children: "Checksum"
665
+ }),
666
+ /* @__PURE__ */ p("th", {
667
+ scope: "col",
668
+ children: "Retenção"
669
+ }),
670
+ /* @__PURE__ */ p("th", {
671
+ scope: "col",
672
+ children: "Criado em"
673
+ }),
674
+ /* @__PURE__ */ p("th", {
675
+ scope: "col",
676
+ className: "text-end",
677
+ children: "Ações"
678
+ })
679
+ ] }) }), /* @__PURE__ */ m("tbody", { children: [S.length === 0 && /* @__PURE__ */ p("tr", { children: /* @__PURE__ */ p("td", {
680
+ colSpan: 9,
681
+ className: "text-center text-muted py-4",
682
+ children: "Nenhum backup cadastrado."
683
+ }) }), S.map((e) => /* @__PURE__ */ m("tr", { children: [
684
+ /* @__PURE__ */ p("td", { children: e.id }),
685
+ /* @__PURE__ */ m("td", {
686
+ className: "text-truncate",
687
+ style: { maxWidth: 260 },
688
+ title: e.filename,
689
+ children: [/* @__PURE__ */ p("i", {
690
+ className: "bi bi-archive me-1 text-primary",
691
+ "aria-hidden": !0
692
+ }), e.filename]
693
+ }),
694
+ /* @__PURE__ */ p("td", { children: L[e.databaseType] ?? e.databaseType }),
695
+ /* @__PURE__ */ p("td", {
696
+ className: "text-end",
697
+ children: N(e.fileSize)
698
+ }),
699
+ /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p(R, { status: e.status }) }),
700
+ /* @__PURE__ */ p("td", { children: e.sha256 ? /* @__PURE__ */ m("code", {
701
+ title: e.sha256,
702
+ style: { fontSize: "0.8em" },
703
+ children: [e.sha256.slice(0, 12), "…"]
704
+ }) : /* @__PURE__ */ p("span", {
705
+ className: "text-muted",
706
+ children: "—"
707
+ }) }),
708
+ /* @__PURE__ */ p("td", { children: e.retentionDays ? /* @__PURE__ */ m("span", {
709
+ className: "badge text-bg-light border",
710
+ children: [
711
+ /* @__PURE__ */ p("i", {
712
+ className: "bi bi-hourglass-split me-1",
713
+ "aria-hidden": !0
714
+ }),
715
+ e.retentionDays,
716
+ " dia(s)"
717
+ ]
718
+ }) : /* @__PURE__ */ p("span", {
719
+ className: "text-muted",
720
+ children: "—"
721
+ }) }),
722
+ /* @__PURE__ */ p("td", { children: P(e.createdAt) }),
723
+ /* @__PURE__ */ m("td", {
724
+ className: "text-end text-nowrap",
725
+ children: [
726
+ /* @__PURE__ */ p("button", {
727
+ type: "button",
728
+ className: "btn btn-sm btn-outline-secondary me-1",
729
+ title: "Verificar integridade",
730
+ disabled: x.isPending && x.variables === e.id,
731
+ onClick: () => x.mutateAsync(e.id).then((t) => u((n) => ({
732
+ ...n,
733
+ [e.id]: t
734
+ }))),
735
+ children: x.isPending && x.variables === e.id ? /* @__PURE__ */ p("span", {
736
+ className: "spinner-border spinner-border-sm",
737
+ "aria-hidden": !0
738
+ }) : /* @__PURE__ */ p("i", {
739
+ className: "bi bi-shield-check",
740
+ "aria-hidden": !0
741
+ })
742
+ }),
743
+ /* @__PURE__ */ p("button", {
744
+ type: "button",
745
+ className: "btn btn-sm btn-outline-primary me-1",
746
+ title: "Baixar",
747
+ disabled: y.isPending,
748
+ onClick: () => y.mutate({
749
+ id: e.id,
750
+ filename: e.filename
751
+ }),
752
+ children: /* @__PURE__ */ p("i", {
753
+ className: "bi bi-download",
754
+ "aria-hidden": !0
755
+ })
756
+ }),
757
+ /* @__PURE__ */ p("button", {
758
+ type: "button",
759
+ className: "btn btn-sm btn-outline-secondary me-1",
760
+ title: "Restaurar",
761
+ onClick: () => a(e),
762
+ children: /* @__PURE__ */ p("i", {
763
+ className: "bi bi-arrow-counterclockwise",
764
+ "aria-hidden": !0
765
+ })
766
+ }),
767
+ /* @__PURE__ */ p("button", {
768
+ type: "button",
769
+ className: "btn btn-sm btn-outline-danger",
770
+ title: "Excluir",
771
+ onClick: () => c(e),
772
+ children: /* @__PURE__ */ p("i", {
773
+ className: "bi bi-trash3",
774
+ "aria-hidden": !0
775
+ })
776
+ })
777
+ ]
778
+ })
779
+ ] }, e.id))] })]
780
+ })
781
+ }),
782
+ /* @__PURE__ */ m("div", {
783
+ className: "d-flex align-items-center justify-content-between flex-wrap gap-2 mt-3",
784
+ children: [/* @__PURE__ */ m("span", {
785
+ className: "text-muted small",
786
+ children: [
787
+ "Página ",
788
+ e + 1,
789
+ " de ",
790
+ Math.max(w, 1)
791
+ ]
792
+ }), /* @__PURE__ */ m("div", {
793
+ className: "btn-group",
794
+ children: [/* @__PURE__ */ p("button", {
795
+ type: "button",
796
+ className: "btn btn-outline-secondary btn-sm",
797
+ disabled: e <= 0,
798
+ onClick: () => t((e) => Math.max(0, e - 1)),
799
+ children: /* @__PURE__ */ p("i", {
800
+ className: "bi bi-chevron-left",
801
+ "aria-hidden": !0
802
+ })
803
+ }), /* @__PURE__ */ p("button", {
804
+ type: "button",
805
+ className: "btn btn-outline-secondary btn-sm",
806
+ disabled: e + 1 >= w,
807
+ onClick: () => t((e) => e + 1),
808
+ children: /* @__PURE__ */ p("i", {
809
+ className: "bi bi-chevron-right",
810
+ "aria-hidden": !0
811
+ })
812
+ })]
813
+ })]
814
+ }),
815
+ n && /* @__PURE__ */ p(U, {
816
+ backup: n,
817
+ onClose: () => a(null)
818
+ }),
819
+ s && /* @__PURE__ */ p(K, {
820
+ backup: s,
821
+ busy: b.isPending,
822
+ onCancel: () => c(null),
823
+ onConfirm: () => {
824
+ b.mutate(s.id), c(null);
825
+ }
826
+ })
827
+ ] });
828
+ }
829
+ function K(e) {
830
+ let { backup: t, busy: n, onCancel: r, onConfirm: i } = e;
831
+ return /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", { className: "modal-backdrop show" }), /* @__PURE__ */ p("div", {
832
+ className: "modal show d-block",
833
+ tabIndex: -1,
834
+ role: "dialog",
835
+ onClick: (e) => {
836
+ e.target === e.currentTarget && r();
837
+ },
838
+ children: /* @__PURE__ */ p("div", {
839
+ className: "modal-dialog modal-dialog-centered",
840
+ role: "document",
841
+ children: /* @__PURE__ */ m("div", {
842
+ className: "modal-content",
843
+ children: [
844
+ /* @__PURE__ */ m("div", {
845
+ className: "modal-header",
846
+ children: [/* @__PURE__ */ m("h5", {
847
+ className: "modal-title",
848
+ children: [
849
+ "Excluir backup #",
850
+ t.id,
851
+ "?"
852
+ ]
853
+ }), /* @__PURE__ */ p("button", {
854
+ type: "button",
855
+ className: "btn-close",
856
+ "aria-label": "Fechar",
857
+ onClick: r
858
+ })]
859
+ }),
860
+ /* @__PURE__ */ p("div", {
861
+ className: "modal-body",
862
+ children: /* @__PURE__ */ m("p", {
863
+ className: "mb-0",
864
+ children: [
865
+ "O arquivo ",
866
+ /* @__PURE__ */ p("code", { children: t.filename }),
867
+ " será removido permanentemente. Essa ação não pode ser desfeita."
868
+ ]
869
+ })
870
+ }),
871
+ /* @__PURE__ */ m("div", {
872
+ className: "modal-footer",
873
+ children: [/* @__PURE__ */ p("button", {
874
+ type: "button",
875
+ className: "btn btn-secondary",
876
+ onClick: r,
877
+ disabled: n,
878
+ children: "Cancelar"
879
+ }), /* @__PURE__ */ m("button", {
880
+ type: "button",
881
+ className: "btn btn-danger",
882
+ onClick: i,
883
+ disabled: n,
884
+ children: [n && /* @__PURE__ */ p("span", {
885
+ className: "spinner-border spinner-border-sm me-2",
886
+ "aria-hidden": !0
887
+ }), "Excluir"]
888
+ })]
889
+ })
890
+ ]
891
+ })
892
+ })
893
+ })] });
894
+ }
895
+ function q(e) {
896
+ return e instanceof Error ? e.message : String(e);
897
+ }
898
+ //#endregion
899
+ //#region src/components/CreateBackupTab.tsx
900
+ function J() {
901
+ let e = w(), [t, n] = o(void 0), [r, i] = o(!1), [a, s] = o(!1), [c, l] = o(() => ({
902
+ type: "LOCAL",
903
+ localPath: ""
904
+ })), [u, d] = o(!1), [h, g] = o({
905
+ format: "custom",
906
+ includeData: !0,
907
+ includeDropTable: !1,
908
+ includeCreateTable: !0,
909
+ includeIndexes: !0,
910
+ includeConstraints: !0,
911
+ includeRelatedTables: !1
912
+ }), [_, v] = o(""), [y, b] = o(""), x = () => {
913
+ if (!t) return;
914
+ let n;
915
+ if (u && (n = { ...h }, _.trim() && (n.tables = _.split(",").map((e) => e.trim()).filter(Boolean)), y.trim())) {
916
+ let e = {};
917
+ y.split(";").forEach((t) => {
918
+ let [n, r] = t.split(":").map((e) => e.trim());
919
+ n && r && (e[n] = r.split(",").map((e) => e.trim()).filter(Boolean));
920
+ }), Object.keys(e).length > 0 && (n.excludeColumnsPerTable = e);
921
+ }
922
+ e.mutate({
923
+ database: t,
924
+ originStorage: a ? c : void 0,
925
+ dumpOptions: n
926
+ });
927
+ }, S = e.isPending;
928
+ return /* @__PURE__ */ m("div", { children: [
929
+ /* @__PURE__ */ m("div", {
930
+ className: "mb-3",
931
+ children: [/* @__PURE__ */ p("h5", {
932
+ className: "mb-1",
933
+ children: "Criar novo backup"
934
+ }), /* @__PURE__ */ p("p", {
935
+ className: "text-muted small mb-0",
936
+ children: "Informe a conexao do banco a ser copiado. O minivault gera o dump e empacota em ZIP."
937
+ })]
938
+ }),
939
+ /* @__PURE__ */ m("div", {
940
+ className: "card mb-3",
941
+ children: [/* @__PURE__ */ m("div", {
942
+ className: "card-header d-flex align-items-center gap-2",
943
+ children: [/* @__PURE__ */ p("i", {
944
+ className: "bi bi-database",
945
+ "aria-hidden": !0
946
+ }), "Conexao do banco de origem"]
947
+ }), /* @__PURE__ */ p("div", {
948
+ className: "card-body",
949
+ children: /* @__PURE__ */ p(H, {
950
+ onChange: n,
951
+ onValidatedChange: i
952
+ })
953
+ })]
954
+ }),
955
+ /* @__PURE__ */ m("div", {
956
+ className: "form-check form-switch mb-3",
957
+ children: [/* @__PURE__ */ p("input", {
958
+ className: "form-check-input",
959
+ type: "checkbox",
960
+ role: "switch",
961
+ id: "minivault-with-dump-options",
962
+ checked: u,
963
+ onChange: (e) => d(e.target.checked)
964
+ }), /* @__PURE__ */ p("label", {
965
+ className: "form-check-label",
966
+ htmlFor: "minivault-with-dump-options",
967
+ children: "Configurar opcoes do dump (tabelas, colunas, formato)"
968
+ })]
969
+ }),
970
+ u && /* @__PURE__ */ m("div", {
971
+ className: "card mb-3",
972
+ children: [/* @__PURE__ */ m("div", {
973
+ className: "card-header d-flex align-items-center gap-2",
974
+ children: [/* @__PURE__ */ p("i", {
975
+ className: "bi bi-gear",
976
+ "aria-hidden": !0
977
+ }), "Opcoes de dump"]
978
+ }), /* @__PURE__ */ m("div", {
979
+ className: "card-body",
980
+ children: [
981
+ /* @__PURE__ */ p("div", {
982
+ className: "row g-3 mb-3",
983
+ children: /* @__PURE__ */ m("div", {
984
+ className: "col-md-4",
985
+ children: [/* @__PURE__ */ p("label", {
986
+ className: "form-label",
987
+ children: "Formato"
988
+ }), /* @__PURE__ */ m("select", {
989
+ className: "form-select",
990
+ value: h.format,
991
+ onChange: (e) => g((t) => ({
992
+ ...t,
993
+ format: e.target.value
994
+ })),
995
+ children: [
996
+ /* @__PURE__ */ p("option", {
997
+ value: "custom",
998
+ children: "Custom (-Fc, recomendado)"
999
+ }),
1000
+ /* @__PURE__ */ p("option", {
1001
+ value: "plain",
1002
+ children: "Plain SQL (texto)"
1003
+ }),
1004
+ /* @__PURE__ */ p("option", {
1005
+ value: "tar",
1006
+ children: "Tar (-Ft)"
1007
+ })
1008
+ ]
1009
+ })]
1010
+ })
1011
+ }),
1012
+ /* @__PURE__ */ m("div", {
1013
+ className: "mb-3",
1014
+ children: [
1015
+ /* @__PURE__ */ p("label", {
1016
+ className: "form-label",
1017
+ children: "Tabelas (separadas por virgula)"
1018
+ }),
1019
+ /* @__PURE__ */ p("input", {
1020
+ className: "form-control font-monospace",
1021
+ value: _,
1022
+ placeholder: "public.users, public.os, auth.user_groups",
1023
+ onChange: (e) => v(e.target.value)
1024
+ }),
1025
+ /* @__PURE__ */ p("small", {
1026
+ className: "text-muted",
1027
+ children: "Deixe vazio para incluir todas as tabelas"
1028
+ })
1029
+ ]
1030
+ }),
1031
+ h.format === "plain" && /* @__PURE__ */ m("div", {
1032
+ className: "mb-3",
1033
+ children: [
1034
+ /* @__PURE__ */ p("label", {
1035
+ className: "form-label",
1036
+ children: "Colunas a omitir (formato: tabela:col1,col2)"
1037
+ }),
1038
+ /* @__PURE__ */ p("input", {
1039
+ className: "form-control font-monospace",
1040
+ value: y,
1041
+ placeholder: "public.users:password_hash,sensitive_data; public.os:internal_notes",
1042
+ onChange: (e) => b(e.target.value)
1043
+ }),
1044
+ /* @__PURE__ */ p("small", {
1045
+ className: "text-muted",
1046
+ children: "Separado por ponto e virgula entre tabelas. Apenas para formato Plain SQL."
1047
+ })
1048
+ ]
1049
+ }),
1050
+ /* @__PURE__ */ p("div", {
1051
+ className: "row g-3",
1052
+ children: [
1053
+ {
1054
+ key: "includeData",
1055
+ label: "Incluir dados (INSERTs)"
1056
+ },
1057
+ {
1058
+ key: "includeDropTable",
1059
+ label: "Incluir DROP TABLE"
1060
+ },
1061
+ {
1062
+ key: "includeCreateTable",
1063
+ label: "Incluir CREATE TABLE"
1064
+ },
1065
+ {
1066
+ key: "includeIndexes",
1067
+ label: "Incluir indices"
1068
+ },
1069
+ {
1070
+ key: "includeConstraints",
1071
+ label: "Incluir constraints"
1072
+ },
1073
+ {
1074
+ key: "includeRelatedTables",
1075
+ label: "Incluir tabelas relacionadas"
1076
+ }
1077
+ ].map(({ key: e, label: t }) => /* @__PURE__ */ p("div", {
1078
+ className: "col-md-4",
1079
+ children: /* @__PURE__ */ m("div", {
1080
+ className: "form-check",
1081
+ children: [/* @__PURE__ */ p("input", {
1082
+ className: "form-check-input",
1083
+ type: "checkbox",
1084
+ id: `dump-opt-${e}`,
1085
+ checked: !!h[e],
1086
+ onChange: (t) => g((n) => ({
1087
+ ...n,
1088
+ [e]: t.target.checked
1089
+ }))
1090
+ }), /* @__PURE__ */ p("label", {
1091
+ className: "form-check-label",
1092
+ htmlFor: `dump-opt-${e}`,
1093
+ children: t
1094
+ })]
1095
+ })
1096
+ }, e))
1097
+ })
1098
+ ]
1099
+ })]
1100
+ }),
1101
+ /* @__PURE__ */ m("div", {
1102
+ className: "form-check form-switch mb-3",
1103
+ children: [/* @__PURE__ */ p("input", {
1104
+ className: "form-check-input",
1105
+ type: "checkbox",
1106
+ role: "switch",
1107
+ id: "minivault-with-origin",
1108
+ checked: a,
1109
+ onChange: (e) => s(e.target.checked)
1110
+ }), /* @__PURE__ */ p("label", {
1111
+ className: "form-check-label",
1112
+ htmlFor: "minivault-with-origin",
1113
+ children: "Incluir arquivos de origem no backup (armazenamento do sistema)"
1114
+ })]
1115
+ }),
1116
+ a && /* @__PURE__ */ m("div", {
1117
+ className: "card mb-3",
1118
+ children: [/* @__PURE__ */ m("div", {
1119
+ className: "card-header d-flex align-items-center gap-2",
1120
+ children: [/* @__PURE__ */ p("i", {
1121
+ className: "bi bi-folder2-open",
1122
+ "aria-hidden": !0
1123
+ }), "Origem dos arquivos"]
1124
+ }), /* @__PURE__ */ p("div", {
1125
+ className: "card-body",
1126
+ children: /* @__PURE__ */ m("div", {
1127
+ className: "row g-3",
1128
+ children: [/* @__PURE__ */ m("div", {
1129
+ className: "col-md-4",
1130
+ children: [/* @__PURE__ */ p("label", {
1131
+ className: "form-label",
1132
+ children: "Tipo"
1133
+ }), /* @__PURE__ */ m("select", {
1134
+ className: "form-select",
1135
+ value: c.type,
1136
+ onChange: (e) => l((t) => ({
1137
+ ...t,
1138
+ type: e.target.value
1139
+ })),
1140
+ children: [/* @__PURE__ */ p("option", {
1141
+ value: "LOCAL",
1142
+ children: "Local (diretorio)"
1143
+ }), /* @__PURE__ */ p("option", {
1144
+ value: "S3",
1145
+ children: "S3 (MinIO/S3)"
1146
+ })]
1147
+ })]
1148
+ }), c.type === "LOCAL" ? /* @__PURE__ */ m("div", {
1149
+ className: "col-md-8",
1150
+ children: [/* @__PURE__ */ p("label", {
1151
+ className: "form-label",
1152
+ children: "Caminho local"
1153
+ }), /* @__PURE__ */ p("input", {
1154
+ className: "form-control",
1155
+ value: c.localPath,
1156
+ placeholder: "/dados/sistema",
1157
+ onChange: (e) => l((t) => ({
1158
+ ...t,
1159
+ localPath: e.target.value
1160
+ }))
1161
+ })]
1162
+ }) : /* @__PURE__ */ m(f, { children: [
1163
+ /* @__PURE__ */ m("div", {
1164
+ className: "col-md-6",
1165
+ children: [/* @__PURE__ */ p("label", {
1166
+ className: "form-label",
1167
+ children: "Endpoint"
1168
+ }), /* @__PURE__ */ p("input", {
1169
+ className: "form-control",
1170
+ value: c.endpoint,
1171
+ placeholder: "http://192.168.0.10:9000",
1172
+ onChange: (e) => l((t) => ({
1173
+ ...t,
1174
+ endpoint: e.target.value
1175
+ }))
1176
+ })]
1177
+ }),
1178
+ /* @__PURE__ */ m("div", {
1179
+ className: "col-md-6",
1180
+ children: [/* @__PURE__ */ p("label", {
1181
+ className: "form-label",
1182
+ children: "Bucket"
1183
+ }), /* @__PURE__ */ p("input", {
1184
+ className: "form-control",
1185
+ value: c.bucketName,
1186
+ placeholder: "storage",
1187
+ onChange: (e) => l((t) => ({
1188
+ ...t,
1189
+ bucketName: e.target.value
1190
+ }))
1191
+ })]
1192
+ }),
1193
+ /* @__PURE__ */ m("div", {
1194
+ className: "col-md-6",
1195
+ children: [/* @__PURE__ */ p("label", {
1196
+ className: "form-label",
1197
+ children: "Access key"
1198
+ }), /* @__PURE__ */ p("input", {
1199
+ className: "form-control",
1200
+ value: c.accessKey,
1201
+ onChange: (e) => l((t) => ({
1202
+ ...t,
1203
+ accessKey: e.target.value
1204
+ }))
1205
+ })]
1206
+ }),
1207
+ /* @__PURE__ */ m("div", {
1208
+ className: "col-md-6",
1209
+ children: [/* @__PURE__ */ p("label", {
1210
+ className: "form-label",
1211
+ children: "Secret key"
1212
+ }), /* @__PURE__ */ p("input", {
1213
+ className: "form-control",
1214
+ type: "password",
1215
+ value: c.secretKey,
1216
+ onChange: (e) => l((t) => ({
1217
+ ...t,
1218
+ secretKey: e.target.value
1219
+ }))
1220
+ })]
1221
+ }),
1222
+ /* @__PURE__ */ m("div", {
1223
+ className: "col-md-6",
1224
+ children: [/* @__PURE__ */ p("label", {
1225
+ className: "form-label",
1226
+ children: "Regiao"
1227
+ }), /* @__PURE__ */ p("input", {
1228
+ className: "form-control",
1229
+ value: c.region,
1230
+ placeholder: "us-east-1",
1231
+ onChange: (e) => l((t) => ({
1232
+ ...t,
1233
+ region: e.target.value
1234
+ }))
1235
+ })]
1236
+ }),
1237
+ /* @__PURE__ */ p("div", {
1238
+ className: "col-md-6 d-flex align-items-end pb-1",
1239
+ children: /* @__PURE__ */ m("div", {
1240
+ className: "form-check form-switch",
1241
+ children: [/* @__PURE__ */ p("input", {
1242
+ className: "form-check-input",
1243
+ type: "checkbox",
1244
+ role: "switch",
1245
+ id: "minivault-origin-pathstyle",
1246
+ checked: !!c.pathStyleEnabled,
1247
+ onChange: (e) => l((t) => ({
1248
+ ...t,
1249
+ pathStyleEnabled: e.target.checked
1250
+ }))
1251
+ }), /* @__PURE__ */ p("label", {
1252
+ className: "form-check-label",
1253
+ htmlFor: "minivault-origin-pathstyle",
1254
+ children: "Path-style (MinIO)"
1255
+ })]
1256
+ })
1257
+ })
1258
+ ] })]
1259
+ })
1260
+ })]
1261
+ }),
1262
+ e.isError && /* @__PURE__ */ m("div", {
1263
+ className: "alert alert-danger",
1264
+ children: [
1265
+ /* @__PURE__ */ p("i", {
1266
+ className: "bi bi-x-circle me-2",
1267
+ "aria-hidden": !0
1268
+ }),
1269
+ "Falha ao criar backup: ",
1270
+ W(e.error)
1271
+ ]
1272
+ }),
1273
+ e.isSuccess && /* @__PURE__ */ m("div", {
1274
+ className: "alert alert-success",
1275
+ children: [
1276
+ /* @__PURE__ */ p("i", {
1277
+ className: "bi bi-check-circle me-2",
1278
+ "aria-hidden": !0
1279
+ }),
1280
+ "Backup #",
1281
+ e.data.id,
1282
+ " criado (",
1283
+ e.data.filename,
1284
+ ")."
1285
+ ]
1286
+ }),
1287
+ /* @__PURE__ */ p("div", {
1288
+ className: "d-flex justify-content-end",
1289
+ children: /* @__PURE__ */ m("button", {
1290
+ type: "button",
1291
+ className: "btn btn-primary",
1292
+ onClick: x,
1293
+ disabled: S || !r,
1294
+ children: [
1295
+ S && /* @__PURE__ */ p("span", {
1296
+ className: "spinner-border spinner-border-sm me-2",
1297
+ "aria-hidden": !0
1298
+ }),
1299
+ /* @__PURE__ */ p("i", {
1300
+ className: "bi bi-plus-lg me-1",
1301
+ "aria-hidden": !0
1302
+ }),
1303
+ "Iniciar backup"
1304
+ ]
1305
+ })
1306
+ })
1307
+ ] });
1308
+ }
1309
+ //#endregion
1310
+ //#region src/components/StorageExplorerTab.tsx
1311
+ function Y({ storageType: e = "LOCAL", storageConfig: n }) {
1312
+ let i = b(), a = d(), [s, c] = o(""), [h, g] = o([]), [_, v] = o(/* @__PURE__ */ new Set()), [y, x] = o(null), S = n?.type ?? e, { data: C, isLoading: w } = u({
1313
+ queryKey: [
1314
+ "storage-files",
1315
+ S,
1316
+ s,
1317
+ n
1318
+ ],
1319
+ queryFn: () => i.listStorageFiles(S, s || void 0, n)
1320
+ }), T = l({
1321
+ mutationFn: (e) => i.deleteStorageFile(e, S, n),
1322
+ onSuccess: () => {
1323
+ a.invalidateQueries({ queryKey: ["storage-files"] }), x(null);
1324
+ }
1325
+ }), E = t((e) => {
1326
+ c(e), g(e ? e.split("/").filter(Boolean) : []), v(/* @__PURE__ */ new Set());
1327
+ }, []), D = t((e) => {
1328
+ let t = h.slice(0, e + 1).join("/");
1329
+ E(t);
1330
+ }, [h, E]);
1331
+ r(() => {
1332
+ g(s ? s.split("/").filter(Boolean) : []);
1333
+ }, [s]);
1334
+ let O = (e) => {
1335
+ v((t) => {
1336
+ let n = new Set(t);
1337
+ return n.has(e) ? n.delete(e) : n.add(e), n;
1338
+ });
1339
+ }, k = () => {
1340
+ C && (_.size === C.length ? v(/* @__PURE__ */ new Set()) : v(new Set(C.map((e) => e.path))));
1341
+ }, A = async (e) => {
1342
+ try {
1343
+ let t = await i.downloadStorageFile(e, S, n), r = e.split("/").pop() ?? e, a = window.URL.createObjectURL(t), o = document.createElement("a");
1344
+ o.href = a, o.download = r, document.body.appendChild(o), o.click(), o.remove(), window.URL.revokeObjectURL(a);
1345
+ } catch {}
1346
+ }, j = async () => {
1347
+ for (let e of _) await A(e);
1348
+ }, M = (e) => e ? P(e) : "-";
1349
+ return /* @__PURE__ */ m("div", {
1350
+ className: "space-y-3",
1351
+ children: [
1352
+ /* @__PURE__ */ m("div", {
1353
+ className: "d-flex align-items-center justify-content-between",
1354
+ children: [/* @__PURE__ */ m("h6", {
1355
+ className: "mb-0",
1356
+ children: [
1357
+ /* @__PURE__ */ p("i", { className: "bi bi-folder2-open me-2" }),
1358
+ "Explorador de Storage",
1359
+ /* @__PURE__ */ p("span", {
1360
+ className: "badge bg-secondary ms-2",
1361
+ children: S
1362
+ })
1363
+ ]
1364
+ }), /* @__PURE__ */ p("div", {
1365
+ className: "d-flex gap-2",
1366
+ children: _.size > 0 && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("button", {
1367
+ className: "btn btn-sm btn-outline-primary",
1368
+ onClick: j,
1369
+ children: [
1370
+ /* @__PURE__ */ p("i", { className: "bi bi-download me-1" }),
1371
+ "Baixar (",
1372
+ _.size,
1373
+ ")"
1374
+ ]
1375
+ }), /* @__PURE__ */ m("button", {
1376
+ className: "btn btn-sm btn-outline-danger",
1377
+ onClick: () => x("multiple"),
1378
+ children: [
1379
+ /* @__PURE__ */ p("i", { className: "bi bi-trash me-1" }),
1380
+ "Excluir (",
1381
+ _.size,
1382
+ ")"
1383
+ ]
1384
+ })] })
1385
+ })]
1386
+ }),
1387
+ /* @__PURE__ */ p("nav", {
1388
+ "aria-label": "breadcrumb",
1389
+ children: /* @__PURE__ */ m("ol", {
1390
+ className: "breadcrumb mb-0 small",
1391
+ children: [/* @__PURE__ */ p("li", {
1392
+ className: `breadcrumb-item ${h.length === 0 ? "active" : ""}`,
1393
+ style: { cursor: h.length > 0 ? "pointer" : "default" },
1394
+ onClick: () => E(""),
1395
+ children: /* @__PURE__ */ p("i", { className: "bi bi-house" })
1396
+ }), h.map((e, t) => /* @__PURE__ */ p("li", {
1397
+ className: `breadcrumb-item ${t === h.length - 1 ? "active" : ""}`,
1398
+ style: { cursor: t < h.length - 1 ? "pointer" : "default" },
1399
+ onClick: () => t < h.length - 1 && D(t),
1400
+ children: e
1401
+ }, t))]
1402
+ })
1403
+ }),
1404
+ w ? /* @__PURE__ */ m("div", {
1405
+ className: "text-center py-5",
1406
+ children: [/* @__PURE__ */ p("div", {
1407
+ className: "spinner-border text-primary",
1408
+ role: "status"
1409
+ }), /* @__PURE__ */ p("div", {
1410
+ className: "mt-2 small text-muted",
1411
+ children: "Carregando arquivos..."
1412
+ })]
1413
+ }) : !C || C.length === 0 ? /* @__PURE__ */ m("div", {
1414
+ className: "text-center py-5 text-muted",
1415
+ children: [
1416
+ /* @__PURE__ */ p("i", { className: "bi bi-folder-x fs-1 d-block mb-2" }),
1417
+ "Nenhum arquivo encontrado",
1418
+ s && /* @__PURE__ */ p("button", {
1419
+ className: "btn btn-sm btn-link mt-2",
1420
+ onClick: () => E(""),
1421
+ children: "Voltar ao inicio"
1422
+ })
1423
+ ]
1424
+ }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("div", {
1425
+ className: "d-flex align-items-center gap-2 mb-2",
1426
+ children: [/* @__PURE__ */ m("button", {
1427
+ className: "btn btn-sm btn-outline-secondary",
1428
+ onClick: k,
1429
+ children: [_.size === C.length ? "Desmarcar" : "Selecionar", " Todos"]
1430
+ }), /* @__PURE__ */ m("span", {
1431
+ className: "small text-muted",
1432
+ children: [C.length, " item(ns)"]
1433
+ })]
1434
+ }), /* @__PURE__ */ p("div", {
1435
+ className: "table-responsive",
1436
+ children: /* @__PURE__ */ m("table", {
1437
+ className: "table table-hover table-sm align-middle mb-0",
1438
+ children: [/* @__PURE__ */ p("thead", {
1439
+ className: "table-light",
1440
+ children: /* @__PURE__ */ m("tr", { children: [
1441
+ /* @__PURE__ */ p("th", { style: { width: 30 } }),
1442
+ /* @__PURE__ */ p("th", { children: "Nome" }),
1443
+ /* @__PURE__ */ p("th", {
1444
+ style: { width: 100 },
1445
+ children: "Tamanho"
1446
+ }),
1447
+ /* @__PURE__ */ p("th", {
1448
+ style: { width: 150 },
1449
+ children: "Modificado"
1450
+ }),
1451
+ /* @__PURE__ */ p("th", {
1452
+ style: { width: 80 },
1453
+ children: "Acoes"
1454
+ })
1455
+ ] })
1456
+ }), /* @__PURE__ */ p("tbody", { children: C.map((e) => /* @__PURE__ */ m("tr", {
1457
+ className: _.has(e.path) ? "table-active" : "",
1458
+ children: [
1459
+ /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p("input", {
1460
+ type: "checkbox",
1461
+ className: "form-check-input",
1462
+ checked: _.has(e.path),
1463
+ onChange: () => O(e.path)
1464
+ }) }),
1465
+ /* @__PURE__ */ p("td", { children: e.directory ? /* @__PURE__ */ m("button", {
1466
+ className: "btn btn-sm btn-link text-decoration-none p-0 text-start",
1467
+ onClick: () => E(e.path),
1468
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-folder-fill text-warning me-2" }), /* @__PURE__ */ p("span", {
1469
+ className: "font-monospace",
1470
+ children: e.name
1471
+ })]
1472
+ }) : /* @__PURE__ */ m("span", {
1473
+ className: "font-monospace small",
1474
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-file-earmark me-2 text-primary" }), e.name]
1475
+ }) }),
1476
+ /* @__PURE__ */ p("td", {
1477
+ className: "text-muted small",
1478
+ children: e.directory ? "-" : N(e.size)
1479
+ }),
1480
+ /* @__PURE__ */ p("td", {
1481
+ className: "text-muted small",
1482
+ children: M(e.lastModified)
1483
+ }),
1484
+ /* @__PURE__ */ p("td", { children: !e.directory && /* @__PURE__ */ m("div", {
1485
+ className: "d-flex gap-1",
1486
+ children: [/* @__PURE__ */ p("button", {
1487
+ className: "btn btn-sm btn-outline-primary py-0",
1488
+ title: "Baixar",
1489
+ onClick: () => A(e.path),
1490
+ children: /* @__PURE__ */ p("i", { className: "bi bi-download" })
1491
+ }), /* @__PURE__ */ p("button", {
1492
+ className: "btn btn-sm btn-outline-danger py-0",
1493
+ title: "Excluir",
1494
+ onClick: () => x(e.path),
1495
+ children: /* @__PURE__ */ p("i", { className: "bi bi-trash" })
1496
+ })]
1497
+ }) })
1498
+ ]
1499
+ }, e.path)) })]
1500
+ })
1501
+ })] }),
1502
+ y && /* @__PURE__ */ p("div", {
1503
+ className: "modal d-block",
1504
+ tabIndex: -1,
1505
+ style: { background: "rgba(0,0,0,.5)" },
1506
+ children: /* @__PURE__ */ p("div", {
1507
+ className: "modal-dialog modal-dialog-centered",
1508
+ children: /* @__PURE__ */ m("div", {
1509
+ className: "modal-content",
1510
+ children: [
1511
+ /* @__PURE__ */ m("div", {
1512
+ className: "modal-header",
1513
+ children: [/* @__PURE__ */ p("h6", {
1514
+ className: "modal-title",
1515
+ children: "Confirmar exclusao"
1516
+ }), /* @__PURE__ */ p("button", {
1517
+ className: "btn-close",
1518
+ onClick: () => x(null)
1519
+ })]
1520
+ }),
1521
+ /* @__PURE__ */ m("div", {
1522
+ className: "modal-body",
1523
+ children: [y === "multiple" ? /* @__PURE__ */ m("p", { children: [
1524
+ "Excluir ",
1525
+ _.size,
1526
+ " arquivo(s) selecionado(s)?"
1527
+ ] }) : /* @__PURE__ */ m("p", { children: [
1528
+ "Excluir ",
1529
+ /* @__PURE__ */ p("code", { children: y.split("/").pop() }),
1530
+ "?"
1531
+ ] }), /* @__PURE__ */ p("p", {
1532
+ className: "text-danger small mb-0",
1533
+ children: "Esta acao nao pode ser desfeita."
1534
+ })]
1535
+ }),
1536
+ /* @__PURE__ */ m("div", {
1537
+ className: "modal-footer",
1538
+ children: [/* @__PURE__ */ p("button", {
1539
+ className: "btn btn-sm btn-secondary",
1540
+ onClick: () => x(null),
1541
+ children: "Cancelar"
1542
+ }), /* @__PURE__ */ p("button", {
1543
+ className: "btn btn-sm btn-danger",
1544
+ disabled: T.isPending,
1545
+ onClick: async () => {
1546
+ if (y === "multiple") for (let e of _) await T.mutateAsync(e);
1547
+ else await T.mutateAsync(y);
1548
+ },
1549
+ children: T.isPending ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { className: "spinner-border spinner-border-sm me-1" }), "Excluindo..."] }) : "Excluir"
1550
+ })]
1551
+ })
1552
+ ]
1553
+ })
1554
+ })
1555
+ })
1556
+ ]
1557
+ });
1558
+ }
1559
+ //#endregion
1560
+ //#region src/components/ImportDumpTab.tsx
1561
+ function X() {
1562
+ let e = k(), t = A(), n = a(null), [r, i] = o("upload"), [s, c] = o(null), [l, u] = o(void 0), [d, f] = o(!1), [h, g] = o(""), [_, v] = o(!1), y = () => {
1563
+ l && (r === "upload" && s ? e.mutate({
1564
+ file: s,
1565
+ database: l
1566
+ }) : r === "storage" && h && t.mutate({
1567
+ storageType: "LOCAL",
1568
+ storagePath: h,
1569
+ database: l
1570
+ }));
1571
+ }, b = e.isPending || t.isPending, x = e.data ?? t.data, S = e.error ?? t.error;
1572
+ return /* @__PURE__ */ m("div", { children: [
1573
+ /* @__PURE__ */ m("div", {
1574
+ className: "mb-3",
1575
+ children: [/* @__PURE__ */ p("h5", {
1576
+ className: "mb-1",
1577
+ children: "Importar dump"
1578
+ }), /* @__PURE__ */ p("p", {
1579
+ className: "text-muted small mb-0",
1580
+ children: "Importe um dump de banco de dados via upload de arquivo ou diretamente do storage (local/S3)."
1581
+ })]
1582
+ }),
1583
+ /* @__PURE__ */ m("div", {
1584
+ className: "btn-group w-100 mb-3",
1585
+ role: "group",
1586
+ children: [
1587
+ /* @__PURE__ */ p("input", {
1588
+ type: "radio",
1589
+ className: "btn-check",
1590
+ name: "importMode",
1591
+ id: "importModeUpload",
1592
+ checked: r === "upload",
1593
+ onChange: () => i("upload")
1594
+ }),
1595
+ /* @__PURE__ */ m("label", {
1596
+ className: "btn btn-outline-primary",
1597
+ htmlFor: "importModeUpload",
1598
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-upload me-1" }), "Upload de arquivo"]
1599
+ }),
1600
+ /* @__PURE__ */ p("input", {
1601
+ type: "radio",
1602
+ className: "btn-check",
1603
+ name: "importMode",
1604
+ id: "importModeStorage",
1605
+ checked: r === "storage",
1606
+ onChange: () => i("storage")
1607
+ }),
1608
+ /* @__PURE__ */ m("label", {
1609
+ className: "btn btn-outline-primary",
1610
+ htmlFor: "importModeStorage",
1611
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-folder2-open me-1" }), "Do storage"]
1612
+ })
1613
+ ]
1614
+ }),
1615
+ r === "upload" && /* @__PURE__ */ m("div", {
1616
+ className: "card mb-3",
1617
+ children: [/* @__PURE__ */ m("div", {
1618
+ className: "card-header d-flex align-items-center gap-2",
1619
+ children: [/* @__PURE__ */ p("i", {
1620
+ className: "bi bi-file-earmark-arrow-up",
1621
+ "aria-hidden": !0
1622
+ }), "Arquivo .sql"]
1623
+ }), /* @__PURE__ */ m("div", {
1624
+ className: "card-body",
1625
+ children: [/* @__PURE__ */ p("input", {
1626
+ ref: n,
1627
+ type: "file",
1628
+ accept: ".sql,.txt,text/plain,application/sql,.Fc,.dump,application/octet-stream",
1629
+ className: "form-control",
1630
+ onChange: (e) => c(e.target.files?.[0] ?? null)
1631
+ }), s && /* @__PURE__ */ m("small", {
1632
+ className: "text-muted",
1633
+ children: [
1634
+ s.name,
1635
+ " · ",
1636
+ (s.size / 1024 / 1024).toFixed(2),
1637
+ " MB"
1638
+ ]
1639
+ })]
1640
+ })]
1641
+ }),
1642
+ r === "storage" && /* @__PURE__ */ m("div", {
1643
+ className: "card mb-3",
1644
+ children: [/* @__PURE__ */ m("div", {
1645
+ className: "card-header d-flex align-items-center justify-content-between",
1646
+ children: [/* @__PURE__ */ m("div", {
1647
+ className: "d-flex align-items-center gap-2",
1648
+ children: [/* @__PURE__ */ p("i", {
1649
+ className: "bi bi-folder2-open",
1650
+ "aria-hidden": !0
1651
+ }), "Arquivo no storage"]
1652
+ }), /* @__PURE__ */ m("button", {
1653
+ className: "btn btn-sm btn-outline-secondary",
1654
+ type: "button",
1655
+ onClick: () => v(!_),
1656
+ children: [/* @__PURE__ */ p("i", { className: "bi bi-search me-1" }), _ ? "Fechar" : "Explorar"]
1657
+ })]
1658
+ }), /* @__PURE__ */ m("div", {
1659
+ className: "card-body",
1660
+ children: [/* @__PURE__ */ m("div", {
1661
+ className: "mb-3",
1662
+ children: [
1663
+ /* @__PURE__ */ p("label", {
1664
+ className: "form-label",
1665
+ children: "Caminho do arquivo no storage"
1666
+ }),
1667
+ /* @__PURE__ */ p("input", {
1668
+ className: "form-control font-monospace",
1669
+ value: h,
1670
+ placeholder: "backups/backup_postgresql_20240101_120000.zip",
1671
+ onChange: (e) => g(e.target.value)
1672
+ }),
1673
+ /* @__PURE__ */ m("small", {
1674
+ className: "text-muted",
1675
+ children: [
1676
+ "Caminho relativo ao diretorio/base do storage (ex.: ",
1677
+ /* @__PURE__ */ p("code", { children: "backups/arquivo.sql" }),
1678
+ ")"
1679
+ ]
1680
+ })
1681
+ ]
1682
+ }), _ && /* @__PURE__ */ p("div", {
1683
+ className: "border rounded p-2",
1684
+ style: {
1685
+ maxHeight: 350,
1686
+ overflow: "auto"
1687
+ },
1688
+ children: /* @__PURE__ */ p(Y, {
1689
+ storageType: "LOCAL",
1690
+ storageConfig: {
1691
+ type: "LOCAL",
1692
+ localPath: "/data/storage"
1693
+ }
1694
+ })
1695
+ })]
1696
+ })]
1697
+ }),
1698
+ /* @__PURE__ */ m("div", {
1699
+ className: "card mb-3",
1700
+ children: [/* @__PURE__ */ m("div", {
1701
+ className: "card-header d-flex align-items-center gap-2",
1702
+ children: [/* @__PURE__ */ p("i", {
1703
+ className: "bi bi-database",
1704
+ "aria-hidden": !0
1705
+ }), "Banco de destino"]
1706
+ }), /* @__PURE__ */ p("div", {
1707
+ className: "card-body",
1708
+ children: /* @__PURE__ */ p(H, {
1709
+ onChange: u,
1710
+ onValidatedChange: f
1711
+ })
1712
+ })]
1713
+ }),
1714
+ S && /* @__PURE__ */ m("div", {
1715
+ className: "alert alert-danger",
1716
+ children: [
1717
+ /* @__PURE__ */ p("i", {
1718
+ className: "bi bi-x-circle me-2",
1719
+ "aria-hidden": !0
1720
+ }),
1721
+ "Falha na importacao: ",
1722
+ W(S)
1723
+ ]
1724
+ }),
1725
+ x && /* @__PURE__ */ m("div", {
1726
+ className: `alert ${x.success ? "alert-success" : "alert-danger"}`,
1727
+ children: [
1728
+ /* @__PURE__ */ p("i", {
1729
+ className: `bi ${x.success ? "bi-check-circle" : "bi-x-circle"} me-2`,
1730
+ "aria-hidden": !0
1731
+ }),
1732
+ x.message,
1733
+ x.log && /* @__PURE__ */ p("pre", {
1734
+ className: "mt-3 mb-0 p-2 bg-body-tertiary rounded small overflow-auto",
1735
+ style: { maxHeight: 260 },
1736
+ children: x.log
1737
+ })
1738
+ ]
1739
+ }),
1740
+ /* @__PURE__ */ p("div", {
1741
+ className: "d-flex justify-content-end",
1742
+ children: /* @__PURE__ */ m("button", {
1743
+ type: "button",
1744
+ className: "btn btn-primary",
1745
+ onClick: y,
1746
+ disabled: b || !d || (r === "upload" ? !s : !h),
1747
+ children: [
1748
+ b && /* @__PURE__ */ p("span", {
1749
+ className: "spinner-border spinner-border-sm me-2",
1750
+ "aria-hidden": !0
1751
+ }),
1752
+ /* @__PURE__ */ p("i", {
1753
+ className: "bi bi-upload me-1",
1754
+ "aria-hidden": !0
1755
+ }),
1756
+ "Importar dump"
1757
+ ]
1758
+ })
1759
+ })
1760
+ ] });
1761
+ }
1762
+ //#endregion
1763
+ //#region src/components/MinivaultModule.tsx
1764
+ function Z(e) {
1765
+ let { companyAcronym: t = "Minivault", theme: n = "light", refetchIntervalMs: r = 15e3, storageType: i = "LOCAL", ...a } = e, [l] = o(() => new s({ defaultOptions: { queries: {
1766
+ refetchInterval: r,
1767
+ retry: 1
1768
+ } } }));
1769
+ return /* @__PURE__ */ p(c, {
1770
+ client: l,
1771
+ children: /* @__PURE__ */ p(y, {
1772
+ ...a,
1773
+ children: /* @__PURE__ */ m("div", {
1774
+ className: "minivault-module h-100 w-100 overflow-auto",
1775
+ "data-minivault-theme": n,
1776
+ children: [/* @__PURE__ */ p(Q, {
1777
+ companyAcronym: t,
1778
+ theme: n
1779
+ }), /* @__PURE__ */ p($, { storageType: i })]
1780
+ })
1781
+ })
1782
+ });
1783
+ }
1784
+ function Q({ companyAcronym: e, theme: t }) {
1785
+ return /* @__PURE__ */ m("div", {
1786
+ className: "d-flex align-items-center justify-content-between flex-wrap gap-2 px-3 py-2 border-bottom",
1787
+ style: {
1788
+ background: "var(--minivault-surface)",
1789
+ borderColor: "var(--minivault-border) !important"
1790
+ },
1791
+ children: [/* @__PURE__ */ m("div", {
1792
+ className: "d-flex align-items-center gap-2",
1793
+ children: [/* @__PURE__ */ p("span", {
1794
+ className: "p-2 rounded-2 d-inline-flex text-white",
1795
+ style: { background: "#0b3d91" },
1796
+ children: /* @__PURE__ */ p("i", {
1797
+ className: "bi bi-database-gear",
1798
+ "aria-hidden": !0
1799
+ })
1800
+ }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("strong", { children: [e, " · Backups"] }), /* @__PURE__ */ p("div", {
1801
+ className: "small text-muted",
1802
+ children: "Gerenciamento de backups de banco de dados"
1803
+ })] })]
1804
+ }), /* @__PURE__ */ p("div", {
1805
+ className: "d-flex align-items-center gap-2",
1806
+ children: /* @__PURE__ */ p("span", {
1807
+ className: "badge text-bg-secondary",
1808
+ children: t
1809
+ })
1810
+ })]
1811
+ });
1812
+ }
1813
+ function $({ storageType: e }) {
1814
+ let [t, n] = o("backups");
1815
+ return /* @__PURE__ */ m("div", {
1816
+ className: "p-3",
1817
+ children: [
1818
+ /* @__PURE__ */ m("ul", {
1819
+ className: "nav nav-tabs mb-3",
1820
+ children: [
1821
+ /* @__PURE__ */ p("li", {
1822
+ className: "nav-item",
1823
+ children: /* @__PURE__ */ m("button", {
1824
+ type: "button",
1825
+ className: `nav-link ${t === "backups" ? "active" : ""}`,
1826
+ onClick: () => n("backups"),
1827
+ children: [/* @__PURE__ */ p("i", {
1828
+ className: "bi bi-archive me-1",
1829
+ "aria-hidden": !0
1830
+ }), "Backups"]
1831
+ })
1832
+ }),
1833
+ /* @__PURE__ */ p("li", {
1834
+ className: "nav-item",
1835
+ children: /* @__PURE__ */ m("button", {
1836
+ type: "button",
1837
+ className: `nav-link ${t === "create" ? "active" : ""}`,
1838
+ onClick: () => n("create"),
1839
+ children: [/* @__PURE__ */ p("i", {
1840
+ className: "bi bi-plus-circle me-1",
1841
+ "aria-hidden": !0
1842
+ }), "Novo backup"]
1843
+ })
1844
+ }),
1845
+ /* @__PURE__ */ p("li", {
1846
+ className: "nav-item",
1847
+ children: /* @__PURE__ */ m("button", {
1848
+ type: "button",
1849
+ className: `nav-link ${t === "import" ? "active" : ""}`,
1850
+ onClick: () => n("import"),
1851
+ children: [/* @__PURE__ */ p("i", {
1852
+ className: "bi bi-file-earmark-arrow-up me-1",
1853
+ "aria-hidden": !0
1854
+ }), "Importar dump"]
1855
+ })
1856
+ }),
1857
+ /* @__PURE__ */ p("li", {
1858
+ className: "nav-item",
1859
+ children: /* @__PURE__ */ m("button", {
1860
+ type: "button",
1861
+ className: `nav-link ${t === "storage" ? "active" : ""}`,
1862
+ onClick: () => n("storage"),
1863
+ children: [/* @__PURE__ */ p("i", {
1864
+ className: "bi bi-folder2-open me-1",
1865
+ "aria-hidden": !0
1866
+ }), "Storage"]
1867
+ })
1868
+ })
1869
+ ]
1870
+ }),
1871
+ t === "backups" && /* @__PURE__ */ p(G, {}),
1872
+ t === "create" && /* @__PURE__ */ p(J, {}),
1873
+ t === "import" && /* @__PURE__ */ p(X, {}),
1874
+ t === "storage" && /* @__PURE__ */ p(Y, { storageType: e })
1875
+ ]
1876
+ });
1877
+ }
1878
+ //#endregion
1879
+ export { G as BackupsTab, J as CreateBackupTab, H as CredentialsFields, L as DATABASE_TYPE_LABELS, X as ImportDumpTab, g as MinivaultApi, h as MinivaultApiError, y as MinivaultApiProvider, Z as MinivaultModule, U as RestoreModal, I as STATUS_BADGE, F as STATUS_LABELS, R as StatusBadge, Y as StorageExplorerTab, P as formatDate, N as formatFileSize, C as useBackups, w as useCreateBackup, E as useDeleteBackup, O as useDownloadBackup, k as useImportDump, A as useImportFromStorage, b as useMinivaultApi, T as useRestoreBackup };