admindb 2.5.0 → 2.6.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.
Files changed (45) hide show
  1. package/dist/app.js +13 -1
  2. package/dist/core/diff/data-differ.d.ts +1 -0
  3. package/dist/core/diff/data-differ.js +243 -0
  4. package/dist/core/diff/patch-generator.d.ts +1 -0
  5. package/dist/core/diff/patch-generator.js +77 -0
  6. package/dist/core/diff/schema-differ.d.ts +1 -0
  7. package/dist/core/diff/schema-differ.js +229 -0
  8. package/dist/core/router.d.ts +1 -1
  9. package/dist/core/transfer/dialect-mapper.d.ts +1 -0
  10. package/dist/core/transfer/dialect-mapper.js +303 -0
  11. package/dist/core/transfer/masking.d.ts +1 -0
  12. package/dist/core/transfer/masking.js +49 -0
  13. package/dist/core/transfer/sync-engine.d.ts +1 -0
  14. package/dist/core/transfer/sync-engine.js +234 -0
  15. package/dist/core/transfer/topological-sort.d.ts +1 -0
  16. package/dist/core/transfer/topological-sort.js +55 -0
  17. package/dist/db/dialects/postgres/introspector.js +1 -1
  18. package/dist/db/dialects/sqlite/introspector.js +6 -3
  19. package/dist/modules/index.d.ts +1 -1
  20. package/dist/modules/index.js +9 -1
  21. package/dist/modules/search/index.d.ts +1 -0
  22. package/dist/modules/search/index.js +19 -0
  23. package/dist/modules/search/search.routes.d.ts +1 -0
  24. package/dist/modules/search/search.routes.js +38 -0
  25. package/dist/modules/search/search.service.d.ts +1 -0
  26. package/dist/modules/search/search.service.js +458 -0
  27. package/dist/modules/search/search.types.d.ts +1 -0
  28. package/dist/modules/search/search.types.js +2 -0
  29. package/dist/modules/sync/index.d.ts +1 -0
  30. package/dist/modules/sync/index.js +18 -0
  31. package/dist/modules/sync/sync.routes.d.ts +1 -0
  32. package/dist/modules/sync/sync.routes.js +135 -0
  33. package/dist/modules/sync/sync.service.d.ts +1 -0
  34. package/dist/modules/sync/sync.service.js +41 -0
  35. package/dist/public/css/app.css +1 -1
  36. package/dist/public/js/browse.js +1 -1
  37. package/dist/public/js/search.js +1 -0
  38. package/dist/public/js/sync.js +1 -0
  39. package/dist/utils/icons.js +3 -0
  40. package/dist/views/layouts/main.hbs +1 -1
  41. package/dist/views/pages/sync.hbs +409 -0
  42. package/dist/views/pages/table.hbs +1 -1
  43. package/dist/views/partials/navbar.hbs +1 -1
  44. package/dist/views/partials/sidebar.hbs +1 -1
  45. package/package.json +7 -8
