admindb 2.2.1 → 2.3.1

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 (89) hide show
  1. package/README.md +368 -364
  2. package/dist/app.js +25 -16
  3. package/dist/auth/config.d.ts +1 -1
  4. package/dist/auth/config.js +18 -30
  5. package/dist/auth/crypto.js +11 -21
  6. package/dist/auth/middleware.js +9 -16
  7. package/dist/auth/routes.js +9 -15
  8. package/dist/cli/args.d.ts +1 -1
  9. package/dist/cli/args.js +20 -29
  10. package/dist/cli/config.d.ts +1 -1
  11. package/dist/cli/config.js +15 -18
  12. package/dist/cli/runner.js +13 -13
  13. package/dist/data/chain.d.ts +1 -1
  14. package/dist/data/chain.js +40 -617
  15. package/dist/data/datasets.d.ts +1 -1
  16. package/dist/data/datasets.js +43 -1
  17. package/dist/data/detector.js +45 -21
  18. package/dist/data/engine.d.ts +1 -1
  19. package/dist/data/engine.js +483 -142
  20. package/dist/data/index.d.ts +1 -1
  21. package/dist/data/index.js +8 -0
  22. package/dist/data/prng.d.ts +1 -0
  23. package/dist/data/prng.js +73 -0
  24. package/dist/data/registry.d.ts +1 -0
  25. package/dist/data/registry.js +805 -0
  26. package/dist/data/schema-graph.d.ts +1 -0
  27. package/dist/data/schema-graph.js +210 -0
  28. package/dist/data/strategies.d.ts +1 -1
  29. package/dist/data/strategies.js +44 -283
  30. package/dist/data/templates.d.ts +1 -0
  31. package/dist/data/templates.js +134 -0
  32. package/dist/data/types.d.ts +1 -1
  33. package/dist/data/validator.d.ts +1 -0
  34. package/dist/data/validator.js +160 -0
  35. package/dist/db/database.js +9 -14
  36. package/dist/db/export.js +32 -55
  37. package/dist/db/filters.d.ts +1 -1
  38. package/dist/db/filters.js +15 -38
  39. package/dist/db/introspection.js +4 -7
  40. package/dist/db/manager.d.ts +1 -1
  41. package/dist/db/manager.js +48 -53
  42. package/dist/db/migrations.js +7 -14
  43. package/dist/db/postgres.js +30 -78
  44. package/dist/index.d.ts +1 -1
  45. package/dist/public/css/app.css +1 -1
  46. package/dist/public/js/browse.js +1 -1
  47. package/dist/public/js/inspector.js +1 -1
  48. package/dist/public/js/query.js +1 -1
  49. package/dist/public/js/seed.js +1 -1
  50. package/dist/routes/api/erd.js +3 -8
  51. package/dist/routes/api/helpers.d.ts +1 -1
  52. package/dist/routes/api/helpers.js +75 -25
  53. package/dist/routes/api/import-export.js +1 -2
  54. package/dist/routes/api/query.js +2 -6
  55. package/dist/routes/api/rows.js +4 -8
  56. package/dist/routes/api/seed.js +35 -21
  57. package/dist/routes/api/tables.js +15 -30
  58. package/dist/routes/databases.js +8 -26
  59. package/dist/routes/pages.js +67 -18
  60. package/dist/serverless.js +31 -44
  61. package/dist/sql/generator.d.ts +1 -1
  62. package/dist/sql/generator.js +35 -109
  63. package/dist/types/api.d.ts +1 -1
  64. package/dist/utils/common.d.ts +1 -1
  65. package/dist/utils/common.js +45 -85
  66. package/dist/utils/csv.d.ts +1 -1
  67. package/dist/utils/csv.js +11 -17
  68. package/dist/utils/datatype.js +46 -60
  69. package/dist/utils/icons.js +8 -8
  70. package/dist/views/layouts/main.hbs +1 -87
  71. package/dist/views/pages/databases.hbs +1 -233
  72. package/dist/views/pages/designer.hbs +1 -89
  73. package/dist/views/pages/erd.hbs +1 -1241
  74. package/dist/views/pages/error.hbs +1 -10
  75. package/dist/views/pages/form.hbs +1 -59
  76. package/dist/views/pages/home.hbs +1 -220
  77. package/dist/views/pages/info.hbs +1 -107
  78. package/dist/views/pages/login.hbs +1 -98
  79. package/dist/views/pages/query.hbs +1 -129
  80. package/dist/views/pages/schema.hbs +1 -298
  81. package/dist/views/pages/seed-select.hbs +251 -0
  82. package/dist/views/pages/seed.hbs +256 -414
  83. package/dist/views/pages/table.hbs +1 -327
  84. package/dist/views/partials/navbar.hbs +1 -83
  85. package/dist/views/partials/sidebar.hbs +1 -129
  86. package/docs/API.md +149 -149
  87. package/docs/EXAMPLES.md +579 -579
  88. package/docs/SECURITY.md +265 -265
  89. package/package.json +80 -79
