admindb 2.1.1 → 2.3.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 (119) hide show
  1. package/README.md +368 -335
  2. package/dist/app.js +227 -1
  3. package/dist/auth/config.d.ts +1 -1
  4. package/dist/auth/config.js +109 -1
  5. package/dist/auth/crypto.js +98 -1
  6. package/dist/auth/index.js +21 -1
  7. package/dist/auth/middleware.js +78 -1
  8. package/dist/auth/routes.js +64 -1
  9. package/dist/auth/types.js +7 -1
  10. package/dist/cli/args.d.ts +1 -1
  11. package/dist/cli/args.js +309 -1
  12. package/dist/cli/config.js +118 -1
  13. package/dist/cli/index.js +20 -1
  14. package/dist/cli/runner.js +208 -1
  15. package/dist/cli.js +4 -1
  16. package/dist/data/chain.d.ts +1 -0
  17. package/dist/data/chain.js +130 -0
  18. package/dist/data/datasets.d.ts +1 -1
  19. package/dist/data/datasets.js +171 -1
  20. package/dist/data/detector.d.ts +1 -1
  21. package/dist/data/detector.js +535 -1
  22. package/dist/data/engine.d.ts +1 -1
  23. package/dist/data/engine.js +586 -1
  24. package/dist/data/index.d.ts +1 -1
  25. package/dist/data/index.js +30 -1
  26. package/dist/data/prng.d.ts +1 -0
  27. package/dist/data/prng.js +73 -0
  28. package/dist/data/registry.d.ts +1 -0
  29. package/dist/data/registry.js +805 -0
  30. package/dist/data/schema-graph.d.ts +1 -0
  31. package/dist/data/schema-graph.js +210 -0
  32. package/dist/data/strategies.d.ts +1 -1
  33. package/dist/data/strategies.js +100 -1
  34. package/dist/data/templates.d.ts +1 -0
  35. package/dist/data/templates.js +134 -0
  36. package/dist/data/types.d.ts +1 -1
  37. package/dist/data/types.js +5 -1
  38. package/dist/data/validator.d.ts +1 -0
  39. package/dist/data/validator.js +160 -0
  40. package/dist/db/database.d.ts +1 -1
  41. package/dist/db/database.js +472 -1
  42. package/dist/db/export.d.ts +1 -1
  43. package/dist/db/export.js +67 -1
  44. package/dist/db/filters.d.ts +1 -1
  45. package/dist/db/filters.js +119 -1
  46. package/dist/db/index.js +24 -1
  47. package/dist/db/introspection.js +164 -1
  48. package/dist/db/manager.js +327 -1
  49. package/dist/db/migrations.js +100 -1
  50. package/dist/db/postgres.d.ts +1 -1
  51. package/dist/db/postgres.js +687 -1
  52. package/dist/db/types.d.ts +1 -1
  53. package/dist/db/types.js +6 -1
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.js +52 -1
  56. package/dist/public/css/app.css +1 -1
  57. package/dist/public/js/api.js +1 -1
  58. package/dist/public/js/browse.js +1 -1
  59. package/dist/public/js/common.js +1 -0
  60. package/dist/public/js/databases.js +1 -1
  61. package/dist/public/js/designer.js +1 -1
  62. package/dist/public/js/forms.js +1 -1
  63. package/dist/public/js/home.js +1 -0
  64. package/dist/public/js/inspector.js +1 -1
  65. package/dist/public/js/query.js +1 -1
  66. package/dist/public/js/schema.js +1 -1
  67. package/dist/public/js/seed.js +1 -1
  68. package/dist/routes/api/erd.d.ts +1 -0
  69. package/dist/routes/api/erd.js +45 -0
  70. package/dist/routes/api/helpers.d.ts +1 -1
  71. package/dist/routes/api/helpers.js +213 -1
  72. package/dist/routes/api/import-export.js +82 -1
  73. package/dist/routes/api/index.js +48 -1
  74. package/dist/routes/api/query.js +74 -1
  75. package/dist/routes/api/rows.js +358 -1
  76. package/dist/routes/api/seed.js +167 -1
  77. package/dist/routes/api/tables.js +216 -1
  78. package/dist/routes/databases.js +210 -1
  79. package/dist/routes/index.js +19 -1
  80. package/dist/routes/pages.js +446 -1
  81. package/dist/serverless.js +149 -1
  82. package/dist/sql/classifier.js +24 -1
  83. package/dist/sql/error-analyzer.d.ts +1 -0
  84. package/dist/sql/error-analyzer.js +550 -0
  85. package/dist/sql/generator.d.ts +1 -1
  86. package/dist/sql/generator.js +245 -1
  87. package/dist/sql/index.js +18 -1
  88. package/dist/types/api.d.ts +1 -1
  89. package/dist/types/api.js +2 -1
  90. package/dist/utils/colors.js +54 -1
  91. package/dist/utils/common.d.ts +1 -1
  92. package/dist/utils/common.js +185 -1
  93. package/dist/utils/csv.d.ts +1 -1
  94. package/dist/utils/csv.js +61 -1
  95. package/dist/utils/datatype.js +167 -1
  96. package/dist/utils/icons.js +81 -1
  97. package/dist/utils/index.js +20 -1
  98. package/dist/utils/logger.js +36 -1
  99. package/dist/views/layouts/main.hbs +1 -74
  100. package/dist/views/pages/databases.hbs +1 -233
  101. package/dist/views/pages/designer.hbs +1 -89
  102. package/dist/views/pages/erd.hbs +1 -0
  103. package/dist/views/pages/error.hbs +1 -10
  104. package/dist/views/pages/form.hbs +1 -59
  105. package/dist/views/pages/home.hbs +1 -124
  106. package/dist/views/pages/info.hbs +1 -0
  107. package/dist/views/pages/login.hbs +1 -98
  108. package/dist/views/pages/query.hbs +1 -87
  109. package/dist/views/pages/schema.hbs +1 -298
  110. package/dist/views/pages/seed-select.hbs +251 -0
  111. package/dist/views/pages/seed.hbs +273 -167
  112. package/dist/views/pages/table.hbs +1 -327
  113. package/dist/views/partials/navbar.hbs +1 -83
  114. package/dist/views/partials/sidebar.hbs +1 -117
  115. package/docs/API.md +149 -144
  116. package/docs/EXAMPLES.md +579 -576
  117. package/docs/SECURITY.md +265 -265
  118. package/package.json +79 -78
  119. package/dist/public/js/icons.js +0 -1