@@ -0,0 +1,409 @@
1
+ <div class="space-y-6 max-w-7xl mx-auto">
2
+ <div class="relative overflow-hidden rounded-2xl border border-primary/20 bg-gradient-to-br from-base-100 via-base-200/50 to-primary/5 p-6 shadow-sm">
3
+ <div class="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
4
+ <div>
5
+ <div class="flex items-center gap-2 mb-1">
6
+ <span class="badge badge-primary badge-sm font-mono uppercase tracking-wider font-bold">Studio</span>
7
+ <span class="text-xs text-base-content/50 font-mono">SQLite ⇄ PostgreSQL</span>
8
+ </div>
9
+ <h1 class="text-2xl font-bold tracking-tight flex items-center gap-2.5">
10
+ <span class="p-2 rounded-xl bg-primary/10 text-primary border border-primary/20 shadow-inner">
11
+ {{{icon "diff" class="h-6 w-6"}}}
12
+ </span>
13
+ Diff & Replication Studio
14
+ </h1>
15
+ <p class="mt-1.5 text-xs text-base-content/70 max-w-2xl leading-relaxed">
16
+ Compare database schemas with Git-style unified diffs, inspect table data row-by-row, generate UP/DOWN SQL migration patches, and safely clone databases across engines and environments.
17
+ </p>
18
+ </div>
19
+ <div class="flex flex-wrap items-center gap-2 pt-2 md:pt-0">
20
+ <button id="btn-generate-sql" type="button" class="btn btn-outline btn-sm gap-1.5 shadow-sm transition hover:scale-[1.02]" disabled title="Generate UP and DOWN SQL migration scripts">
21
+ {{{icon "sql" class="h-4 w-4 text-primary"}}}
22
+ Migration SQL
23
+ </button>
24
+ <button id="btn-dry-run" type="button" class="btn btn-outline btn-info btn-sm gap-1.5 shadow-sm transition hover:scale-[1.02]" disabled title="Simulate replication without writing data">
25
+ {{{icon "inspect" class="h-4 w-4"}}}
26
+ Dry Run
27
+ </button>
28
+ <button id="btn-execute-sync" type="button" class="btn btn-primary btn-sm gap-1.5 shadow-sm transition hover:scale-[1.02]" disabled title="Synchronize / replicate data">
29
+ {{{icon "sync" class="h-4 w-4"}}}
30
+ Replicate Database
31
+ </button>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="app-card border border-base-300 p-5 shadow-sm space-y-4">
36
+ <div class="grid grid-cols-1 items-center gap-4 lg:grid-cols-[1fr,auto,1fr]">
37
+ <div class="rounded-xl border border-emerald-500/30 bg-emerald-500/[0.03] p-4 space-y-3 transition hover:border-emerald-500/50">
38
+ <div class="flex items-center justify-between">
39
+ <span class="text-xs font-bold uppercase tracking-wider text-emerald-600 dark:text-emerald-400 flex items-center gap-1.5">
40
+ <span class="relative flex h-2 w-2">
41
+ <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
42
+ <span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
43
+ </span>
44
+ Source Database (Origin)
45
+ </span>
46
+ <span id="src-badge-engine" class="badge badge-sm font-mono badge-success">SQLite</span>
47
+ </div>
48
+ <div>
49
+ <label class="text-[11px] font-semibold text-base-content/60 mb-1 block">Choose source instance:</label>
50
+ <select id="select-source-db" class="select select-bordered select-sm w-full font-mono text-xs focus:border-emerald-500">
51
+ <option value="" disabled selected>Select source database…</option>
52
+ {{#each databases}}
53
+ <option value="{{this.id}}" data-dialect="{{this.dialect}}" data-readonly="{{this.readonly}}" {{#if (eq this.id ../dbId)}}selected{{/if}}>
54
+ {{this.name}} ({{this.dialect}}{{#if this.readonly}} · Read-only{{/if}})
55
+ </option>
56
+ {{/each}}
57
+ </select>
58
+ </div>
59
+ <div class="flex items-center justify-between text-[11px] text-base-content/50 font-mono truncate" id="src-path-label">
60
+ <span>Select database above</span>
61
+ </div>
62
+ </div>
63
+ <div class="flex flex-col items-center justify-center gap-1">
64
+ <button id="btn-swap-dbs" type="button" class="btn btn-circle btn-sm btn-ghost border border-base-300 shadow-sm hover:bg-primary/10 hover:text-primary hover:border-primary/40 hover:rotate-180 transition-all duration-300" title="Swap direction (Source ⇄ Target)">
65
+ {{{icon "swap" class="h-4 w-4"}}}
66
+ </button>
67
+ <span class="text-[10px] uppercase font-mono tracking-widest text-base-content/40 font-semibold">Transfer</span>
68
+ </div>
69
+ <div class="rounded-xl border border-info/30 bg-info/[0.03] p-4 space-y-3 transition hover:border-info/50">
70
+ <div class="flex items-center justify-between">
71
+ <span class="text-xs font-bold uppercase tracking-wider text-info flex items-center gap-1.5">
72
+ <span class="relative flex h-2 w-2">
73
+ <span class="relative inline-flex rounded-full h-2 w-2 bg-info"></span>
74
+ </span>
75
+ Target Database (Destination)
76
+ </span>
77
+ <span id="tgt-badge-engine" class="badge badge-sm font-mono badge-info">PostgreSQL</span>
78
+ </div>
79
+ <div>
80
+ <label class="text-[11px] font-semibold text-base-content/60 mb-1 block">Choose target destination:</label>
81
+ <select id="select-target-db" class="select select-bordered select-sm w-full font-mono text-xs focus:border-info">
82
+ <option value="" disabled selected>Select target database…</option>
83
+ {{#each databases}}
84
+ <option value="{{this.id}}" data-dialect="{{this.dialect}}" data-readonly="{{this.readonly}}">
85
+ {{this.name}} ({{this.dialect}}{{#if this.readonly}} · Read-only{{/if}})
86
+ </option>
87
+ {{/each}}
88
+ </select>
89
+ </div>
90
+ <div class="flex items-center justify-between text-[11px] text-base-content/50 font-mono truncate" id="tgt-path-label">
91
+ <span>Select target database above</span>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <div class="pt-3 border-t border-base-200 flex flex-wrap items-center justify-between gap-3">
96
+ <div class="flex items-center gap-2 text-xs text-base-content/60">
97
+ <span class="badge badge-xs badge-info"></span>
98
+ <span>Select source and target instances to run schema diffing or cross-database replication.</span>
99
+ </div>
100
+ <button id="btn-compare-now" type="button" class="btn btn-primary btn-sm gap-1.5 shadow-sm transition hover:scale-[1.02]">
101
+ {{{icon "search" class="h-4 w-4"}}}
102
+ Compare Diff Now
103
+ </button>
104
+ </div>
105
+ </div>
106
+ <div class="app-card border border-base-300 overflow-hidden shadow-sm">
107
+ <div class="p-4 bg-base-200/40 border-b border-base-200 flex items-center justify-between cursor-pointer select-none transition hover:bg-base-200/60" id="toggle-options-header">
108
+ <div class="flex items-center gap-2.5">
109
+ <span class="p-1 rounded bg-base-300/60 text-base-content/70">
110
+ {{{icon "settings" class="h-4 w-4"}}}
111
+ </span>
112
+ <span class="text-sm font-bold tracking-tight">Replication & Safety Options</span>
113
+ <span class="badge badge-sm badge-outline font-mono text-[10px]" id="badge-active-mode">Full Clone</span>
114
+ </div>
115
+ <div class="flex items-center gap-2 text-xs text-base-content/50 font-mono">
116
+ <span id="options-toggle-hint">Customize mode, masking & tables</span>
117
+ {{{icon "chevronDown" class="h-3.5 w-3.5 transition-transform duration-200" id="options-chevron"}}}
118
+ </div>
119
+ </div>
120
+ <div class="p-5 space-y-5 hidden" id="options-panel">
121
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
122
+ <div class="space-y-2.5">
123
+ <label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70">Select Replication Strategy</label>
124
+ <div class="space-y-2.5">
125
+ <label class="flex items-start gap-3 p-3 rounded-xl border border-base-300 bg-base-100 hover:border-primary/40 hover:bg-primary/[0.02] cursor-pointer transition">
126
+ <input type="radio" name="sync-mode" value="full" class="radio radio-primary radio-sm mt-0.5" checked />
127
+ <div>
128
+ <div class="text-xs font-bold text-base-content flex items-center gap-2">
129
+ Full Clone
130
+ <span class="badge badge-xs badge-error">Drops & Recreates</span>
131
+ </div>
132
+ <div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
133
+ Drops target tables in dependency order, recreates DDL matching source schema, and transfers all records with automatic sequence sync.
134
+ </div>
135
+ </div>
136
+ </label>
137
+ <label class="flex items-start gap-3 p-3 rounded-xl border border-base-300 bg-base-100 hover:border-primary/40 hover:bg-primary/[0.02] cursor-pointer transition">
138
+ <input type="radio" name="sync-mode" value="schema_only" class="radio radio-primary radio-sm mt-0.5" />
139
+ <div>
140
+ <div class="text-xs font-bold text-base-content flex items-center gap-2">
141
+ Schema Only
142
+ <span class="badge badge-xs badge-success">Non-Destructive</span>
143
+ </div>
144
+ <div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
145
+ Creates missing tables, columns, indexes, and constraints without touching or transferring row records.
146
+ </div>
147
+ </div>
148
+ </label>
149
+ <label class="flex items-start gap-3 p-3 rounded-xl border border-base-300 bg-base-100 hover:border-primary/40 hover:bg-primary/[0.02] cursor-pointer transition">
150
+ <input type="radio" name="sync-mode" value="data_only_replace" class="radio radio-primary radio-sm mt-0.5" />
151
+ <div>
152
+ <div class="text-xs font-bold text-base-content flex items-center gap-2">
153
+ Data Only (Clean & Replace)
154
+ <span class="badge badge-xs badge-warning">Truncates Data</span>
155
+ </div>
156
+ <div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
157
+ Preserves existing target table schemas, truncates target data rows, and streams fresh records from source.
158
+ </div>
159
+ </div>
160
+ </label>
161
+ </div>
162
+ </div>
163
+ <div class="space-y-4">
164
+ <div>
165
+ <label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70">Anonymization & Privacy Guard</label>
166
+ <div class="p-3.5 rounded-xl border border-warning/30 bg-warning/[0.03] space-y-2">
167
+ <label class="flex items-start gap-3 cursor-pointer">
168
+ <input type="checkbox" id="chk-mask-data" class="checkbox checkbox-warning checkbox-sm mt-0.5" checked />
169
+ <div>
170
+ <div class="text-xs font-bold text-warning flex items-center gap-1.5">
171
+ {{{icon "lock" class="h-3.5 w-3.5"}}}
172
+ Anonymize Sensitive Data (Prod ➔ Test Masking)
173
+ </div>
174
+ <div class="text-[11px] text-base-content/65 mt-0.5 leading-relaxed">
175
+ Automatically replaces emails (<code class="font-mono text-[10px]">user1@masked.test</code>), password hashes, phone numbers, and full names with synthetic mock data during replication.
176
+ </div>
177
+ </div>
178
+ </label>
179
+ </div>
180
+ </div>
181
+ <div>
182
+ <div class="flex items-center justify-between mb-1.5">
183
+ <label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70 mb-0">Tables to Transfer</label>
184
+ <div class="flex items-center gap-2 text-xs">
185
+ <button type="button" id="btn-select-all-tables" class="text-primary font-semibold hover:underline">Select All</button>
186
+ <span class="text-base-content/30">|</span>
187
+ <button type="button" id="btn-deselect-all-tables" class="text-base-content/60 hover:underline">Clear</button>
188
+ </div>
189
+ </div>
190
+ <div id="table-checkboxes-container" class="max-h-40 overflow-y-auto p-2.5 rounded-xl border border-base-300 bg-base-100 divide-y divide-base-200/50 text-xs font-mono">
191
+ <span class="text-base-content/40 italic p-1 block">Select source database above to load tables.</span>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ </div>
198
+ <div class="app-card border border-base-300 overflow-hidden shadow-sm">
199
+ <div class="border-b border-base-300 bg-base-200/50 px-4 pt-3 flex flex-wrap items-center justify-between gap-3">
200
+ <div class="tabs tabs-boxed bg-base-300/40 p-1 gap-1 rounded-xl" id="diff-tabs">
201
+ <button type="button" class="tab tab-sm tab-active font-semibold gap-1.5 rounded-lg" data-tab="unified">
202
+ {{{icon "diff" class="h-3.5 w-3.5"}}}
203
+ Git Unified Diff
204
+ </button>
205
+ <button type="button" class="tab tab-sm font-semibold gap-1.5 rounded-lg" data-tab="visual">
206
+ {{{icon "table" class="h-3.5 w-3.5"}}}
207
+ Visual Breakdown
208
+ </button>
209
+ <button type="button" class="tab tab-sm font-semibold gap-1.5 rounded-lg" data-tab="data">
210
+ {{{icon "inspect" class="h-3.5 w-3.5"}}}
211
+ Data Diff (Row-by-Row)
212
+ </button>
213
+ </div>
214
+ <div class="flex items-center gap-2 pb-2 text-xs" id="diff-stats-chips">
215
+ </div>
216
+ </div>
217
+ <div id="tab-content-unified" class="p-5 space-y-3">
218
+ <div class="flex items-center justify-between text-xs text-base-content/60">
219
+ <span class="font-mono text-[11px] flex items-center gap-1.5">
220
+ <span class="h-2 w-2 rounded-full bg-primary"></span>
221
+ Standard Git Patch format · Green (+) additions, Red (-) deletions, Amber (~) modifications
222
+ </span>
223
+ <button id="btn-copy-unified-diff" type="button" class="btn btn-ghost btn-xs gap-1 font-mono hover:text-primary">
224
+ {{{icon "copy" class="h-3 w-3"}}}
225
+ Copy Diff Text
226
+ </button>
227
+ </div>
228
+ <div id="unified-diff-view" class="bg-neutral text-neutral-content rounded-xl p-4 font-mono text-xs overflow-x-auto min-h-[300px] max-h-[600px] leading-relaxed select-text border border-neutral-focus shadow-inner">
229
+ <div class="text-neutral-content/40 italic text-center py-20">
230
+ Select source and target instances above and click <strong>Compare Diff Now</strong> to compute git-style schema differences.
231
+ </div>
232
+ </div>
233
+ </div>
234
+ <div id="tab-content-visual" class="p-5 hidden space-y-4">
235
+ <div class="flex flex-wrap items-center justify-between gap-3 p-2 rounded-xl bg-base-200/50 border border-base-300">
236
+ <div class="relative flex-1 min-w-[200px]">
237
+ <span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/40 pointer-events-none">
238
+ {{{icon "search" class="h-3.5 w-3.5"}}}
239
+ </span>
240
+ <input type="text" id="input-filter-visual-tables" class="input input-sm input-bordered w-full pl-8 font-mono text-xs" placeholder="Filter tables by name…" autocomplete="off" />
241
+ </div>
242
+ <div class="flex items-center gap-1 text-xs" id="filter-status-buttons">
243
+ <button type="button" class="btn btn-xs btn-ghost btn-active js-filter-status" data-filter="all">All</button>
244
+ <button type="button" class="btn btn-xs btn-ghost js-filter-status text-warning" data-filter="modified">Modified</button>
245
+ <button type="button" class="btn btn-xs btn-ghost js-filter-status text-success" data-filter="added">Added</button>
246
+ <button type="button" class="btn btn-xs btn-ghost js-filter-status text-error" data-filter="removed">Removed</button>
247
+ </div>
248
+ </div>
249
+ <div id="visual-diff-cards" class="space-y-3">
250
+ <div class="text-base-content/40 italic text-center py-20">
251
+ No comparison performed yet. Select databases and click "Compare Diff Now".
252
+ </div>
253
+ </div>
254
+ </div>
255
+ <div id="tab-content-data" class="p-5 hidden space-y-4">
256
+ <div class="flex flex-wrap items-center justify-between gap-3 p-3 rounded-xl bg-base-200/50 border border-base-300">
257
+ <div class="flex flex-wrap items-center gap-2.5">
258
+ <label class="text-xs font-bold uppercase tracking-wider text-base-content/60">Table to Compare:</label>
259
+ <select id="select-data-diff-table" class="select select-bordered select-xs font-mono min-w-[180px]">
260
+ <option value="" disabled selected>Select table…</option>
261
+ </select>
262
+ <label class="text-xs font-bold uppercase tracking-wider text-base-content/60 ml-2">Sample Limit:</label>
263
+ <select id="select-data-diff-limit" class="select select-bordered select-xs font-mono">
264
+ <option value="50">50 rows</option>
265
+ <option value="150" selected>150 rows</option>
266
+ <option value="300">300 rows</option>
267
+ <option value="500">500 rows</option>
268
+ </select>
269
+ <button id="btn-fetch-data-diff" type="button" class="btn btn-primary btn-xs gap-1 shadow-sm">
270
+ {{{icon "refresh" class="h-3 w-3"}}}
271
+ Compare Rows
272
+ </button>
273
+ </div>
274
+ <div id="data-diff-stats" class="flex items-center gap-1.5 text-xs font-mono"></div>
275
+ </div>
276
+ <div id="data-diff-results" class="bg-base-200/30 rounded-xl p-4 font-mono text-xs overflow-x-auto min-h-[250px] max-h-[550px] border border-base-300">
277
+ <div class="text-base-content/40 italic text-center py-16">
278
+ Select a table and click <strong>Compare Rows</strong> to inspect added, removed, and modified data rows.
279
+ </div>
280
+ </div>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ <dialog id="modal-sql-patch" class="modal">
285
+ <div class="modal-box max-w-3xl border border-base-300 bg-base-100 p-6 space-y-4 shadow-2xl">
286
+ <div class="flex items-center justify-between border-b border-base-200 pb-3">
287
+ <h3 class="font-bold text-base flex items-center gap-2">
288
+ <span class="p-1 rounded bg-primary/10 text-primary">
289
+ {{{icon "sql" class="h-5 w-5"}}}
290
+ </span>
291
+ Generated Migration SQL Patch
292
+ </h3>
293
+ <form method="dialog">
294
+ <button class="btn btn-sm btn-circle btn-ghost">✕</button>
295
+ </form>
296
+ </div>
297
+ <div class="tabs tabs-boxed bg-base-200/60 p-1 gap-1 rounded-xl">
298
+ <button type="button" id="tab-up-sql" class="tab tab-sm tab-active font-bold rounded-lg">UP Script (Migrate Target)</button>
299
+ <button type="button" id="tab-down-sql" class="tab tab-sm font-bold rounded-lg">DOWN Script (Rollback Changes)</button>
300
+ </div>
301
+ <div class="relative">
302
+ <pre id="patch-sql-code" class="bg-neutral text-neutral-content p-4 rounded-xl font-mono text-xs max-h-96 overflow-auto border border-neutral-focus select-all shadow-inner leading-relaxed"></pre>
303
+ <div class="absolute top-3 right-3 flex items-center gap-1.5">
304
+ <button id="btn-copy-patch-sql" type="button" class="btn btn-xs btn-outline gap-1 bg-base-100 shadow-sm text-base-content hover:bg-base-200">
305
+ {{{icon "copy" class="h-3 w-3"}}}
306
+ Copy SQL
307
+ </button>
308
+ </div>
309
+ </div>
310
+ <div class="modal-action flex justify-between items-center pt-2 border-t border-base-200">
311
+ <span class="text-xs text-base-content/50">Run this script in your target database query editor to align schema structure.</span>
312
+ <form method="dialog">
313
+ <button class="btn btn-sm">Close</button>
314
+ </form>
315
+ </div>
316
+ </div>
317
+ <form method="dialog" class="modal-backdrop">
318
+ <button>close</button>
319
+ </form>
320
+ </dialog>
321
+ <dialog id="modal-sync-execute" class="modal">
322
+ <div class="modal-box max-w-lg border border-base-300 bg-base-100 p-6 space-y-4 shadow-2xl">
323
+ <div class="flex items-center justify-between border-b border-base-200 pb-3">
324
+ <h3 class="font-bold text-base flex items-center gap-2" id="exec-modal-title">
325
+ <span class="p-1 rounded bg-error/10 text-error" id="exec-modal-icon-badge">
326
+ {{{icon "warning" class="h-5 w-5"}}}
327
+ </span>
328
+ Confirm Replication Execution
329
+ </h3>
330
+ <form method="dialog">
331
+ <button id="btn-exec-close-x" class="btn btn-sm btn-circle btn-ghost">✕</button>
332
+ </form>
333
+ </div>
334
+ <div id="exec-prompt-content" class="space-y-4 text-xs leading-relaxed">
335
+ <div id="exec-destructive-banner" class="p-4 rounded-xl border border-error/40 bg-error/[0.06] text-error space-y-2.5">
336
+ <div class="font-bold flex items-center gap-2 text-sm">
337
+ {{{icon "warning" class="h-4 w-4 shrink-0 text-error"}}}
338
+ Caution: Destructive Action Ahead!
339
+ </div>
340
+ <p class="text-[11.5px] leading-relaxed text-base-content/80">
341
+ This operation will <strong class="text-error font-bold" id="lbl-destructive-action-desc">permanently drop/truncate</strong> existing tables and data on target database <code class="font-mono font-bold text-error px-1 py-0.5 rounded bg-error/10" id="lbl-confirm-tgt-highlight"></code>.
342
+ </p>
343
+ <div class="text-[11px] text-base-content/60 font-mono">
344
+ Affected tables: <span id="lbl-affected-tables-list" class="font-bold text-base-content">All selected tables</span>
345
+ </div>
346
+ </div>
347
+ <div class="p-3.5 rounded-xl border border-base-200 bg-base-200/40 space-y-1.5 font-mono text-[11.5px]">
348
+ <div class="flex justify-between">
349
+ <span class="text-base-content/60">Source (Origin):</span>
350
+ <span id="lbl-confirm-src" class="font-bold text-emerald-600 dark:text-emerald-400"></span>
351
+ </div>
352
+ <div class="flex justify-between">
353
+ <span class="text-base-content/60">Target (Destination):</span>
354
+ <span id="lbl-confirm-tgt" class="font-bold text-info"></span>
355
+ </div>
356
+ <div class="flex justify-between">
357
+ <span class="text-base-content/60">Selected Mode:</span>
358
+ <span id="lbl-confirm-mode" class="font-bold"></span>
359
+ </div>
360
+ <div class="flex justify-between">
361
+ <span class="text-base-content/60">PII Data Anonymization:</span>
362
+ <span id="lbl-confirm-mask" class="font-bold text-warning"></span>
363
+ </div>
364
+ <div class="flex justify-between">
365
+ <span class="text-base-content/60">Tables Selected:</span>
366
+ <span id="lbl-confirm-tables" class="font-bold"></span>
367
+ </div>
368
+ </div>
369
+ <div id="exec-safety-locks" class="space-y-3 pt-1">
370
+ <label class="flex items-start gap-2.5 p-2.5 rounded-lg border border-base-300 bg-base-100 hover:bg-base-200/50 cursor-pointer">
371
+ <input type="checkbox" id="chk-confirm-destruction" class="checkbox checkbox-error checkbox-sm mt-0.5" />
372
+ <span class="text-[11.5px] font-medium text-base-content/80 select-none">
373
+ I understand that existing tables and records on the target database will be overwritten.
374
+ </span>
375
+ </label>
376
+ <div id="box-confirm-phrase" class="space-y-1.5">
377
+ <label class="text-[11px] font-bold text-base-content/70 block">
378
+ Type <code class="font-mono text-error font-bold px-1 rounded bg-error/10" id="lbl-required-confirm-word">OVERWRITE</code> to unlock replication:
379
+ </label>
380
+ <input type="text" id="input-confirm-phrase" class="input input-sm input-bordered w-full font-mono text-xs bg-base-100 focus:border-error" placeholder="Type here to confirm" autocomplete="off" spellcheck="false" />
381
+ </div>
382
+ </div>
383
+ </div>
384
+ <div id="exec-progress-container" class="space-y-3 hidden">
385
+ <div class="flex items-center justify-between text-xs font-mono">
386
+ <span id="exec-current-table" class="font-semibold flex items-center gap-2">
387
+ <span class="loading loading-spinner loading-xs text-primary"></span>
388
+ Synchronizing records...
389
+ </span>
390
+ <span id="exec-progress-percent" class="text-primary font-bold">0%</span>
391
+ </div>
392
+ <progress id="exec-progress-bar" class="progress progress-primary w-full h-3" value="0" max="100"></progress>
393
+ <div id="exec-log-container" class="max-h-40 overflow-y-auto font-mono text-[11px] p-3 rounded-xl bg-neutral text-neutral-content border border-neutral-focus space-y-1 select-text"></div>
394
+ </div>
395
+ <div class="modal-action pt-3 border-t border-base-200 flex justify-between items-center" id="exec-modal-buttons">
396
+ <form method="dialog">
397
+ <button id="btn-exec-cancel" class="btn btn-sm btn-ghost">Cancel</button>
398
+ </form>
399
+ <button id="btn-exec-start" type="button" class="btn btn-sm btn-error gap-1.5 shadow-sm" disabled>
400
+ {{{icon "sync" class="h-4 w-4"}}}
401
+ Confirm & Start Replication
402
+ </button>
403
+ </div>
404
+ </div>
405
+ <form method="dialog" class="modal-backdrop">
406
+ <button>close</button>
407
+ </form>
408
+ </dialog>
409
+ <script src="{{basePath}}/js/sync.js" defer></script>