admindb 2.4.1 → 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 (170) hide show
  1. package/LICENSE +20 -20
  2. package/dist/app.js +48 -25
  3. package/dist/core/context.d.ts +1 -0
  4. package/dist/core/context.js +2 -0
  5. package/dist/core/diff/data-differ.d.ts +1 -0
  6. package/dist/core/diff/data-differ.js +243 -0
  7. package/dist/core/diff/patch-generator.d.ts +1 -0
  8. package/dist/core/diff/patch-generator.js +77 -0
  9. package/dist/core/diff/schema-differ.d.ts +1 -0
  10. package/dist/core/diff/schema-differ.js +229 -0
  11. package/dist/core/errors.d.ts +1 -0
  12. package/dist/core/errors.js +39 -0
  13. package/dist/core/index.d.ts +1 -0
  14. package/dist/core/index.js +20 -0
  15. package/dist/core/result.d.ts +1 -0
  16. package/dist/core/result.js +10 -0
  17. package/dist/core/router.d.ts +1 -0
  18. package/dist/core/router.js +37 -0
  19. package/dist/core/transfer/dialect-mapper.d.ts +1 -0
  20. package/dist/core/transfer/dialect-mapper.js +303 -0
  21. package/dist/core/transfer/masking.d.ts +1 -0
  22. package/dist/core/transfer/masking.js +49 -0
  23. package/dist/core/transfer/sync-engine.d.ts +1 -0
  24. package/dist/core/transfer/sync-engine.js +234 -0
  25. package/dist/core/transfer/topological-sort.d.ts +1 -0
  26. package/dist/core/transfer/topological-sort.js +55 -0
  27. package/dist/data/chain.js +1 -1
  28. package/dist/data/engine.js +1 -1
  29. package/dist/db/database.d.ts +1 -1
  30. package/dist/db/database.js +9 -31
  31. package/dist/db/dialects/index.d.ts +1 -0
  32. package/dist/db/dialects/index.js +58 -0
  33. package/dist/db/dialects/postgres/ddl.d.ts +1 -0
  34. package/dist/db/dialects/postgres/ddl.js +107 -0
  35. package/dist/db/dialects/postgres/dialect.d.ts +1 -0
  36. package/dist/db/dialects/postgres/dialect.js +28 -0
  37. package/dist/db/dialects/postgres/introspector.d.ts +1 -0
  38. package/dist/db/dialects/postgres/introspector.js +265 -0
  39. package/dist/db/dialects/postgres/types.d.ts +1 -0
  40. package/dist/db/dialects/postgres/types.js +83 -0
  41. package/dist/db/dialects/sqlite/ddl.d.ts +1 -0
  42. package/dist/db/dialects/sqlite/ddl.js +244 -0
  43. package/dist/db/dialects/sqlite/dialect.d.ts +1 -0
  44. package/dist/db/dialects/sqlite/dialect.js +25 -0
  45. package/dist/db/dialects/sqlite/introspector.d.ts +1 -0
  46. package/dist/db/dialects/sqlite/introspector.js +217 -0
  47. package/dist/db/dialects/sqlite/types.d.ts +1 -0
  48. package/dist/db/dialects/sqlite/types.js +69 -0
  49. package/dist/db/dialects/types.d.ts +1 -0
  50. package/dist/db/dialects/types.js +15 -0
  51. package/dist/db/export.js +1 -1
  52. package/dist/db/index.d.ts +1 -1
  53. package/dist/db/index.js +1 -1
  54. package/dist/db/manager.d.ts +1 -1
  55. package/dist/db/manager.js +101 -21
  56. package/dist/db/postgres.d.ts +1 -1
  57. package/dist/db/postgres.js +20 -284
  58. package/dist/db/types.d.ts +1 -1
  59. package/dist/db/types.js +0 -4
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.js +4 -1
  62. package/dist/modules/databases/databases.routes.d.ts +1 -0
  63. package/dist/modules/databases/databases.routes.js +150 -0
  64. package/dist/modules/databases/databases.service.d.ts +1 -0
  65. package/dist/modules/databases/databases.service.js +134 -0
  66. package/dist/modules/databases/index.d.ts +1 -0
  67. package/dist/{routes → modules/databases}/index.js +2 -3
  68. package/dist/modules/erd/erd.routes.d.ts +1 -0
  69. package/dist/modules/erd/erd.routes.js +32 -0
  70. package/dist/modules/erd/erd.service.d.ts +1 -0
  71. package/dist/modules/erd/erd.service.js +39 -0
  72. package/dist/modules/erd/index.d.ts +1 -0
  73. package/dist/modules/erd/index.js +18 -0
  74. package/dist/modules/index.d.ts +1 -0
  75. package/dist/modules/index.js +70 -0
  76. package/dist/modules/query/index.d.ts +1 -0
  77. package/dist/modules/query/index.js +18 -0
  78. package/dist/modules/query/query.routes.d.ts +1 -0
  79. package/dist/modules/query/query.routes.js +54 -0
  80. package/dist/modules/query/query.service.d.ts +1 -0
  81. package/dist/modules/query/query.service.js +95 -0
  82. package/dist/modules/rows/blob.helper.d.ts +1 -0
  83. package/dist/modules/rows/blob.helper.js +40 -0
  84. package/dist/modules/rows/display.helper.d.ts +1 -0
  85. package/dist/modules/rows/display.helper.js +73 -0
  86. package/dist/modules/rows/index.d.ts +1 -0
  87. package/dist/modules/rows/index.js +20 -0
  88. package/dist/modules/rows/rows.routes.d.ts +1 -0
  89. package/dist/modules/rows/rows.routes.js +555 -0
  90. package/dist/modules/rows/rows.service.d.ts +1 -0
  91. package/dist/modules/rows/rows.service.js +433 -0
  92. package/dist/modules/schema/index.d.ts +1 -0
  93. package/dist/modules/schema/index.js +18 -0
  94. package/dist/modules/schema/schema.routes.d.ts +1 -0
  95. package/dist/modules/schema/schema.routes.js +171 -0
  96. package/dist/modules/schema/schema.service.d.ts +1 -0
  97. package/dist/modules/schema/schema.service.js +58 -0
  98. package/dist/modules/search/index.d.ts +1 -0
  99. package/dist/modules/search/index.js +19 -0
  100. package/dist/modules/search/search.routes.d.ts +1 -0
  101. package/dist/modules/search/search.routes.js +38 -0
  102. package/dist/modules/search/search.service.d.ts +1 -0
  103. package/dist/modules/search/search.service.js +458 -0
  104. package/dist/modules/search/search.types.d.ts +1 -0
  105. package/dist/modules/search/search.types.js +2 -0
  106. package/dist/modules/seed/index.d.ts +1 -0
  107. package/dist/modules/seed/index.js +18 -0
  108. package/dist/modules/seed/seed.routes.d.ts +1 -0
  109. package/dist/modules/seed/seed.routes.js +212 -0
  110. package/dist/modules/seed/seed.service.d.ts +1 -0
  111. package/dist/{routes/api/helpers.js → modules/seed/seed.service.js} +86 -109
  112. package/dist/modules/sync/index.d.ts +1 -0
  113. package/dist/modules/sync/index.js +18 -0
  114. package/dist/modules/sync/sync.routes.d.ts +1 -0
  115. package/dist/modules/sync/sync.routes.js +135 -0
  116. package/dist/modules/sync/sync.service.d.ts +1 -0
  117. package/dist/modules/sync/sync.service.js +41 -0
  118. package/dist/modules/tables/index.d.ts +1 -0
  119. package/dist/modules/tables/index.js +18 -0
  120. package/dist/modules/tables/tables.routes.d.ts +1 -0
  121. package/dist/modules/tables/tables.routes.js +194 -0
  122. package/dist/modules/tables/tables.service.d.ts +1 -0
  123. package/dist/modules/tables/tables.service.js +218 -0
  124. package/dist/public/css/app.css +1 -1
  125. package/dist/public/js/browse.js +1 -1
  126. package/dist/public/js/query.js +1 -1
  127. package/dist/public/js/search.js +1 -0
  128. package/dist/public/js/sync.js +1 -0
  129. package/dist/types/api.d.ts +1 -1
  130. package/dist/utils/common.d.ts +1 -1
  131. package/dist/utils/common.js +1 -3
  132. package/dist/utils/icons.js +3 -0
  133. package/dist/utils/stream.d.ts +1 -0
  134. package/dist/utils/stream.js +131 -0
  135. package/dist/views/layouts/main.hbs +1 -1
  136. package/dist/views/pages/error.hbs +10 -1
  137. package/dist/views/pages/home.hbs +1 -1
  138. package/dist/views/pages/query.hbs +1 -1
  139. package/dist/views/pages/seed-select.hbs +1 -252
  140. package/dist/views/pages/seed.hbs +1 -307
  141. package/dist/views/pages/sync.hbs +409 -0
  142. package/dist/views/pages/table.hbs +1 -1
  143. package/dist/views/partials/navbar.hbs +1 -1
  144. package/dist/views/partials/sidebar.hbs +1 -1
  145. package/docs/API.md +4 -17
  146. package/docs/EXAMPLES.md +579 -579
  147. package/docs/SECURITY.md +265 -265
  148. package/package.json +10 -9
  149. package/dist/db/introspection.d.ts +0 -1
  150. package/dist/db/introspection.js +0 -164
  151. package/dist/routes/api/erd.d.ts +0 -1
  152. package/dist/routes/api/erd.js +0 -45
  153. package/dist/routes/api/helpers.d.ts +0 -1
  154. package/dist/routes/api/import-export.d.ts +0 -1
  155. package/dist/routes/api/import-export.js +0 -84
  156. package/dist/routes/api/index.d.ts +0 -1
  157. package/dist/routes/api/index.js +0 -55
  158. package/dist/routes/api/query.d.ts +0 -1
  159. package/dist/routes/api/query.js +0 -77
  160. package/dist/routes/api/rows.d.ts +0 -1
  161. package/dist/routes/api/rows.js +0 -373
  162. package/dist/routes/api/seed.d.ts +0 -1
  163. package/dist/routes/api/seed.js +0 -180
  164. package/dist/routes/api/tables.d.ts +0 -1
  165. package/dist/routes/api/tables.js +0 -230
  166. package/dist/routes/databases.d.ts +0 -1
  167. package/dist/routes/databases.js +0 -212
  168. package/dist/routes/index.d.ts +0 -1
  169. package/dist/routes/pages.d.ts +0 -1
  170. package/dist/routes/pages.js +0 -540