@@ -1,201 +1,307 @@
1
- <div class="space-y-6">
2
- <div class="flex flex-wrap items-center justify-between gap-4 border-b border-base-200 pb-5">
3
- <div class="flex items-center gap-3">
4
- <a href="{{basePath}}/tables/{{table}}" class="btn btn-circle btn-ghost btn-sm" aria-label="Back to table">
5
- {{{icon "arrowLeft" class="h-5 w-5"}}}
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" 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
6
  </a>
7
- <div>
8
- <div class="flex flex-wrap items-center gap-2">
9
- <h1 class="font-mono text-2xl font-bold tracking-tight">{{table}}</h1>
10
- <span class="badge badge-sm badge-neutral font-mono">{{rowCount}} rows in DB</span>
11
- <span class="badge badge-sm badge-ghost font-mono">{{colCount}} columns</span>
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" 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/{{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>
12
27
  </div>
13
- <p class="mt-0.5 text-xs text-base-content/55">Data generator — fill the table with realistic mock data, simulate sparse records, and preview in real time.</p>
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}}
14
35
  </div>
15
36
  </div>
16
- <div class="flex flex-wrap items-center gap-2">
17
- <div class="dropdown dropdown-end">
18
- <button tabindex="0" type="button" class="btn btn-outline btn-sm gap-1.5">
19
- {{{icon "seed" class="h-4 w-4"}}}
20
- Presets
21
- {{{icon "chevronDown" class="h-3.5 w-3.5 opacity-60"}}}
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>
22
46
  </button>
23
- <ul tabindex="0" class="dropdown-content z-20 menu p-2 shadow-lg bg-base-100 rounded-xl w-56 border border-base-200 text-xs">
24
- <li><button type="button" id="preset-realistic" class="py-2">✨ Realistic Mock Data</button></li>
25
- <li><button type="button" id="preset-minimal" class="py-2">⚡ Minimal (Required Only)</button></li>
26
- <li><button type="button" id="preset-sparse" class="py-2">🎲 Sparse (30% Nullables)</button></li>
27
- <li><button type="button" id="preset-numbered" class="py-2">🔢 Sequential & Numbered</button></li>
28
- <li class="border-t border-base-200 my-1"></li>
29
- <li><button type="button" id="seed-export-config" class="py-2">💾 Export Plan as JSON</button></li>
30
- <li><button type="button" id="seed-import-config" class="py-2">📥 Import Plan JSON…</button></li>
31
- </ul>
32
47
  </div>