@@ -0,0 +1,251 @@
1
+ <div class="space-y-6 max-w-5xl mx-auto pb-16">
2
+ <div class="page-header">
3
+ <div class="page-header-row">
4
+ <div>
5
+ <div class="page-pretitle">Developer Tools</div>
6
+ <h1 class="page-title">Seed Data Generator</h1>
7
+ <p class="mt-0.5 text-xs text-base-content/60">
8
+ Generate realistic mock datasets with column heuristics or populate complete relational entity graphs.
9
+ </p>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ {{#if hasTables}}
14
+ <div class="grid gap-6 lg:grid-cols-[1fr_380px]">
15
+ <div class="space-y-4">
16
+ <div class="app-card overflow-hidden">
17
+ <div class="p-4 sm:p-5 border-b border-base-200 bg-base-200/30 flex flex-wrap items-center justify-between gap-3">
18
+ <div>
19
+ <h2 class="text-sm font-bold text-base-content flex items-center gap-2">
20
+ <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/15 text-primary text-xs font-bold font-mono">1</span>
21
+ Choose Target Table
22
+ </h2>
23
+ <p class="text-[11px] text-base-content/50 mt-0.5">Select the root table to generate rows for.</p>
24
+ </div>
25
+ <div class="w-full sm:w-56">
26
+ <div class="relative">
27
+ <span class="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-base-content/40">
28
+ {{{icon "search" class="h-3.5 w-3.5"}}}
29
+ </span>
30
+ <input id="table-search-input" type="text" placeholder="Filter tables…" autocomplete="off"
31
+ class="field-input text-xs !py-1 !pl-8 w-full" />
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div id="table-cards-list" class="p-3 sm:p-4 space-y-2 max-h-[480px] overflow-y-auto">
36
+ {{#each tables}}
37
+ <label class="table-option-card block cursor-pointer select-none rounded-xl border p-3 transition-all {{#if (eq this.name ../defaultTable)}}border-primary bg-primary/[0.04] shadow-sm{{else}}border-base-200 bg-base-100 hover:border-base-300 hover:bg-base-200/40{{/if}}"
38
+ data-table="{{this.name}}">
39
+ <div class="flex items-center justify-between gap-3">
40
+ <div class="flex items-center gap-3 min-w-0">
41
+ <input type="radio" name="selected_table" value="{{this.name}}" class="radio radio-primary radio-xs"
42
+ {{#if (eq this.name ../defaultTable)}}checked{{/if}} />
43
+ <div class="min-w-0">
44
+ <div class="font-mono font-bold text-sm text-base-content truncate flex items-center gap-2">
45
+ {{{icon "table" class="h-3.5 w-3.5 text-base-content/50 shrink-0"}}}
46
+ <span>{{this.name}}</span>
47
+ </div>
48
+ <div class="flex items-center gap-2 mt-0.5 text-[11px] text-base-content/50">
49
+ <span>{{this.cols}} cols</span>
50
+ <span>·</span>
51
+ <span>{{this.rowCount}} existing rows</span>
52
+ {{#if this.fks}}
53
+ <span>·</span>
54
+ <span class="text-amber-500 font-medium">{{this.fks}} FK refs</span>
55
+ {{/if}}
56
+ </div>
57
+ </div>
58
+ </div>
59
+ <div class="flex items-center gap-1 shrink-0">
60
+ <button type="button" class="btn btn-ghost btn-xs text-[11px] text-base-content/70 hover:text-primary quick-seed-btn"
61
+ data-table="{{this.name}}" data-mode="single" title="Seed this table directly">
62
+ Single
63
+ </button>
64
+ <button type="button" class="btn btn-ghost btn-xs text-[11px] text-emerald-600 hover:text-emerald-500 quick-seed-btn"
65
+ data-table="{{this.name}}" data-mode="chain" title="Seed relational ER chain directly">
66
+ ER Chain
67
+ </button>
68
+ </div>
69
+ </div>
70
+ </label>
71
+ {{/each}}
72
+ </div>
73
+ </div>
74
+ </div>
75
+ <div class="space-y-4 lg:sticky lg:top-20 self-start">
76
+ <div class="app-card overflow-hidden">
77
+ <div class="p-4 border-b border-base-200 bg-base-200/30">
78
+ <h2 class="text-sm font-bold text-base-content flex items-center gap-2">
79
+ <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/15 text-primary text-xs font-bold font-mono">2</span>
80
+ Choose Generation Mode
81
+ </h2>
82
+ <p class="text-[11px] text-base-content/50 mt-0.5">Select how rows should be populated.</p>
83
+ </div>
84
+ <div class="p-3.5 space-y-2.5">
85
+ <label class="mode-option-card block cursor-pointer select-none rounded-xl border p-3.5 transition-all {{#if (eq defaultMode 'single')}}border-primary bg-primary/[0.04] shadow-sm{{else}}border-base-200 bg-base-100 hover:border-base-300 hover:bg-base-200/40{{/if}}"
86
+ data-mode="single">
87
+ <div class="flex items-start gap-3">
88
+ <input type="radio" name="selected_mode" value="single" class="radio radio-primary radio-xs mt-0.5"
89
+ {{#if (eq defaultMode 'single')}}checked{{/if}} />
90
+ <div class="space-y-1">
91
+ <div class="flex items-center gap-2">
92
+ <span class="font-bold text-xs text-base-content">Single Table Seeder</span>
93
+ <span class="badge badge-xs badge-ghost text-[10px] font-mono">Standalone</span>
94
+ </div>
95
+ <p class="text-[11px] text-base-content/60 leading-relaxed">
96
+ Generates realistic rows for the selected table with automated column heuristics (names, emails, dates, addresses, UUIDs) and live formula templates.
97
+ </p>
98
+ </div>
99
+ </div>
100
+ </label>
101
+ <label class="mode-option-card block cursor-pointer select-none rounded-xl border p-3.5 transition-all {{#if (eq defaultMode 'chain')}}border-primary bg-primary/[0.04] shadow-sm{{else}}border-base-200 bg-base-100 hover:border-base-300 hover:bg-base-200/40{{/if}}"
102
+ data-mode="chain">
103
+ <div class="flex items-start gap-3">
104
+ <input type="radio" name="selected_mode" value="chain" class="radio radio-primary radio-xs mt-0.5"
105
+ {{#if (eq defaultMode 'chain')}}checked{{/if}} />
106
+ <div class="space-y-1">
107
+ <div class="flex items-center gap-2">
108
+ <span class="font-bold text-xs text-base-content">Relational ER Chain Seeder</span>
109
+ <span class="badge badge-xs badge-outline badge-success text-[10px] font-mono">Full Graph</span>
110
+ </div>
111
+ <p class="text-[11px] text-base-content/60 leading-relaxed">
112
+ Analyzes schema graph foreign keys and seeds related parent & child entities in topological order to guarantee full relational integrity.
113
+ </p>
114
+ </div>
115
+ </div>
116
+ </label>
117
+ </div>
118
+ <div class="p-3.5 border-t border-base-200 bg-base-200/20">
119
+ <button id="btn-launch-seed" type="button" class="btn btn-primary btn-sm w-full gap-2 font-bold shadow-sm">
120
+ {{{icon "seed" class="h-4 w-4"}}}
121
+ <span id="launch-btn-label">Open Seed Generator</span>
122
+ {{{icon "arrowRight" class="h-3.5 w-3.5"}}}
123
+ </button>
124
+ </div>
125
+ </div>
126
+ <div class="p-3.5 rounded-xl bg-base-200/50 border border-base-300 text-xs space-y-1 text-base-content/70">
127
+ <div class="font-semibold text-base-content flex items-center gap-1.5 text-[11px]">
128
+ {{{icon "info" class="h-3.5 w-3.5 text-primary"}}}
129
+ Deterministic Generation
130
+ </div>
131
+ <p class="text-[11px] leading-relaxed text-base-content/60">
132
+ You can specify an exact numeric seed for deterministic reproducible data, or import/export seed profiles.
133
+ </p>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ {{else}}
138
+ <div class="empty-state">
139
+ <span class="empty-icon">{{{icon "table" class="h-7 w-7"}}}</span>
140
+ <p class="text-sm font-medium text-base-content/70">No tables available in the database</p>
141
+ <p class="text-xs text-base-content/50 mt-1 max-w-sm">Create a table using the visual designer or run SQL migrations before generating seed data.</p>
142
+ <div class="mt-4 flex gap-2">
143
+ <a href="{{basePath}}/designer" class="btn btn-primary btn-sm gap-1.5">
144
+ {{{icon "plus" class="h-4 w-4"}}}
145
+ Create table
146
+ </a>
147
+ <a href="{{basePath}}/query" class="btn btn-outline btn-sm gap-1.5">
148
+ {{{icon "query" class="h-4 w-4"}}}
149
+ Query editor
150
+ </a>
151
+ </div>
152
+ </div>
153
+ {{/if}}
154
+ </div>
155
+ <script>
156
+ document.addEventListener('DOMContentLoaded', () => {
157
+ const BASE = '{{basePath}}';
158
+ let selectedTable = '{{defaultTable}}';
159
+ let selectedMode = '{{defaultMode}}' || 'single';
160
+ const tableCards = document.querySelectorAll('.table-option-card');
161
+ const modeCards = document.querySelectorAll('.mode-option-card');
162
+ const launchBtn = document.getElementById('btn-launch-seed');
163
+ const launchLabel = document.getElementById('launch-btn-label');
164
+ const searchInput = document.getElementById('table-search-input');
165
+ function updateLaunchLabel() {
166
+ if (launchLabel) {
167
+ launchLabel.textContent = selectedTable
168
+ ? `Seed "${selectedTable}" (${selectedMode === 'chain' ? 'ER Chain' : 'Single Table'})`
169
+ : 'Open Seed Generator';
170
+ }
171
+ }
172
+ function setSelectedTable(tableName) {
173
+ selectedTable = tableName;
174
+ tableCards.forEach(card => {
175
+ const isMatch = card.dataset.table === tableName;
176
+ const radio = card.querySelector('input[type="radio"]');
177
+ if (radio) radio.checked = isMatch;
178
+ if (isMatch) {
179
+ card.classList.add('border-primary', 'bg-primary/[0.04]', 'shadow-sm');
180
+ card.classList.remove('border-base-200', 'bg-base-100');
181
+ } else {
182
+ card.classList.remove('border-primary', 'bg-primary/[0.04]', 'shadow-sm');
183
+ card.classList.add('border-base-200', 'bg-base-100');
184
+ }
185
+ });
186
+ updateLaunchLabel();
187
+ }
188
+ function setSelectedMode(mode) {
189
+ selectedMode = mode;
190
+ modeCards.forEach(card => {
191
+ const isMatch = card.dataset.mode === mode;
192
+ const radio = card.querySelector('input[type="radio"]');
193
+ if (radio) radio.checked = isMatch;
194
+ if (isMatch) {
195
+ card.classList.add('border-primary', 'bg-primary/[0.04]', 'shadow-sm');
196
+ card.classList.remove('border-base-200', 'bg-base-100');
197
+ } else {
198
+ card.classList.remove('border-primary', 'bg-primary/[0.04]', 'shadow-sm');
199
+ card.classList.add('border-base-200', 'bg-base-100');
200
+ }
201
+ });
202
+ updateLaunchLabel();
203
+ }
204
+ tableCards.forEach(card => {
205
+ card.addEventListener('click', (e) => {
206
+ if (e.target.closest('.quick-seed-btn')) return;
207
+ const table = card.dataset.table;
208
+ if (table) setSelectedTable(table);
209
+ });
210
+ });
211
+ modeCards.forEach(card => {
212
+ card.addEventListener('click', () => {
213
+ const mode = card.dataset.mode;
214
+ if (mode) setSelectedMode(mode);
215
+ });
216
+ });
217
+ // Direct quick-seed buttons
218
+ document.querySelectorAll('.quick-seed-btn').forEach(btn => {
219
+ btn.addEventListener('click', (e) => {
220
+ e.stopPropagation();
221
+ const table = btn.dataset.table;
222
+ const mode = btn.dataset.mode || 'single';
223
+ if (table) {
224
+ window.location.href = `${BASE}/seed/${encodeURIComponent(table)}?mode=${encodeURIComponent(mode)}`;
225
+ }
226
+ });
227
+ });
228
+ // Launch button
229
+ if (launchBtn) {
230
+ launchBtn.addEventListener('click', () => {
231
+ if (!selectedTable) return;
232
+ window.location.href = `${BASE}/seed/${encodeURIComponent(selectedTable)}?mode=${encodeURIComponent(selectedMode)}`;
233
+ });
234
+ }
235
+ // Real-time table search filter
236
+ if (searchInput) {
237
+ searchInput.addEventListener('input', () => {
238
+ const q = searchInput.value.trim().toLowerCase();
239
+ tableCards.forEach(card => {
240
+ const name = (card.dataset.table || '').toLowerCase();
241
+ if (!q || name.includes(q)) {
242
+ card.classList.remove('hidden');
243
+ } else {
244
+ card.classList.add('hidden');
245
+ }
246
+ });
247
+ });
248
+ }
249
+ updateLaunchLabel();
250
+ });
251
+ </script>