@@ -1,307 +1 @@
1
- <div class="space-y-4 pb-20">
2
- <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
3
- <div class="flex items-center gap-3 min-w-0">
4
- <a href="{{basePath}}/seed/{{encodeUri dbId}}" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Choose table & mode">
5
- {{{icon "arrowLeft" class="h-4 w-4"}}}
6
- </a>
7
- <div class="h-4 w-px bg-base-300"></div>
8
- <div class="flex items-center gap-2 flex-wrap">
9
- <a href="{{basePath}}/seed/{{encodeUri dbId}}" class="text-xs font-semibold text-base-content/50 hover:text-primary transition-colors">Seed Data</a>
10
- <span class="text-xs text-base-content/30">/</span>
11
- {{#if allTables.length}}
12
- <div class="dropdown dropdown-bottom">
13
- <label tabindex="0" class="btn btn-xs btn-ghost gap-1 font-mono font-bold text-xs" title="Switch table">
14
- <span>{{table}}</span>
15
- {{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
16
- </label>
17
- <ul tabindex="0" class="dropdown-content z-30 menu p-1 shadow-lg bg-base-100 border border-base-300 rounded-box w-52 max-h-60 overflow-y-auto">
18
- {{#each allTables}}
19
- <li>
20
- <a href="{{../basePath}}/seed/{{encodeUri ../dbId}}/{{encodeUri this}}" class="{{#if (eq this ../table)}}active font-bold{{/if}} font-mono text-xs">
21
- {{{icon "table" class="h-3.5 w-3.5"}}}
22
- {{this}}
23
- </a>
24
- </li>
25
- {{/each}}
26
- </ul>
27
- </div>
28
- {{else}}
29
- <span class="font-mono font-bold text-sm text-base-content">{{table}}</span>
30
- {{/if}}
31
- <span class="badge badge-sm badge-ghost font-mono text-[11px] text-base-content/60">{{colCount}} cols</span>
32
- {{#if dialect}}
33
- <span class="badge badge-sm badge-outline font-mono text-[10px] uppercase text-base-content/50">{{dialect}}</span>
34
- {{/if}}
35
- </div>
36
- </div>
37
- <div class="flex items-center gap-2.5 flex-wrap">
38
- <div class="seed-mode-segment">
39
- <button type="button" id="btn-select-single" class="seed-mode-btn {{#unless isChainMode}}active{{/unless}}">
40
- {{{icon "table" class="h-3.5 w-3.5"}}}
41
- <span>Single Table</span>
42
- </button>
43
- <button type="button" id="btn-select-chain" class="seed-mode-btn {{#if isChainMode}}active{{/if}}">
44
- {{{icon "diagram" class="h-3.5 w-3.5"}}}
45
- <span>ER Chain</span>
46
- </button>
47
- </div>
48
- <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
49
- <div class="flex items-center gap-1.5" title="Numeric seed for deterministic generation">
50
- <div class="relative">
51
- <input id="plan-seed-input" type="number" placeholder="Seed (auto)"
52
- class="field-input w-28 font-mono text-xs !py-1 pl-2.5 pr-6" />
53
- <span class="absolute right-2 top-1/2 -translate-y-1/2 text-[10px] font-mono text-base-content/40">#</span>
54
- </div>
55
- <button type="button" id="btn-random-seed" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Roll random seed">
56
- {{{icon "refresh" class="h-3.5 w-3.5"}}}
57
- </button>
58
- </div>
59
- <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
60
- <div class="flex items-center gap-1">
61
- <button type="button" id="btn-profiles-modal" class="btn btn-sm btn-ghost gap-1.5 text-xs text-base-content/80 hover:text-base-content" title="Manage seed profiles">
62
- {{{icon "book" class="h-3.5 w-3.5 text-primary"}}}
63
- <span class="hidden md:inline">Profiles</span>
64
- </button>
65
- <button type="button" id="btn-export-plan-json" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Export generation plan JSON">
66
- {{{icon "download" class="h-3.5 w-3.5"}}}
67
- </button>
68
- <label for="input-import-plan-json" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content cursor-pointer" title="Import generation plan JSON">
69
- {{{icon "upload" class="h-3.5 w-3.5"}}}
70
- <input type="file" id="input-import-plan-json" accept=".json" class="hidden" />
71
- </label>
72
- </div>
73
- <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
74
- <button id="seed-insert" type="button" class="btn btn-primary btn-sm gap-2 font-bold px-4 shadow-sm">
75
- {{{icon "play" class="h-3.5 w-3.5"}}}
76
- <span>Execute Seed</span>
77
- </button>
78
- </div>
79
- </div>
80
- <div id="step-content-1" class="hidden">
81
- <button id="btn-next-1" class="hidden"></button>
82
- </div>
83
- <div id="step-content-2" class="contents">
84
- <button id="btn-prev-2" class="hidden"></button>
85
- <button id="btn-next-2" class="hidden"></button>
86
- </div>
87
- <div id="step-content-3" class="contents">
88
- <button id="btn-prev-3" class="hidden"></button>
89
- </div>
90
- <div id="step-nav-1" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
91
- <div id="step-nav-2" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
92
- <div id="step-nav-3" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
93
- <div id="wizard-progress-bar" class="hidden"></div>
94
- <div class="grid grid-cols-1 xl:grid-cols-12 gap-4 items-start">
95
- <div class="xl:col-span-7 space-y-4">
96
- <div id="config-single" class="{{#if isChainMode}}hidden{{/if}} space-y-4">
97
- <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
98
- <div class="flex items-center gap-3">
99
- <div class="flex items-center">
100
- <button type="button" id="seed-count-dec" class="btn btn-xs btn-outline rounded-r-none border-r-0 px-2.5 font-mono text-sm hover:bg-primary hover:text-primary-content hover:border-primary">−</button>
101
- <input id="seed-count" type="number" value="10" min="1" max="{{maxRows}}"
102
- class="field-input !rounded-none border-x-0 !py-0.5 font-mono w-20 font-bold text-xs text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" />
103
- <button type="button" id="seed-count-inc" class="btn btn-xs btn-outline rounded-l-none border-l-0 px-2.5 font-mono text-sm hover:bg-primary hover:text-primary-content hover:border-primary">+</button>
104
- </div>
105
- <span class="text-[11px] uppercase font-bold text-base-content/50">Rows</span>
106
- <div class="h-4 w-px bg-base-200 hidden sm:block"></div>
107
- <div class="flex gap-1 flex-wrap">
108
- {{#each quickCounts}}
109
- <button type="button" class="preset-pill btn btn-xs btn-ghost border border-base-300 font-mono text-[11px] px-2" data-count="{{this}}">{{this}}</button>
110
- {{/each}}
111
- </div>
112
- </div>
113
- <div class="flex items-center gap-2 w-full sm:w-auto">
114
- <input type="text" id="seed-col-search" placeholder="Filter columns…" class="field-input text-xs !py-1 w-full sm:w-48" />
115
- <span id="col-count-badge" class="badge badge-sm badge-ghost font-mono text-[11px] shrink-0">{{colCount}} cols</span>
116
- </div>
117
- </div>
118
- <div class="app-card p-4 space-y-3">
119
- <div class="flex items-center justify-between pb-2 border-b border-base-200">
120
- <span class="text-xs font-bold uppercase tracking-wider text-base-content/70">Columns Specification</span>
121
- <span class="text-[11px] text-base-content/40">Select generator strategy & customize parameters per column</span>
122
- </div>
123
- <div id="seed-columns" class="space-y-2.5">
124
- </div>
125
- </div>
126
- </div>
127
- <div id="config-chain" class="{{#unless isChainMode}}hidden{{/unless}} space-y-4">
128
- <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
129
- <div class="flex items-center gap-3">
130
- <label class="text-xs font-bold text-base-content/70">Graph Scope:</label>
131
- <select id="chain-scope" class="field-select !py-1 text-xs font-semibold w-52">
132
- <option value="chain">Connected Relational Chain</option>
133
- <option value="ancestors">Upstream Parents Only</option>
134
- <option value="descendants">Downstream Children Only</option>
135
- <option value="all">Entire Database (All Tables)</option>
136
- </select>
137
- </div>
138
- <div class="flex items-center gap-2">
139
- <span class="text-xs font-bold text-base-content/70">Scale:</span>
140
- <div class="join">
141
- <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="0.5">0.5×</button>
142
- <button type="button" class="chain-scale-btn btn btn-xs join-item btn-neutral font-mono" data-scale="1">1×</button>
143
- <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="2">2×</button>
144
- <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="5">5×</button>
145
- </div>
146
- <span id="chain-summary-badge" class="badge badge-sm badge-primary font-mono font-bold ml-2">0 Tables</span>
147
- </div>
148
- </div>
149
- <div class="app-card p-4 space-y-3">
150
- <div class="flex items-center justify-between pb-2 border-b border-base-200">
151
- <span class="text-xs font-bold uppercase tracking-wider text-base-content/70">Topological Execution Pipeline</span>
152
- <span class="text-[11px] text-base-content/40">Dependencies ordered upstream-first</span>
153
- </div>
154
- <div id="chain-pipeline-container" class="space-y-2.5">
155
- </div>
156
- </div>
157
- </div>
158
- <details class="app-card group">
159
- <summary class="p-3.5 flex items-center justify-between cursor-pointer list-none select-none text-xs font-bold text-base-content/70 hover:text-base-content">
160
- <div class="flex items-center gap-2">
161
- {{{icon "settings" class="h-3.5 w-3.5"}}}
162
- <span>Advanced Execution Options</span>
163
- </div>
164
- <span class="text-xs text-base-content/40 group-open:rotate-180 transition-transform">▼</span>
165
- </summary>
166
- <div class="p-3.5 pt-0 border-t border-base-200/80 mt-1 flex flex-wrap items-center gap-6 text-xs">
167
- <label class="cursor-pointer flex items-center gap-2 select-none group">
168
- <input id="plan-transaction-opt" type="checkbox" checked class="checkbox checkbox-primary checkbox-xs" />
169
- <span class="font-medium text-base-content/80 group-hover:text-base-content">Wrap in Transaction (BEGIN ... COMMIT)</span>
170
- </label>
171
- <label class="cursor-pointer flex items-center gap-2 select-none group">
172
- <input id="plan-rollback-opt" type="checkbox" checked class="checkbox checkbox-primary checkbox-xs" />
173
- <span class="font-medium text-base-content/80 group-hover:text-base-content">Atomic Rollback on Error</span>
174
- </label>
175
- <label class="cursor-pointer flex items-center gap-2 select-none group">
176
- <input id="seed-truncate" type="checkbox" class="checkbox checkbox-error checkbox-xs" />
177
- <span class="font-medium text-error/90 group-hover:text-error">Clear tables before inserting (Truncate)</span>
178
- </label>
179
- </div>
180
- </details>
181
- </div>
182
- <div class="xl:col-span-5 space-y-4 xl:sticky xl:top-4">
183
- <div id="validation-report-card" class="app-card p-3.5 space-y-2">
184
- <div class="flex items-center justify-between">
185
- <div id="validation-summary-pill" class="flex items-center gap-2">
186
- <span id="validation-status-dot" class="w-2 h-2 rounded-full bg-success"></span>
187
- <span id="validation-status-text" class="text-xs font-mono font-bold text-base-content">Plan Ready</span>
188
- </div>
189
- <span id="validation-summary-chip" class="badge badge-sm badge-success font-mono text-[10px] font-bold">All Checks Passed</span>
190
- </div>
191
- <div id="validation-issues-list" class="space-y-1.5 text-xs">
192
- <div class="flex items-center gap-2 text-success font-medium text-[11px]">
193
- {{{icon "check" class="h-3.5 w-3.5 shrink-0"}}}
194
- <span>Primary key & constraint strategies valid</span>
195
- </div>
196
- </div>
197
- </div>
198
- <div class="app-card overflow-hidden">
199
- <div class="flex items-center justify-between p-3 border-b border-base-200 bg-base-100 gap-2 flex-wrap">
200
- <div class="join">
201
- <button type="button" id="preview-tab-grid" class="btn btn-xs join-item btn-active font-bold">Table Preview</button>
202
- <button type="button" id="preview-tab-sql" class="btn btn-xs join-item font-bold">SQL Script</button>
203
- </div>
204
- <button id="seed-refresh-preview" type="button" class="btn btn-xs btn-ghost gap-1 text-xs text-base-content/70 hover:text-primary">
205
- {{{icon "refresh" class="h-3 w-3"}}}
206
- <span>Refresh</span>
207
- </button>
208
- </div>
209
- <div id="seed-chain-table-tabs" class="tabs tabs-bordered flex-nowrap w-full overflow-x-auto hidden px-3 py-1 bg-base-200/40 border-b border-base-200 text-xs"></div>
210
- <div id="preview-view-grid">
211
- <div class="overflow-x-auto max-h-[440px]">
212
- <table class="table table-zebra table-pin-rows table-xs w-full">
213
- <thead id="seed-preview-thead" class="bg-base-200/90 text-[10px] uppercase font-mono tracking-wider text-base-content/70 backdrop-blur sticky top-0 z-10"></thead>
214
- <tbody id="seed-preview-tbody" class="font-mono text-[11px]">
215
- <tr>
216
- <td colspan="100" class="text-center py-12 opacity-50">
217
- <div class="flex flex-col items-center gap-2">
218
- <span class="loading loading-spinner loading-sm text-primary"></span>
219
- <span class="text-xs">Generating preview…</span>
220
- </div>
221
- </td>
222
- </tr>
223
- </tbody>
224
- </table>
225
- </div>
226
- </div>
227
- <div id="preview-view-sql" class="hidden p-3 bg-base-200/20 space-y-2">
228
- <div class="flex items-center justify-between">
229
- <span class="text-[11px] font-mono text-base-content/50 uppercase font-bold">Generated SQL (Preview)</span>
230
- <button type="button" id="btn-copy-sql" class="btn btn-xs btn-outline gap-1 text-[11px]">
231
- {{{icon "copy" class="h-3 w-3"}}}
232
- <span>Copy SQL</span>
233
- </button>
234
- </div>
235
- <pre id="preview-sql-code" class="bg-neutral text-neutral-content p-3.5 rounded-lg font-mono text-xs overflow-x-auto max-h-[380px] border border-base-300 leading-relaxed"></pre>
236
- </div>
237
- </div>
238
- <div id="seed-truncate-banner" class="hidden p-3 rounded-lg bg-error/10 border border-error/20 flex items-center gap-2.5">
239
- <span class="text-error shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
240
- <p class="text-xs font-bold text-error">
241
- Destructive Action: Existing table rows will be truncated before seeding.
242
- </p>
243
- </div>
244
- <div id="seed-execute-bar" class="hidden"></div>
245
- <div id="seed-feedback" class="hidden"></div>
246
- </div>
247
- </div>
248
- </div>
249
- <dialog id="seed-profiles-dialog" class="modal">
250
- <div class="modal-box p-0 overflow-hidden max-w-lg rounded-2xl border border-base-200 shadow-xl">
251
- <div class="px-5 py-4 bg-base-200/50 border-b border-base-200 flex items-center justify-between">
252
- <div class="flex items-center gap-2.5">
253
- {{{icon "book" class="h-4 w-4 text-primary"}}}
254
- <h3 class="font-bold text-sm text-base-content">Seed Profiles & Presets</h3>
255
- </div>
256
- <button type="button" class="btn btn-xs btn-circle btn-ghost" id="btn-close-profiles">✕</button>
257
- </div>
258
- <div class="p-5 space-y-4 text-xs">
259
- <div>
260
- <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/50 mb-2">Quick Blueprints</h4>
261
- <div class="grid grid-cols-3 gap-2">
262
- <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="smoke">⚡ Smoke (10)</button>
263
- <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="realistic">🌱 Standard (100)</button>
264
- <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="stress">🚀 Stress (1000)</button>
265
- </div>
266
- </div>
267
- <div class="p-3 rounded-lg bg-base-200/40 border border-base-300 space-y-2">
268
- <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/60">Save Current Configuration</h4>
269
- <div class="flex gap-2">
270
- <input id="profile-name-input" type="text" placeholder="Profile name (e.g. Test Dataset)"
271
- class="field-input flex-1 text-xs !py-1 font-medium" />
272
- <button type="button" id="btn-save-profile" class="btn btn-xs btn-primary px-3 font-bold">Save</button>
273
- </div>
274
- </div>
275
- <div>
276
- <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/50 mb-1.5">Saved Profiles</h4>
277
- <div id="profiles-list-container" class="space-y-1.5 max-h-48 overflow-y-auto pr-1">
278
- <div class="py-4 text-center text-xs text-base-content/40">No saved profiles yet.</div>
279
- </div>
280
- </div>
281
- </div>
282
- </div>
283
- <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>
284
- </dialog>
285
- <dialog id="seed-truncate-dialog" class="modal">
286
- <div class="modal-box p-0 overflow-hidden max-w-md rounded-2xl border border-error/20 shadow-xl">
287
- <div class="px-5 py-4 bg-error/5 border-b border-error/15 flex items-center gap-2.5">
288
- <span class="text-error">{{{icon "warning" class="h-5 w-5"}}}</span>
289
- <h3 class="font-bold text-sm text-error">Confirm Truncate Action</h3>
290
- </div>
291
- <div class="p-5 space-y-3 text-xs text-base-content/80 leading-relaxed">
292
- <p>
293
- You have enabled <strong class="text-error">Clear tables before inserting</strong>. All existing records in affected tables will be permanently deleted in reverse topological order before new rows are inserted.
294
- </p>
295
- </div>
296
- <div class="px-5 pb-4 flex items-center justify-end gap-2">
297
- <button type="button" class="btn btn-ghost btn-xs" id="seed-truncate-cancel">Cancel</button>
298
- <button type="button" class="btn btn-error btn-xs font-bold gap-1.5" id="seed-truncate-confirm">
299
- {{{icon "warning" class="h-3.5 w-3.5"}}}
300
- <span>Yes, Truncate & Seed</span>
301
- </button>
302
- </div>
303
- </div>
304
- <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>
305
- </dialog>
306
- <script id="seed-config" type="application/json">{{{json seedConfig}}}</script>
307
- <script src="{{basePath}}/js/seed.js" defer></script>
1
+ <div class="space-y-4 pb-20">
308
2
  <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
309
3
  <div class="flex items-center gap-3 min-w-0">
310
4
  <a href="{{basePath}}/seed/{{encodeUri dbId}}" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Choose table & mode">
311
5
  {{{icon "arrowLeft" class="h-4 w-4"}}}
312
6
  </a>
313
7
  <div class="h-4 w-px bg-base-300"></div>
314
8
  <div class="flex items-center gap-2 flex-wrap">
315
9
  <a href="{{basePath}}/seed/{{encodeUri dbId}}" class="text-xs font-semibold text-base-content/50 hover:text-primary transition-colors">Seed Data</a>
316
10
  <span class="text-xs text-base-content/30">/</span>
317
11
  {{#if allTables.length}}
318
12
  <div class="dropdown dropdown-bottom">
319
13
  <label tabindex="0" class="btn btn-xs btn-ghost gap-1 font-mono font-bold text-xs" title="Switch table">
320
14
  <span>{{table}}</span>
321
15
  {{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
322
16
  </label>
323
17
  <ul tabindex="0" class="dropdown-content z-30 menu p-1 shadow-lg bg-base-100 border border-base-300 rounded-box w-52 max-h-60 overflow-y-auto">
324
18
  {{#each allTables}}
325
19
  <li>
326
20
  <a href="{{../basePath}}/seed/{{encodeUri ../dbId}}/{{encodeUri this}}" class="{{#if (eq this ../table)}}active font-bold{{/if}} font-mono text-xs">
327
21
  {{{icon "table" class="h-3.5 w-3.5"}}}
328
22
  {{this}}
329
23
  </a>
330
24
  </li>
331
25
  {{/each}}
332
26
  </ul>
333
27
  </div>
334
28
  {{else}}
335
29
  <span class="font-mono font-bold text-sm text-base-content">{{table}}</span>
336
30
  {{/if}}
337
31
  <span class="badge badge-sm badge-ghost font-mono text-[11px] text-base-content/60">{{colCount}} cols</span>
338
32
  {{#if dialect}}
339
33
  <span class="badge badge-sm badge-outline font-mono text-[10px] uppercase text-base-content/50">{{dialect}}</span>
340
34
  {{/if}}
341
35
  </div>
342
36
  </div>
343
37
  <div class="flex items-center gap-2.5 flex-wrap">
344
38
  <div class="seed-mode-segment">
345
39
  <button type="button" id="btn-select-single" class="seed-mode-btn {{#unless isChainMode}}active{{/unless}}">
346
40
  {{{icon "table" class="h-3.5 w-3.5"}}}
347
41
  <span>Single Table</span>
348
42
  </button>
349
43
  <button type="button" id="btn-select-chain" class="seed-mode-btn {{#if isChainMode}}active{{/if}}">
350
44
  {{{icon "diagram" class="h-3.5 w-3.5"}}}
351
45
  <span>ER Chain</span>
352
46
  </button>
353
47
  </div>
354
48
  <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
355
49
  <div class="flex items-center gap-1.5" title="Numeric seed for deterministic generation">
356
50
  <div class="relative">
357
51
  <input id="plan-seed-input" type="number" placeholder="Seed (auto)"
358
52
  class="field-input w-28 font-mono text-xs !py-1 pl-2.5 pr-6" />
359
53
  <span class="absolute right-2 top-1/2 -translate-y-1/2 text-[10px] font-mono text-base-content/40">#</span>
360
54
  </div>
361
55
  <button type="button" id="btn-random-seed" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Roll random seed">
362
56
  {{{icon "refresh" class="h-3.5 w-3.5"}}}
363
57
  </button>
364
58
  </div>
365
59
  <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
366
60
  <div class="flex items-center gap-1">
367
61
  <button type="button" id="btn-profiles-modal" class="btn btn-sm btn-ghost gap-1.5 text-xs text-base-content/80 hover:text-base-content" title="Manage seed profiles">
368
62
  {{{icon "book" class="h-3.5 w-3.5 text-primary"}}}
369
63
  <span class="hidden md:inline">Profiles</span>
370
64
  </button>
371
65
  <button type="button" id="btn-export-plan-json" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content" title="Export generation plan JSON">
372
66
  {{{icon "download" class="h-3.5 w-3.5"}}}
373
67
  </button>
374
68
  <label for="input-import-plan-json" class="btn btn-sm btn-ghost btn-square text-base-content/70 hover:text-base-content cursor-pointer" title="Import generation plan JSON">
375
69
  {{{icon "upload" class="h-3.5 w-3.5"}}}
376
70
  <input type="file" id="input-import-plan-json" accept=".json" class="hidden" />
377
71
  </label>
378
72
  </div>
379
73
  <div class="h-4 w-px bg-base-300 hidden sm:block"></div>
380
74
  <button id="seed-insert" type="button" class="btn btn-primary btn-sm gap-2 font-bold px-4 shadow-sm">
381
75
  {{{icon "play" class="h-3.5 w-3.5"}}}
382
76
  <span>Execute Seed</span>
383
77
  </button>
384
78
  </div>
385
79
  </div>
386
80
  <div id="step-content-1" class="hidden">
387
81
  <button id="btn-next-1" class="hidden"></button>
388
82
  </div>
389
83
  <div id="step-content-2" class="contents">
390
84
  <button id="btn-prev-2" class="hidden"></button>
391
85
  <button id="btn-next-2" class="hidden"></button>
392
86
  </div>
393
87
  <div id="step-content-3" class="contents">
394
88
  <button id="btn-prev-3" class="hidden"></button>
395
89
  </div>
396
90
  <div id="step-nav-1" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
397
91
  <div id="step-nav-2" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
398
92
  <div id="step-nav-3" class="hidden"><div class="seed-step-circle"><span class="seed-step-num"></span><span class="seed-step-check"></span></div></div>
399
93
  <div id="wizard-progress-bar" class="hidden"></div>
400
94
  <div class="grid grid-cols-1 xl:grid-cols-12 gap-4 items-start">
401
95
  <div class="xl:col-span-7 space-y-4">
402
96
  <div id="config-single" class="{{#if isChainMode}}hidden{{/if}} space-y-4">
403
97
  <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
404
98
  <div class="flex items-center gap-3">
405
99
  <div class="flex items-center">
406
100
  <button type="button" id="seed-count-dec" class="btn btn-xs btn-outline rounded-r-none border-r-0 px-2.5 font-mono text-sm hover:bg-primary hover:text-primary-content hover:border-primary">−</button>
407
101
  <input id="seed-count" type="number" value="10" min="1" max="{{maxRows}}"
408
102
  class="field-input !rounded-none border-x-0 !py-0.5 font-mono w-20 font-bold text-xs text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" />
409
103
  <button type="button" id="seed-count-inc" class="btn btn-xs btn-outline rounded-l-none border-l-0 px-2.5 font-mono text-sm hover:bg-primary hover:text-primary-content hover:border-primary">+</button>
410
104
  </div>
411
105
  <span class="text-[11px] uppercase font-bold text-base-content/50">Rows</span>
412
106
  <div class="h-4 w-px bg-base-200 hidden sm:block"></div>
413
107
  <div class="flex gap-1 flex-wrap">
414
108
  {{#each quickCounts}}
415
109
  <button type="button" class="preset-pill btn btn-xs btn-ghost border border-base-300 font-mono text-[11px] px-2" data-count="{{this}}">{{this}}</button>
416
110
  {{/each}}
417
111
  </div>
418
112
  </div>
419
113
  <div class="flex items-center gap-2 w-full sm:w-auto">
420
114
  <input type="text" id="seed-col-search" placeholder="Filter columns…" class="field-input text-xs !py-1 w-full sm:w-48" />
421
115
  <span id="col-count-badge" class="badge badge-sm badge-ghost font-mono text-[11px] shrink-0">{{colCount}} cols</span>
422
116
  </div>
423
117
  </div>
424
118
  <div class="app-card p-4 space-y-3">
425
119
  <div class="flex items-center justify-between pb-2 border-b border-base-200">
426
120
  <span class="text-xs font-bold uppercase tracking-wider text-base-content/70">Columns Specification</span>
427
121
  <span class="text-[11px] text-base-content/40">Select generator strategy & customize parameters per column</span>
428
122
  </div>
429
123
  <div id="seed-columns" class="space-y-2.5">
430
124
  </div>
431
125
  </div>
432
126
  </div>
433
127
  <div id="config-chain" class="{{#unless isChainMode}}hidden{{/unless}} space-y-4">
434
128
  <div class="app-card p-3.5 flex flex-wrap items-center justify-between gap-4">
435
129
  <div class="flex items-center gap-3">
436
130
  <label class="text-xs font-bold text-base-content/70">Graph Scope:</label>
437
131
  <select id="chain-scope" class="field-select !py-1 text-xs font-semibold w-52">
438
132
  <option value="chain">Connected Relational Chain</option>
439
133
  <option value="ancestors">Upstream Parents Only</option>
440
134
  <option value="descendants">Downstream Children Only</option>
441
135
  <option value="all">Entire Database (All Tables)</option>
442
136
  </select>
443
137
  </div>
444
138
  <div class="flex items-center gap-2">
445
139
  <span class="text-xs font-bold text-base-content/70">Scale:</span>
446
140
  <div class="join">
447
141
  <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="0.5">0.5×</button>
448
142
  <button type="button" class="chain-scale-btn btn btn-xs join-item btn-neutral font-mono" data-scale="1">1×</button>
449
143
  <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="2">2×</button>
450
144
  <button type="button" class="chain-scale-btn btn btn-xs join-item font-mono" data-scale="5">5×</button>
451
145
  </div>
452
146
  <span id="chain-summary-badge" class="badge badge-sm badge-primary font-mono font-bold ml-2">0 Tables</span>
453
147
  </div>
454
148
  </div>
455
149
  <div class="app-card p-4 space-y-3">
456
150
  <div class="flex items-center justify-between pb-2 border-b border-base-200">
457
151
  <span class="text-xs font-bold uppercase tracking-wider text-base-content/70">Topological Execution Pipeline</span>
458
152
  <span class="text-[11px] text-base-content/40">Dependencies ordered upstream-first</span>
459
153
  </div>
460
154
  <div id="chain-pipeline-container" class="space-y-2.5">
461
155
  </div>
462
156
  </div>
463
157
  </div>
464
158
  <details class="app-card group">
465
159
  <summary class="p-3.5 flex items-center justify-between cursor-pointer list-none select-none text-xs font-bold text-base-content/70 hover:text-base-content">
466
160
  <div class="flex items-center gap-2">
467
161
  {{{icon "settings" class="h-3.5 w-3.5"}}}
468
162
  <span>Advanced Execution Options</span>
469
163
  </div>
470
164
  <span class="text-xs text-base-content/40 group-open:rotate-180 transition-transform">▼</span>
471
165
  </summary>
472
166
  <div class="p-3.5 pt-0 border-t border-base-200/80 mt-1 flex flex-wrap items-center gap-6 text-xs">
473
167
  <label class="cursor-pointer flex items-center gap-2 select-none group">
474
168
  <input id="plan-transaction-opt" type="checkbox" checked class="checkbox checkbox-primary checkbox-xs" />
475
169
  <span class="font-medium text-base-content/80 group-hover:text-base-content">Wrap in Transaction (BEGIN ... COMMIT)</span>
476
170
  </label>
477
171
  <label class="cursor-pointer flex items-center gap-2 select-none group">
478
172
  <input id="plan-rollback-opt" type="checkbox" checked class="checkbox checkbox-primary checkbox-xs" />
479
173
  <span class="font-medium text-base-content/80 group-hover:text-base-content">Atomic Rollback on Error</span>
480
174
  </label>
481
175
  <label class="cursor-pointer flex items-center gap-2 select-none group">
482
176
  <input id="seed-truncate" type="checkbox" class="checkbox checkbox-error checkbox-xs" />
483
177
  <span class="font-medium text-error/90 group-hover:text-error">Clear tables before inserting (Truncate)</span>
484
178
  </label>
485
179
  </div>
486
180
  </details>
487
181
  </div>
488
182
  <div class="xl:col-span-5 space-y-4 xl:sticky xl:top-4">
489
183
  <div id="validation-report-card" class="app-card p-3.5 space-y-2">
490
184
  <div class="flex items-center justify-between">
491
185
  <div id="validation-summary-pill" class="flex items-center gap-2">
492
186
  <span id="validation-status-dot" class="w-2 h-2 rounded-full bg-success"></span>
493
187
  <span id="validation-status-text" class="text-xs font-mono font-bold text-base-content">Plan Ready</span>
494
188
  </div>
495
189
  <span id="validation-summary-chip" class="badge badge-sm badge-success font-mono text-[10px] font-bold">All Checks Passed</span>
496
190
  </div>
497
191
  <div id="validation-issues-list" class="space-y-1.5 text-xs">
498
192
  <div class="flex items-center gap-2 text-success font-medium text-[11px]">
499
193
  {{{icon "check" class="h-3.5 w-3.5 shrink-0"}}}
500
194
  <span>Primary key & constraint strategies valid</span>
501
195
  </div>
502
196
  </div>
503
197
  </div>
504
198
  <div class="app-card overflow-hidden">
505
199
  <div class="flex items-center justify-between p-3 border-b border-base-200 bg-base-100 gap-2 flex-wrap">
506
200
  <div class="join">
507
201
  <button type="button" id="preview-tab-grid" class="btn btn-xs join-item btn-active font-bold">Table Preview</button>
508
202
  <button type="button" id="preview-tab-sql" class="btn btn-xs join-item font-bold">SQL Script</button>
509
203
  </div>
510
204
  <button id="seed-refresh-preview" type="button" class="btn btn-xs btn-ghost gap-1 text-xs text-base-content/70 hover:text-primary">
511
205
  {{{icon "refresh" class="h-3 w-3"}}}
512
206
  <span>Refresh</span>
513
207
  </button>
514
208
  </div>
515
209
  <div id="seed-chain-table-tabs" class="tabs tabs-bordered flex-nowrap w-full overflow-x-auto hidden px-3 py-1 bg-base-200/40 border-b border-base-200 text-xs"></div>
516
210
  <div id="preview-view-grid">
517
211
  <div class="overflow-x-auto max-h-[440px]">
518
212
  <table class="table table-zebra table-pin-rows table-xs w-full">
519
213
  <thead id="seed-preview-thead" class="bg-base-200/90 text-[10px] uppercase font-mono tracking-wider text-base-content/70 backdrop-blur sticky top-0 z-10"></thead>
520
214
  <tbody id="seed-preview-tbody" class="font-mono text-[11px]">
521
215
  <tr>
522
216
  <td colspan="100" class="text-center py-12 opacity-50">
523
217
  <div class="flex flex-col items-center gap-2">
524
218
  <span class="loading loading-spinner loading-sm text-primary"></span>
525
219
  <span class="text-xs">Generating preview…</span>
526
220
  </div>
527
221
  </td>
528
222
  </tr>
529
223
  </tbody>
530
224
  </table>
531
225
  </div>
532
226
  </div>
533
227
  <div id="preview-view-sql" class="hidden p-3 bg-base-200/20 space-y-2">
534
228
  <div class="flex items-center justify-between">
535
229
  <span class="text-[11px] font-mono text-base-content/50 uppercase font-bold">Generated SQL (Preview)</span>
536
230
  <button type="button" id="btn-copy-sql" class="btn btn-xs btn-outline gap-1 text-[11px]">
537
231
  {{{icon "copy" class="h-3 w-3"}}}
538
232
  <span>Copy SQL</span>
539
233
  </button>
540
234
  </div>
541
235
  <pre id="preview-sql-code" class="bg-neutral text-neutral-content p-3.5 rounded-lg font-mono text-xs overflow-x-auto max-h-[380px] border border-base-300 leading-relaxed"></pre>
542
236
  </div>
543
237
  </div>
544
238
  <div id="seed-truncate-banner" class="hidden p-3 rounded-lg bg-error/10 border border-error/20 flex items-center gap-2.5">
545
239
  <span class="text-error shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
546
240
  <p class="text-xs font-bold text-error">
547
241
  Destructive Action: Existing table rows will be truncated before seeding.
548
242
  </p>
549
243
  </div>
550
244
  <div id="seed-execute-bar" class="hidden"></div>
551
245
  <div id="seed-feedback" class="hidden"></div>
552
246
  </div>
553
247
  </div>
554
248
  <div class="modal-box p-0 overflow-hidden max-w-lg rounded-2xl border border-base-200 shadow-xl">
555
249
  <div class="px-5 py-4 bg-base-200/50 border-b border-base-200 flex items-center justify-between">
556
250
  <div class="flex items-center gap-2.5">
557
251
  {{{icon "book" class="h-4 w-4 text-primary"}}}
558
252
  <h3 class="font-bold text-sm text-base-content">Seed Profiles & Presets</h3>
559
253
  </div>
560
254
  <button type="button" class="btn btn-xs btn-circle btn-ghost" id="btn-close-profiles">✕</button>
561
255
  </div>
562
256
  <div class="p-5 space-y-4 text-xs">
563
257
  <div>
564
258
  <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/50 mb-2">Quick Blueprints</h4>
565
259
  <div class="grid grid-cols-3 gap-2">
566
260
  <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="smoke">⚡ Smoke (10)</button>
567
261
  <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="realistic">🌱 Standard (100)</button>
568
262
  <button type="button" class="btn-preset-profile btn btn-xs btn-outline font-mono" data-preset="stress">🚀 Stress (1000)</button>
569
263
  </div>
570
264
  </div>
571
265
  <div class="p-3 rounded-lg bg-base-200/40 border border-base-300 space-y-2">
572
266
  <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/60">Save Current Configuration</h4>
573
267
  <div class="flex gap-2">
574
268
  <input id="profile-name-input" type="text" placeholder="Profile name (e.g. Test Dataset)"
575
269
  class="field-input flex-1 text-xs !py-1 font-medium" />
576
270
  <button type="button" id="btn-save-profile" class="btn btn-xs btn-primary px-3 font-bold">Save</button>
577
271
  </div>
578
272
  </div>
579
273
  <div>
580
274
  <h4 class="font-bold text-[10px] uppercase tracking-wider text-base-content/50 mb-1.5">Saved Profiles</h4>
581
275
  <div id="profiles-list-container" class="space-y-1.5 max-h-48 overflow-y-auto pr-1">
582
276
  <div class="py-4 text-center text-xs text-base-content/40">No saved profiles yet.</div>
583
277
  </div>
584
278
  </div>
585
279
  </div>
586
280
  </div>
587
281
  <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>
588
282
  <div class="modal-box p-0 overflow-hidden max-w-md rounded-2xl border border-error/20 shadow-xl">
589
283
  <div class="px-5 py-4 bg-error/5 border-b border-error/15 flex items-center gap-2.5">
590
284
  <span class="text-error">{{{icon "warning" class="h-5 w-5"}}}</span>
591
285
  <h3 class="font-bold text-sm text-error">Confirm Truncate Action</h3>
592
286
  </div>
593
287
  <div class="p-5 space-y-3 text-xs text-base-content/80 leading-relaxed">
594
288
  <p>
595
289
  You have enabled <strong class="text-error">Clear tables before inserting</strong>. All existing records in affected tables will be permanently deleted in reverse topological order before new rows are inserted.
596
290
  </p>
597
291
  </div>
598
292
  <div class="px-5 pb-4 flex items-center justify-end gap-2">
599
293
  <button type="button" class="btn btn-ghost btn-xs" id="seed-truncate-cancel">Cancel</button>
600
294
  <button type="button" class="btn btn-error btn-xs font-bold gap-1.5" id="seed-truncate-confirm">
601
295
  {{{icon "warning" class="h-3.5 w-3.5"}}}
602
296
  <span>Yes, Truncate & Seed</span>
603
297
  </button>
604
298
  </div>
605
299
  </div>
606
300
  <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>