33
- <button id="seed-preview" type="button" class="btn btn-outline btn-sm gap-1.5">
34
- {{{icon "inspect" class="h-4 w-4 text-primary"}}}
35
- Preview Data
36
- </button>
37
- {{#unless readonly}}
38
- <button id="seed-insert" type="button" class="btn btn-primary btn-sm gap-1.5 shadow-sm">
39
- {{{icon "plus" class="h-4 w-4"}}}
40
- Insert Rows
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>
41
64
  </button>
42
- {{else}}
43
- <span class="inline-flex items-center gap-1.5 text-xs font-medium text-warning bg-warning/10 px-2.5 py-1.5 rounded-lg">
44
- {{{icon "lock" class="h-4 w-4"}}}
45
- Read-only database
46
- </span>
47
- {{/unless}}
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>
48
78
  </div>
49
79
  </div>
50
- <div class="app-card p-5 bg-base-100">
51
- <div class="grid grid-cols-1 gap-5 lg:grid-cols-12 lg:items-end">
52
- <div class="lg:col-span-4 space-y-1.5">
53
- <label class="field-label !mb-0 font-medium" for="seed-count">
54
- <span>Rows to generate</span>
55
- <span class="text-xs text-base-content/45 font-normal">(max {{maxRows}})</span>
56
- </label>
57
- <div class="flex items-center gap-2">
58
- <input id="seed-count" type="number" min="1" max="{{maxRows}}" value="10" class="field-input w-28 font-mono font-medium" />
59
- <div class="flex flex-wrap items-center gap-1">
60
- {{#each quickCounts}}
61
- <button type="button" class="seed-quick btn btn-outline btn-xs px-2.5" data-n="{{this}}">{{this}}</button>
62
- {{/each}}
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">
63
124
  </div>
64
125
  </div>
65
126
  </div>
66
- <div class="lg:col-span-4 space-y-1.5">
67
- <label class="field-label !mb-0 font-medium" for="seed-search">
68
- <span>Filter columns</span>
69
- </label>
70
- <div class="relative">
71
- <span class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-base-content/40">
72
- {{{icon "search" class="h-4 w-4"}}}
73
- </span>
74
- <input id="seed-search" type="text" placeholder="Search column by name or type..." class="field-input pl-9 text-xs" />
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>
75
156
  </div>
76
157
  </div>
77
- <div class="lg:col-span-4 flex flex-col justify-end space-y-2">
78
- {{#unless readonly}}
79
- <label class="cursor-pointer flex items-center gap-2 text-xs font-medium text-base-content/80 hover:text-base-content transition-colors">
80
- <input id="seed-truncate" type="checkbox" class="checkbox checkbox-xs checkbox-error rounded" />
81
- <span class="flex items-center gap-1 text-error/90">
82
- {{{icon "trash" class="h-3.5 w-3.5"}}}
83
- Clear table before inserting (DELETE all rows)
84
- </span>
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>
85
170
  </label>
86
- {{/unless}}
87
- <p class="text-[11px] text-base-content/45 leading-tight">Rows are inserted in a single atomic transaction. Any constraint failure safely rolls back.</p>
88
- </div>
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>
89
181
  </div>
90
- </div>
91
- <div class="space-y-3">
92
- <div class="flex flex-wrap items-center justify-between gap-2">
93
- <div class="flex items-center gap-2">
94
- <h2 class="text-sm font-semibold uppercase tracking-wider text-base-content/50">Column Strategies</h2>
95
- <span id="seed-col-count-badge" class="badge badge-sm badge-ghost font-mono"></span>
96
- </div>
97
- <div class="flex flex-wrap items-center gap-1.5">
98
- <button id="seed-refresh-samples" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/60" title="Refresh live sample previews">
99
- {{{icon "refresh" class="h-3.5 w-3.5"}}}
100
- Refresh Samples
101
- </button>
102
- <button id="seed-apply-all" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/60">
103
- {{{icon "duplicate" class="h-3.5 w-3.5"}}}
104
- Apply strategy to all…
105
- </button>
106
- <button id="seed-reset" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/60">
107
- {{{icon "refresh" class="h-3.5 w-3.5"}}}
108
- Reset Defaults
109
- </button>
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>
110
197
  </div>
111
- </div>
112
- <div id="seed-columns" class="grid grid-cols-1 gap-3.5 md:grid-cols-2 2xl:grid-cols-3"></div>
113
- <div id="seed-empty-search" class="hidden p-8 text-center app-card">
114
- <p class="text-sm text-base-content/50">No columns match the current search query.</p>
115
- </div>
116
- </div>
117
- <div id="seed-feedback" class="hidden"></div>
118
- <div id="seed-preview-card" class="hidden app-card overflow-hidden transition-all duration-200">
119
- <div class="flex flex-wrap items-center justify-between border-b border-base-200 bg-base-200/40 px-5 py-3 gap-3">
120
- <div class="flex items-center gap-3">
121
- <div class="tabs tabs-boxed bg-base-300/40 p-0.5 rounded-lg">
122
- <button id="tab-table-view" type="button" class="tab tab-sm tab-active font-medium gap-1.5">
123
- {{{icon "table" class="h-3.5 w-3.5"}}}
124
- Table Preview
125
- </button>
126
- <button id="tab-sql-view" type="button" class="tab tab-sm font-medium gap-1.5">
127
- {{{icon "sql" class="h-3.5 w-3.5"}}}
128
- SQL Statements
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>
129
207
  </button>
130
208
  </div>
131
- <span id="preview-summary-badge" class="badge badge-sm badge-ghost font-mono"></span>
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>
132
237
  </div>
133
- <div class="flex flex-wrap items-center gap-1.5">
134
- <button id="seed-export-csv" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
135
- {{{icon "export" class="h-3.5 w-3.5"}}}
136
- Export CSV
137
- </button>
138
- <button id="seed-export-json" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
139
- {{{icon "export" class="h-3.5 w-3.5"}}}
140
- Export JSON
141
- </button>
142
- <button id="seed-copy-sql" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
143
- {{{icon "copy" class="h-3.5 w-3.5"}}}
144
- Copy SQL
145
- </button>
146
- <button id="seed-download-sql" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
147
- {{{icon "export" class="h-3.5 w-3.5"}}}
148
- Download .sql
149
- </button>
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>
150
243
  </div>
151
- </div>
152
- <div id="seed-table-view-container" class="overflow-x-auto max-h-[32rem]">
153
- <table class="table table-sm table-pin-rows table-zebra w-full text-xs">
154
- <thead id="seed-preview-thead" class="bg-base-200 font-mono text-[11px] text-base-content/70"></thead>
155
- <tbody id="seed-preview-tbody"></tbody>
156
- </table>
157
- </div>
158
- <div id="seed-sql-view-container" class="hidden p-4">
159
- <pre class="code-panel max-h-[32rem] overflow-auto"><code id="seed-sql-code"></code></pre>
244
+ <div id="seed-execute-bar" class="hidden"></div>
245
+ <div id="seed-feedback" class="hidden"></div>
160
246
  </div>
161
247
  </div>
162
248
  </div>
163
- <dialog id="seed-config-dialog" class="modal">
164
- <div class="modal-box app-card max-w-lg">
165
- <h3 id="seed-config-dialog-title" class="text-base font-bold">Seed Plan Configuration</h3>
166
- <p class="mt-1 text-xs text-base-content/60">Export or paste a JSON configuration for column generator settings.</p>
167
- <textarea id="seed-config-textarea" rows="12" class="field-input mt-3 w-full font-mono text-xs" spellcheck="false"></textarea>
168
- <div class="mt-4 flex justify-end gap-2">
169
- <button id="seed-config-dialog-cancel" type="button" class="btn btn-ghost btn-sm">Close</button>
170
- <button id="seed-config-dialog-apply" type="button" class="btn btn-primary btn-sm">Apply Configuration</button>
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>
171
281
  </div>
172
282
  </div>
173
- <form method="dialog" class="modal-backdrop">
174
- <button>close</button>
175
- </form>
283
+ <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>
176
284
  </dialog>
177
285
  <dialog id="seed-truncate-dialog" class="modal">
178
- <div class="modal-box app-card max-w-md border border-error/30">
179
- <div class="flex items-center gap-3 text-error">
180
- <span class="grid h-10 w-10 shrink-0 place-items-center rounded-xl bg-error/10">
181
- {{{icon "warning" class="h-6 w-6"}}}
182
- </span>
183
- <div>
184
- <h3 class="text-base font-bold text-base-content">Clear table before inserting?</h3>
185
- <p class="text-xs text-error font-medium">All existing rows in "{{table}}" will be permanently deleted.</p>
186
- </div>
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>
187
290
  </div>
188
- <p class="mt-3 text-xs text-base-content/60 leading-relaxed">
189
- This will execute <code>DELETE FROM "{{table}}"</code> before inserting the newly generated seed rows. This action cannot be undone.
190
- </p>
191
- <div class="mt-5 flex justify-end gap-2">
192
- <button id="seed-truncate-cancel" type="button" class="btn btn-ghost btn-sm">Cancel</button>
193
- <button id="seed-truncate-confirm" type="button" class="btn btn-error btn-sm">Yes, Clear & Insert</button>
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>
194
302
  </div>
195
303
  </div>
196
- <form method="dialog" class="modal-backdrop">
197
- <button>close</button>
198
- </form>
304
+ <form method="dialog" class="modal-backdrop bg-base-300/60 backdrop-blur-sm"><button>close</button></form>
199
305
  </dialog>
200
306
  <script id="seed-config" type="application/json">{{{json seedConfig}}}</script>
201
307
  <script src="{{basePath}}/js/seed.js" defer></script>