admindb 2.6.0 → 2.6.2
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.
- package/LICENSE +20 -20
- package/dist/db/dialects/postgres/introspector.js +70 -70
- package/dist/public/css/app.css +2 -1
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/seed-select.hbs +252 -1
- package/dist/views/pages/seed.hbs +307 -1
- package/dist/views/pages/sync.hbs +1 -409
- package/docs/EXAMPLES.md +579 -579
- package/docs/SECURITY.md +265 -265
- package/package.json +9 -3
|
@@ -1,409 +1 @@
|
|
|
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>
|
|
1
|
+
<div class="space-y-6 max-w-7xl mx-auto">
|
|
410
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">
|
|
411
3
|
<div class="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
412
4
|
<div>
|
|
413
5
|
<div class="flex items-center gap-2 mb-1">
|
|
414
6
|
<span class="badge badge-primary badge-sm font-mono uppercase tracking-wider font-bold">Studio</span>
|
|
415
7
|
<span class="text-xs text-base-content/50 font-mono">SQLite ⇄ PostgreSQL</span>
|
|
416
8
|
</div>
|
|
417
9
|
<h1 class="text-2xl font-bold tracking-tight flex items-center gap-2.5">
|
|
418
10
|
<span class="p-2 rounded-xl bg-primary/10 text-primary border border-primary/20 shadow-inner">
|
|
419
11
|
{{{icon "diff" class="h-6 w-6"}}}
|
|
420
12
|
</span>
|
|
421
13
|
Diff & Replication Studio
|
|
422
14
|
</h1>
|
|
423
15
|
<p class="mt-1.5 text-xs text-base-content/70 max-w-2xl leading-relaxed">
|
|
424
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.
|
|
425
17
|
</p>
|
|
426
18
|
</div>
|
|
427
19
|
<div class="flex flex-wrap items-center gap-2 pt-2 md:pt-0">
|
|
428
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">
|
|
429
21
|
{{{icon "sql" class="h-4 w-4 text-primary"}}}
|
|
430
22
|
Migration SQL
|
|
431
23
|
</button>
|
|
432
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">
|
|
433
25
|
{{{icon "inspect" class="h-4 w-4"}}}
|
|
434
26
|
Dry Run
|
|
435
27
|
</button>
|
|
436
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">
|
|
437
29
|
{{{icon "sync" class="h-4 w-4"}}}
|
|
438
30
|
Replicate Database
|
|
439
31
|
</button>
|
|
440
32
|
</div>
|
|
441
33
|
</div>
|
|
442
34
|
</div>
|
|
443
35
|
<div class="app-card border border-base-300 p-5 shadow-sm space-y-4">
|
|
444
36
|
<div class="grid grid-cols-1 items-center gap-4 lg:grid-cols-[1fr,auto,1fr]">
|
|
445
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">
|
|
446
38
|
<div class="flex items-center justify-between">
|
|
447
39
|
<span class="text-xs font-bold uppercase tracking-wider text-emerald-600 dark:text-emerald-400 flex items-center gap-1.5">
|
|
448
40
|
<span class="relative flex h-2 w-2">
|
|
449
41
|
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
|
450
42
|
<span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
|
|
451
43
|
</span>
|
|
452
44
|
Source Database (Origin)
|
|
453
45
|
</span>
|
|
454
46
|
<span id="src-badge-engine" class="badge badge-sm font-mono badge-success">SQLite</span>
|
|
455
47
|
</div>
|
|
456
48
|
<div>
|
|
457
49
|
<label class="text-[11px] font-semibold text-base-content/60 mb-1 block">Choose source instance:</label>
|
|
458
50
|
<select id="select-source-db" class="select select-bordered select-sm w-full font-mono text-xs focus:border-emerald-500">
|
|
459
51
|
<option value="" disabled selected>Select source database…</option>
|
|
460
52
|
{{#each databases}}
|
|
461
53
|
<option value="{{this.id}}" data-dialect="{{this.dialect}}" data-readonly="{{this.readonly}}" {{#if (eq this.id ../dbId)}}selected{{/if}}>
|
|
462
54
|
{{this.name}} ({{this.dialect}}{{#if this.readonly}} · Read-only{{/if}})
|
|
463
55
|
</option>
|
|
464
56
|
{{/each}}
|
|
465
57
|
</select>
|
|
466
58
|
</div>
|
|
467
59
|
<div class="flex items-center justify-between text-[11px] text-base-content/50 font-mono truncate" id="src-path-label">
|
|
468
60
|
<span>Select database above</span>
|
|
469
61
|
</div>
|
|
470
62
|
</div>
|
|
471
63
|
<div class="flex flex-col items-center justify-center gap-1">
|
|
472
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)">
|
|
473
65
|
{{{icon "swap" class="h-4 w-4"}}}
|
|
474
66
|
</button>
|
|
475
67
|
<span class="text-[10px] uppercase font-mono tracking-widest text-base-content/40 font-semibold">Transfer</span>
|
|
476
68
|
</div>
|
|
477
69
|
<div class="rounded-xl border border-info/30 bg-info/[0.03] p-4 space-y-3 transition hover:border-info/50">
|
|
478
70
|
<div class="flex items-center justify-between">
|
|
479
71
|
<span class="text-xs font-bold uppercase tracking-wider text-info flex items-center gap-1.5">
|
|
480
72
|
<span class="relative flex h-2 w-2">
|
|
481
73
|
<span class="relative inline-flex rounded-full h-2 w-2 bg-info"></span>
|
|
482
74
|
</span>
|
|
483
75
|
Target Database (Destination)
|
|
484
76
|
</span>
|
|
485
77
|
<span id="tgt-badge-engine" class="badge badge-sm font-mono badge-info">PostgreSQL</span>
|
|
486
78
|
</div>
|
|
487
79
|
<div>
|
|
488
80
|
<label class="text-[11px] font-semibold text-base-content/60 mb-1 block">Choose target destination:</label>
|
|
489
81
|
<select id="select-target-db" class="select select-bordered select-sm w-full font-mono text-xs focus:border-info">
|
|
490
82
|
<option value="" disabled selected>Select target database…</option>
|
|
491
83
|
{{#each databases}}
|
|
492
84
|
<option value="{{this.id}}" data-dialect="{{this.dialect}}" data-readonly="{{this.readonly}}">
|
|
493
85
|
{{this.name}} ({{this.dialect}}{{#if this.readonly}} · Read-only{{/if}})
|
|
494
86
|
</option>
|
|
495
87
|
{{/each}}
|
|
496
88
|
</select>
|
|
497
89
|
</div>
|
|
498
90
|
<div class="flex items-center justify-between text-[11px] text-base-content/50 font-mono truncate" id="tgt-path-label">
|
|
499
91
|
<span>Select target database above</span>
|
|
500
92
|
</div>
|
|
501
93
|
</div>
|
|
502
94
|
</div>
|
|
503
95
|
<div class="pt-3 border-t border-base-200 flex flex-wrap items-center justify-between gap-3">
|
|
504
96
|
<div class="flex items-center gap-2 text-xs text-base-content/60">
|
|
505
97
|
<span class="badge badge-xs badge-info"></span>
|
|
506
98
|
<span>Select source and target instances to run schema diffing or cross-database replication.</span>
|
|
507
99
|
</div>
|
|
508
100
|
<button id="btn-compare-now" type="button" class="btn btn-primary btn-sm gap-1.5 shadow-sm transition hover:scale-[1.02]">
|
|
509
101
|
{{{icon "search" class="h-4 w-4"}}}
|
|
510
102
|
Compare Diff Now
|
|
511
103
|
</button>
|
|
512
104
|
</div>
|
|
513
105
|
</div>
|
|
514
106
|
<div class="app-card border border-base-300 overflow-hidden shadow-sm">
|
|
515
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">
|
|
516
108
|
<div class="flex items-center gap-2.5">
|
|
517
109
|
<span class="p-1 rounded bg-base-300/60 text-base-content/70">
|
|
518
110
|
{{{icon "settings" class="h-4 w-4"}}}
|
|
519
111
|
</span>
|
|
520
112
|
<span class="text-sm font-bold tracking-tight">Replication & Safety Options</span>
|
|
521
113
|
<span class="badge badge-sm badge-outline font-mono text-[10px]" id="badge-active-mode">Full Clone</span>
|
|
522
114
|
</div>
|
|
523
115
|
<div class="flex items-center gap-2 text-xs text-base-content/50 font-mono">
|
|
524
116
|
<span id="options-toggle-hint">Customize mode, masking & tables</span>
|
|
525
117
|
{{{icon "chevronDown" class="h-3.5 w-3.5 transition-transform duration-200" id="options-chevron"}}}
|
|
526
118
|
</div>
|
|
527
119
|
</div>
|
|
528
120
|
<div class="p-5 space-y-5 hidden" id="options-panel">
|
|
529
121
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
530
122
|
<div class="space-y-2.5">
|
|
531
123
|
<label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70">Select Replication Strategy</label>
|
|
532
124
|
<div class="space-y-2.5">
|
|
533
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">
|
|
534
126
|
<input type="radio" name="sync-mode" value="full" class="radio radio-primary radio-sm mt-0.5" checked />
|
|
535
127
|
<div>
|
|
536
128
|
<div class="text-xs font-bold text-base-content flex items-center gap-2">
|
|
537
129
|
Full Clone
|
|
538
130
|
<span class="badge badge-xs badge-error">Drops & Recreates</span>
|
|
539
131
|
</div>
|
|
540
132
|
<div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
|
|
541
133
|
Drops target tables in dependency order, recreates DDL matching source schema, and transfers all records with automatic sequence sync.
|
|
542
134
|
</div>
|
|
543
135
|
</div>
|
|
544
136
|
</label>
|
|
545
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">
|
|
546
138
|
<input type="radio" name="sync-mode" value="schema_only" class="radio radio-primary radio-sm mt-0.5" />
|
|
547
139
|
<div>
|
|
548
140
|
<div class="text-xs font-bold text-base-content flex items-center gap-2">
|
|
549
141
|
Schema Only
|
|
550
142
|
<span class="badge badge-xs badge-success">Non-Destructive</span>
|
|
551
143
|
</div>
|
|
552
144
|
<div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
|
|
553
145
|
Creates missing tables, columns, indexes, and constraints without touching or transferring row records.
|
|
554
146
|
</div>
|
|
555
147
|
</div>
|
|
556
148
|
</label>
|
|
557
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">
|
|
558
150
|
<input type="radio" name="sync-mode" value="data_only_replace" class="radio radio-primary radio-sm mt-0.5" />
|
|
559
151
|
<div>
|
|
560
152
|
<div class="text-xs font-bold text-base-content flex items-center gap-2">
|
|
561
153
|
Data Only (Clean & Replace)
|
|
562
154
|
<span class="badge badge-xs badge-warning">Truncates Data</span>
|
|
563
155
|
</div>
|
|
564
156
|
<div class="text-[11px] text-base-content/60 mt-0.5 leading-relaxed">
|
|
565
157
|
Preserves existing target table schemas, truncates target data rows, and streams fresh records from source.
|
|
566
158
|
</div>
|
|
567
159
|
</div>
|
|
568
160
|
</label>
|
|
569
161
|
</div>
|
|
570
162
|
</div>
|
|
571
163
|
<div class="space-y-4">
|
|
572
164
|
<div>
|
|
573
165
|
<label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70">Anonymization & Privacy Guard</label>
|
|
574
166
|
<div class="p-3.5 rounded-xl border border-warning/30 bg-warning/[0.03] space-y-2">
|
|
575
167
|
<label class="flex items-start gap-3 cursor-pointer">
|
|
576
168
|
<input type="checkbox" id="chk-mask-data" class="checkbox checkbox-warning checkbox-sm mt-0.5" checked />
|
|
577
169
|
<div>
|
|
578
170
|
<div class="text-xs font-bold text-warning flex items-center gap-1.5">
|
|
579
171
|
{{{icon "lock" class="h-3.5 w-3.5"}}}
|
|
580
172
|
Anonymize Sensitive Data (Prod ➔ Test Masking)
|
|
581
173
|
</div>
|
|
582
174
|
<div class="text-[11px] text-base-content/65 mt-0.5 leading-relaxed">
|
|
583
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.
|
|
584
176
|
</div>
|
|
585
177
|
</div>
|
|
586
178
|
</label>
|
|
587
179
|
</div>
|
|
588
180
|
</div>
|
|
589
181
|
<div>
|
|
590
182
|
<div class="flex items-center justify-between mb-1.5">
|
|
591
183
|
<label class="field-label font-bold text-xs uppercase tracking-wider text-base-content/70 mb-0">Tables to Transfer</label>
|
|
592
184
|
<div class="flex items-center gap-2 text-xs">
|
|
593
185
|
<button type="button" id="btn-select-all-tables" class="text-primary font-semibold hover:underline">Select All</button>
|
|
594
186
|
<span class="text-base-content/30">|</span>
|
|
595
187
|
<button type="button" id="btn-deselect-all-tables" class="text-base-content/60 hover:underline">Clear</button>
|
|
596
188
|
</div>
|
|
597
189
|
</div>
|
|
598
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">
|
|
599
191
|
<span class="text-base-content/40 italic p-1 block">Select source database above to load tables.</span>
|
|
600
192
|
</div>
|
|
601
193
|
</div>
|
|
602
194
|
</div>
|
|
603
195
|
</div>
|
|
604
196
|
</div>
|
|
605
197
|
</div>
|
|
606
198
|
<div class="app-card border border-base-300 overflow-hidden shadow-sm">
|
|
607
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">
|
|
608
200
|
<div class="tabs tabs-boxed bg-base-300/40 p-1 gap-1 rounded-xl" id="diff-tabs">
|
|
609
201
|
<button type="button" class="tab tab-sm tab-active font-semibold gap-1.5 rounded-lg" data-tab="unified">
|
|
610
202
|
{{{icon "diff" class="h-3.5 w-3.5"}}}
|
|
611
203
|
Git Unified Diff
|
|
612
204
|
</button>
|
|
613
205
|
<button type="button" class="tab tab-sm font-semibold gap-1.5 rounded-lg" data-tab="visual">
|
|
614
206
|
{{{icon "table" class="h-3.5 w-3.5"}}}
|
|
615
207
|
Visual Breakdown
|
|
616
208
|
</button>
|
|
617
209
|
<button type="button" class="tab tab-sm font-semibold gap-1.5 rounded-lg" data-tab="data">
|
|
618
210
|
{{{icon "inspect" class="h-3.5 w-3.5"}}}
|
|
619
211
|
Data Diff (Row-by-Row)
|
|
620
212
|
</button>
|
|
621
213
|
</div>
|
|
622
214
|
<div class="flex items-center gap-2 pb-2 text-xs" id="diff-stats-chips">
|
|
623
215
|
</div>
|
|
624
216
|
</div>
|
|
625
217
|
<div id="tab-content-unified" class="p-5 space-y-3">
|
|
626
218
|
<div class="flex items-center justify-between text-xs text-base-content/60">
|
|
627
219
|
<span class="font-mono text-[11px] flex items-center gap-1.5">
|
|
628
220
|
<span class="h-2 w-2 rounded-full bg-primary"></span>
|
|
629
221
|
Standard Git Patch format · Green (+) additions, Red (-) deletions, Amber (~) modifications
|
|
630
222
|
</span>
|
|
631
223
|
<button id="btn-copy-unified-diff" type="button" class="btn btn-ghost btn-xs gap-1 font-mono hover:text-primary">
|
|
632
224
|
{{{icon "copy" class="h-3 w-3"}}}
|
|
633
225
|
Copy Diff Text
|
|
634
226
|
</button>
|
|
635
227
|
</div>
|
|
636
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">
|
|
637
229
|
<div class="text-neutral-content/40 italic text-center py-20">
|
|
638
230
|
Select source and target instances above and click <strong>Compare Diff Now</strong> to compute git-style schema differences.
|
|
639
231
|
</div>
|
|
640
232
|
</div>
|
|
641
233
|
</div>
|
|
642
234
|
<div id="tab-content-visual" class="p-5 hidden space-y-4">
|
|
643
235
|
<div class="flex flex-wrap items-center justify-between gap-3 p-2 rounded-xl bg-base-200/50 border border-base-300">
|
|
644
236
|
<div class="relative flex-1 min-w-[200px]">
|
|
645
237
|
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-base-content/40 pointer-events-none">
|
|
646
238
|
{{{icon "search" class="h-3.5 w-3.5"}}}
|
|
647
239
|
</span>
|
|
648
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" />
|
|
649
241
|
</div>
|
|
650
242
|
<div class="flex items-center gap-1 text-xs" id="filter-status-buttons">
|
|
651
243
|
<button type="button" class="btn btn-xs btn-ghost btn-active js-filter-status" data-filter="all">All</button>
|
|
652
244
|
<button type="button" class="btn btn-xs btn-ghost js-filter-status text-warning" data-filter="modified">Modified</button>
|
|
653
245
|
<button type="button" class="btn btn-xs btn-ghost js-filter-status text-success" data-filter="added">Added</button>
|
|
654
246
|
<button type="button" class="btn btn-xs btn-ghost js-filter-status text-error" data-filter="removed">Removed</button>
|
|
655
247
|
</div>
|
|
656
248
|
</div>
|
|
657
249
|
<div id="visual-diff-cards" class="space-y-3">
|
|
658
250
|
<div class="text-base-content/40 italic text-center py-20">
|
|
659
251
|
No comparison performed yet. Select databases and click "Compare Diff Now".
|
|
660
252
|
</div>
|
|
661
253
|
</div>
|
|
662
254
|
</div>
|
|
663
255
|
<div id="tab-content-data" class="p-5 hidden space-y-4">
|
|
664
256
|
<div class="flex flex-wrap items-center justify-between gap-3 p-3 rounded-xl bg-base-200/50 border border-base-300">
|
|
665
257
|
<div class="flex flex-wrap items-center gap-2.5">
|
|
666
258
|
<label class="text-xs font-bold uppercase tracking-wider text-base-content/60">Table to Compare:</label>
|
|
667
259
|
<select id="select-data-diff-table" class="select select-bordered select-xs font-mono min-w-[180px]">
|
|
668
260
|
<option value="" disabled selected>Select table…</option>
|
|
669
261
|
</select>
|
|
670
262
|
<label class="text-xs font-bold uppercase tracking-wider text-base-content/60 ml-2">Sample Limit:</label>
|
|
671
263
|
<select id="select-data-diff-limit" class="select select-bordered select-xs font-mono">
|
|
672
264
|
<option value="50">50 rows</option>
|
|
673
265
|
<option value="150" selected>150 rows</option>
|
|
674
266
|
<option value="300">300 rows</option>
|
|
675
267
|
<option value="500">500 rows</option>
|
|
676
268
|
</select>
|
|
677
269
|
<button id="btn-fetch-data-diff" type="button" class="btn btn-primary btn-xs gap-1 shadow-sm">
|
|
678
270
|
{{{icon "refresh" class="h-3 w-3"}}}
|
|
679
271
|
Compare Rows
|
|
680
272
|
</button>
|
|
681
273
|
</div>
|
|
682
274
|
<div id="data-diff-stats" class="flex items-center gap-1.5 text-xs font-mono"></div>
|
|
683
275
|
</div>
|
|
684
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">
|
|
685
277
|
<div class="text-base-content/40 italic text-center py-16">
|
|
686
278
|
Select a table and click <strong>Compare Rows</strong> to inspect added, removed, and modified data rows.
|
|
687
279
|
</div>
|
|
688
280
|
</div>
|
|
689
281
|
</div>
|
|
690
282
|
</div>
|
|
691
283
|
<div class="modal-box max-w-3xl border border-base-300 bg-base-100 p-6 space-y-4 shadow-2xl">
|
|
692
284
|
<div class="flex items-center justify-between border-b border-base-200 pb-3">
|
|
693
285
|
<h3 class="font-bold text-base flex items-center gap-2">
|
|
694
286
|
<span class="p-1 rounded bg-primary/10 text-primary">
|
|
695
287
|
{{{icon "sql" class="h-5 w-5"}}}
|
|
696
288
|
</span>
|
|
697
289
|
Generated Migration SQL Patch
|
|
698
290
|
</h3>
|
|
699
291
|
<form method="dialog">
|
|
700
292
|
<button class="btn btn-sm btn-circle btn-ghost">✕</button>
|
|
701
293
|
</form>
|
|
702
294
|
</div>
|
|
703
295
|
<div class="tabs tabs-boxed bg-base-200/60 p-1 gap-1 rounded-xl">
|
|
704
296
|
<button type="button" id="tab-up-sql" class="tab tab-sm tab-active font-bold rounded-lg">UP Script (Migrate Target)</button>
|
|
705
297
|
<button type="button" id="tab-down-sql" class="tab tab-sm font-bold rounded-lg">DOWN Script (Rollback Changes)</button>
|
|
706
298
|
</div>
|
|
707
299
|
<div class="relative">
|
|
708
300
|
<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>
|
|
709
301
|
<div class="absolute top-3 right-3 flex items-center gap-1.5">
|
|
710
302
|
<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">
|
|
711
303
|
{{{icon "copy" class="h-3 w-3"}}}
|
|
712
304
|
Copy SQL
|
|
713
305
|
</button>
|
|
714
306
|
</div>
|
|
715
307
|
</div>
|
|
716
308
|
<div class="modal-action flex justify-between items-center pt-2 border-t border-base-200">
|
|
717
309
|
<span class="text-xs text-base-content/50">Run this script in your target database query editor to align schema structure.</span>
|
|
718
310
|
<form method="dialog">
|
|
719
311
|
<button class="btn btn-sm">Close</button>
|
|
720
312
|
</form>
|
|
721
313
|
</div>
|
|
722
314
|
</div>
|
|
723
315
|
<form method="dialog" class="modal-backdrop">
|
|
724
316
|
<button>close</button>
|
|
725
317
|
</form>
|
|
726
318
|
<div class="modal-box max-w-lg border border-base-300 bg-base-100 p-6 space-y-4 shadow-2xl">
|
|
727
319
|
<div class="flex items-center justify-between border-b border-base-200 pb-3">
|
|
728
320
|
<h3 class="font-bold text-base flex items-center gap-2" id="exec-modal-title">
|
|
729
321
|
<span class="p-1 rounded bg-error/10 text-error" id="exec-modal-icon-badge">
|
|
730
322
|
{{{icon "warning" class="h-5 w-5"}}}
|
|
731
323
|
</span>
|
|
732
324
|
Confirm Replication Execution
|
|
733
325
|
</h3>
|
|
734
326
|
<form method="dialog">
|
|
735
327
|
<button id="btn-exec-close-x" class="btn btn-sm btn-circle btn-ghost">✕</button>
|
|
736
328
|
</form>
|
|
737
329
|
</div>
|
|
738
330
|
<div id="exec-prompt-content" class="space-y-4 text-xs leading-relaxed">
|
|
739
331
|
<div id="exec-destructive-banner" class="p-4 rounded-xl border border-error/40 bg-error/[0.06] text-error space-y-2.5">
|
|
740
332
|
<div class="font-bold flex items-center gap-2 text-sm">
|
|
741
333
|
{{{icon "warning" class="h-4 w-4 shrink-0 text-error"}}}
|
|
742
334
|
Caution: Destructive Action Ahead!
|
|
743
335
|
</div>
|
|
744
336
|
<p class="text-[11.5px] leading-relaxed text-base-content/80">
|
|
745
337
|
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>.
|
|
746
338
|
</p>
|
|
747
339
|
<div class="text-[11px] text-base-content/60 font-mono">
|
|
748
340
|
Affected tables: <span id="lbl-affected-tables-list" class="font-bold text-base-content">All selected tables</span>
|
|
749
341
|
</div>
|
|
750
342
|
</div>
|
|
751
343
|
<div class="p-3.5 rounded-xl border border-base-200 bg-base-200/40 space-y-1.5 font-mono text-[11.5px]">
|
|
752
344
|
<div class="flex justify-between">
|
|
753
345
|
<span class="text-base-content/60">Source (Origin):</span>
|
|
754
346
|
<span id="lbl-confirm-src" class="font-bold text-emerald-600 dark:text-emerald-400"></span>
|
|
755
347
|
</div>
|
|
756
348
|
<div class="flex justify-between">
|
|
757
349
|
<span class="text-base-content/60">Target (Destination):</span>
|
|
758
350
|
<span id="lbl-confirm-tgt" class="font-bold text-info"></span>
|
|
759
351
|
</div>
|
|
760
352
|
<div class="flex justify-between">
|
|
761
353
|
<span class="text-base-content/60">Selected Mode:</span>
|
|
762
354
|
<span id="lbl-confirm-mode" class="font-bold"></span>
|
|
763
355
|
</div>
|
|
764
356
|
<div class="flex justify-between">
|
|
765
357
|
<span class="text-base-content/60">PII Data Anonymization:</span>
|
|
766
358
|
<span id="lbl-confirm-mask" class="font-bold text-warning"></span>
|
|
767
359
|
</div>
|
|
768
360
|
<div class="flex justify-between">
|
|
769
361
|
<span class="text-base-content/60">Tables Selected:</span>
|
|
770
362
|
<span id="lbl-confirm-tables" class="font-bold"></span>
|
|
771
363
|
</div>
|
|
772
364
|
</div>
|
|
773
365
|
<div id="exec-safety-locks" class="space-y-3 pt-1">
|
|
774
366
|
<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">
|
|
775
367
|
<input type="checkbox" id="chk-confirm-destruction" class="checkbox checkbox-error checkbox-sm mt-0.5" />
|
|
776
368
|
<span class="text-[11.5px] font-medium text-base-content/80 select-none">
|
|
777
369
|
I understand that existing tables and records on the target database will be overwritten.
|
|
778
370
|
</span>
|
|
779
371
|
</label>
|
|
780
372
|
<div id="box-confirm-phrase" class="space-y-1.5">
|
|
781
373
|
<label class="text-[11px] font-bold text-base-content/70 block">
|
|
782
374
|
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:
|
|
783
375
|
</label>
|
|
784
376
|
<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" />
|
|
785
377
|
</div>
|
|
786
378
|
</div>
|
|
787
379
|
</div>
|
|
788
380
|
<div id="exec-progress-container" class="space-y-3 hidden">
|
|
789
381
|
<div class="flex items-center justify-between text-xs font-mono">
|
|
790
382
|
<span id="exec-current-table" class="font-semibold flex items-center gap-2">
|
|
791
383
|
<span class="loading loading-spinner loading-xs text-primary"></span>
|
|
792
384
|
Synchronizing records...
|
|
793
385
|
</span>
|
|
794
386
|
<span id="exec-progress-percent" class="text-primary font-bold">0%</span>
|
|
795
387
|
</div>
|
|
796
388
|
<progress id="exec-progress-bar" class="progress progress-primary w-full h-3" value="0" max="100"></progress>
|
|
797
389
|
<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>
|
|
798
390
|
</div>
|
|
799
391
|
<div class="modal-action pt-3 border-t border-base-200 flex justify-between items-center" id="exec-modal-buttons">
|
|
800
392
|
<form method="dialog">
|
|
801
393
|
<button id="btn-exec-cancel" class="btn btn-sm btn-ghost">Cancel</button>
|
|
802
394
|
</form>
|
|
803
395
|
<button id="btn-exec-start" type="button" class="btn btn-sm btn-error gap-1.5 shadow-sm" disabled>
|
|
804
396
|
{{{icon "sync" class="h-4 w-4"}}}
|
|
805
397
|
Confirm & Start Replication
|
|
806
398
|
</button>
|
|
807
399
|
</div>
|
|
808
400
|
</div>
|
|
809
401
|
<form method="dialog" class="modal-backdrop">
|
|
810
402
|
<button>close</button>
|
|
811
403
|
</form>
|