admindb 2.1.1 → 2.2.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 (91) hide show
  1. package/README.md +41 -12
  2. package/dist/app.js +230 -1
  3. package/dist/auth/config.js +121 -1
  4. package/dist/auth/crypto.js +108 -1
  5. package/dist/auth/index.js +21 -1
  6. package/dist/auth/middleware.js +85 -1
  7. package/dist/auth/routes.js +70 -1
  8. package/dist/auth/types.js +7 -1
  9. package/dist/cli/args.js +320 -1
  10. package/dist/cli/config.js +128 -1
  11. package/dist/cli/index.js +20 -1
  12. package/dist/cli/runner.js +211 -1
  13. package/dist/cli.js +4 -1
  14. package/dist/data/chain.d.ts +1 -0
  15. package/dist/data/chain.js +707 -0
  16. package/dist/data/datasets.js +129 -1
  17. package/dist/data/detector.d.ts +1 -1
  18. package/dist/data/detector.js +511 -1
  19. package/dist/data/engine.d.ts +1 -1
  20. package/dist/data/engine.js +245 -1
  21. package/dist/data/index.d.ts +1 -1
  22. package/dist/data/index.js +22 -1
  23. package/dist/data/strategies.d.ts +1 -1
  24. package/dist/data/strategies.js +339 -1
  25. package/dist/data/types.d.ts +1 -1
  26. package/dist/data/types.js +5 -1
  27. package/dist/db/database.d.ts +1 -1
  28. package/dist/db/database.js +477 -1
  29. package/dist/db/export.d.ts +1 -1
  30. package/dist/db/export.js +90 -1
  31. package/dist/db/filters.js +142 -1
  32. package/dist/db/index.js +24 -1
  33. package/dist/db/introspection.js +167 -1
  34. package/dist/db/manager.js +351 -1
  35. package/dist/db/migrations.js +107 -1
  36. package/dist/db/postgres.d.ts +1 -1
  37. package/dist/db/postgres.js +735 -1
  38. package/dist/db/types.d.ts +1 -1
  39. package/dist/db/types.js +6 -1
  40. package/dist/index.js +52 -1
  41. package/dist/public/css/app.css +1 -1
  42. package/dist/public/js/api.js +1 -1
  43. package/dist/public/js/browse.js +1 -1
  44. package/dist/public/js/common.js +1 -0
  45. package/dist/public/js/databases.js +1 -1
  46. package/dist/public/js/designer.js +1 -1
  47. package/dist/public/js/forms.js +1 -1
  48. package/dist/public/js/home.js +1 -0
  49. package/dist/public/js/inspector.js +1 -1
  50. package/dist/public/js/query.js +1 -1
  51. package/dist/public/js/schema.js +1 -1
  52. package/dist/public/js/seed.js +1 -1
  53. package/dist/routes/api/erd.d.ts +1 -0
  54. package/dist/routes/api/erd.js +50 -0
  55. package/dist/routes/api/helpers.d.ts +1 -1
  56. package/dist/routes/api/helpers.js +163 -1
  57. package/dist/routes/api/import-export.js +83 -1
  58. package/dist/routes/api/index.js +48 -1
  59. package/dist/routes/api/query.js +78 -1
  60. package/dist/routes/api/rows.js +362 -1
  61. package/dist/routes/api/seed.js +153 -1
  62. package/dist/routes/api/tables.js +231 -1
  63. package/dist/routes/databases.js +228 -1
  64. package/dist/routes/index.js +19 -1
  65. package/dist/routes/pages.js +397 -1
  66. package/dist/serverless.js +174 -1
  67. package/dist/sql/classifier.js +24 -1
  68. package/dist/sql/error-analyzer.d.ts +1 -0
  69. package/dist/sql/error-analyzer.js +550 -0
  70. package/dist/sql/generator.js +319 -1
  71. package/dist/sql/index.js +18 -1
  72. package/dist/types/api.js +2 -1
  73. package/dist/utils/colors.js +54 -1
  74. package/dist/utils/common.d.ts +1 -1
  75. package/dist/utils/common.js +225 -1
  76. package/dist/utils/csv.js +67 -1
  77. package/dist/utils/datatype.js +181 -1
  78. package/dist/utils/icons.js +81 -1
  79. package/dist/utils/index.js +20 -1
  80. package/dist/utils/logger.js +36 -1
  81. package/dist/views/layouts/main.hbs +14 -1
  82. package/dist/views/pages/erd.hbs +1241 -0
  83. package/dist/views/pages/home.hbs +98 -2
  84. package/dist/views/pages/info.hbs +107 -0
  85. package/dist/views/pages/query.hbs +54 -12
  86. package/dist/views/pages/seed.hbs +435 -171
  87. package/dist/views/partials/sidebar.hbs +12 -0
  88. package/docs/API.md +6 -1
  89. package/docs/EXAMPLES.md +3 -0
  90. package/package.json +5 -4
  91. package/dist/public/js/icons.js +0 -1
@@ -69,11 +69,96 @@
69
69
  <span class="text-sm text-base-content/45">{{tables.length}} total</span>
70
70
  </div>
71
71
  {{#if tables.length}}
72
+ {{#unless readonly}}
73
+ <div id="home-bulk-toolbar"
74
+ style="max-height: 0; overflow: hidden; transition: max-height 0.22s cubic-bezier(0.4,0,0.2,1), opacity 0.18s ease; opacity: 0;"
75
+ aria-hidden="true">
76
+ <div class="mb-3 flex flex-wrap items-center gap-3 rounded-xl border border-base-300 bg-base-100 px-4 py-3 shadow-soft">
77
+ <span id="home-bulk-count"
78
+ class="inline-flex items-center gap-1.5 rounded-full bg-primary/10 px-3 py-1 text-xs font-bold text-primary">
79
+ <span id="home-bulk-count-num">0</span> selected
80
+ </span>
81
+ <div class="h-4 w-px bg-base-300"></div>
82
+ <div class="dropdown dropdown-bottom" id="home-dd-clear">
83
+ <button tabindex="0" id="home-btn-clear"
84
+ class="btn btn-sm btn-warning gap-1.5 font-semibold">
85
+ {{{icon "refresh" class="h-3.5 w-3.5"}}}
86
+ Clear Rows
87
+ {{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
88
+ </button>
89
+ <ul tabindex="0"
90
+ class="dropdown-content menu bg-base-100 rounded-xl border border-base-300 shadow-lift z-30 mt-1 w-64 p-2 text-sm">
91
+ <li>
92
+ <button id="home-clear-normal" class="flex items-start gap-2.5 rounded-lg px-3 py-2.5 hover:bg-base-200 text-left w-full">
93
+ <span class="mt-0.5 text-warning shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
94
+ <span>
95
+ <span class="block font-semibold">Clear rows</span>
96
+ <span class="block text-xs text-base-content/50">Deletes all rows; fails if FK references exist</span>
97
+ </span>
98
+ </button>
99
+ </li>
100
+ <li>
101
+ <button id="home-clear-force" class="flex items-start gap-2.5 rounded-lg px-3 py-2.5 hover:bg-error/10 text-left w-full text-error">
102
+ <span class="mt-0.5 shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
103
+ <span>
104
+ <span class="block font-semibold">Force Clear <span class="text-[10px] font-bold uppercase tracking-wide rounded bg-error/15 px-1 py-0.5 ml-1">ignore FK</span></span>
105
+ <span class="block text-xs text-error/60">Disables FK checks; deletes regardless of references</span>
106
+ </span>
107
+ </button>
108
+ </li>
109
+ </ul>
110
+ </div>
111
+ <div class="dropdown dropdown-bottom" id="home-dd-drop">
112
+ <button tabindex="0" id="home-btn-drop"
113
+ class="btn btn-sm btn-error gap-1.5 font-semibold text-white">
114
+ {{{icon "warning" class="h-3.5 w-3.5"}}}
115
+ Drop Tables
116
+ {{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
117
+ </button>
118
+ <ul tabindex="0"
119
+ class="dropdown-content menu bg-base-100 rounded-xl border border-base-300 shadow-lift z-30 mt-1 w-64 p-2 text-sm">
120
+ <li>
121
+ <button id="home-drop-normal" class="flex items-start gap-2.5 rounded-lg px-3 py-2.5 hover:bg-base-200 text-left w-full">
122
+ <span class="mt-0.5 text-error shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
123
+ <span>
124
+ <span class="block font-semibold">Drop tables</span>
125
+ <span class="block text-xs text-base-content/50">Permanently deletes tables and all data</span>
126
+ </span>
127
+ </button>
128
+ </li>
129
+ <li>
130
+ <button id="home-drop-force" class="flex items-start gap-2.5 rounded-lg px-3 py-2.5 hover:bg-error/10 text-left w-full text-error">
131
+ <span class="mt-0.5 shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
132
+ <span>
133
+ <span class="block font-semibold">Force Drop <span class="text-[10px] font-bold uppercase tracking-wide rounded bg-error/15 px-1 py-0.5 ml-1">ignore FK</span></span>
134
+ <span class="block text-xs text-error/60">Drops with FK checks disabled; cascades on Postgres</span>
135
+ </span>
136
+ </button>
137
+ </li>
138
+ </ul>
139
+ </div>
140
+ <div class="ml-auto">
141
+ <button id="home-bulk-deselect"
142
+ class="btn btn-ghost btn-sm gap-1 text-base-content/50 hover:text-base-content">
143
+ {{{icon "x" class="h-3.5 w-3.5"}}}
144
+ Deselect all
145
+ </button>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ {{/unless}}
72
150
  <div class="app-card overflow-hidden">
73
151
  <div class="overflow-x-auto">
74
- <table class="table table-sm">
152
+ <table class="table table-sm" id="home-tables-table">
75
153
  <thead>
76
154
  <tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
155
+ {{#unless readonly}}
156
+ <th class="w-10">
157
+ <input type="checkbox" id="home-select-all"
158
+ class="checkbox checkbox-sm checkbox-primary"
159
+ title="Select all tables" />
160
+ </th>
161
+ {{/unless}}
77
162
  <th class="font-semibold">Table</th>
78
163
  <th class="text-right font-semibold">Columns</th>
79
164
  <th class="text-right font-semibold">Rows</th>
@@ -82,7 +167,15 @@
82
167
  </thead>
83
168
  <tbody>
84
169
  {{#each tables}}
85
- <tr class="group hover:bg-base-200/50">
170
+ <tr class="group hover:bg-base-200/50 home-table-row" data-table="{{this}}">
171
+ {{#unless ../readonly}}
172
+ <td class="w-10">
173
+ <input type="checkbox"
174
+ class="checkbox checkbox-sm checkbox-primary home-table-checkbox"
175
+ data-table="{{this}}"
176
+ title="Select {{this}}" />
177
+ </td>
178
+ {{/unless}}
86
179
  <td>
87
180
  <a href="{{../basePath}}/tables/{{this}}" class="inline-flex items-center gap-2.5 font-medium">
88
181
  <span class="grid h-8 w-8 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
@@ -122,3 +215,6 @@
122
215
  {{/if}}
123
216
  </div>
124
217
  </div>
218
+ {{#unless readonly}}
219
+ <script src="{{basePath}}/js/home.js" defer></script>
220
+ {{/unless}}
@@ -0,0 +1,107 @@
1
+ <div class="space-y-6">
2
+ <div class="flex flex-wrap items-center justify-between gap-3">
3
+ <div>
4
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary">{{dialect}} Database</p>
5
+ <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Info & Settings</h1>
6
+ <p class="mt-1.5 text-sm text-base-content/55">Database configuration, settings, and schema DDL overview.</p>
7
+ </div>
8
+ </div>
9
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
10
+ <div class="lg:col-span-1 space-y-6">
11
+ <div class="app-card overflow-hidden">
12
+ <div class="border-b border-base-200 bg-base-200/40 px-4 py-3">
13
+ <h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Settings / Configuration</h2>
14
+ </div>
15
+ <div class="p-0">
16
+ <table class="table table-sm w-full">
17
+ <tbody>
18
+ {{#each settings}}
19
+ <tr class="hover:bg-base-200/20">
20
+ <td class="font-medium text-base-content/70 w-1/2">{{@key}}</td>
21
+ <td class="font-mono text-xs">{{this}}</td>
22
+ </tr>
23
+ {{else}}
24
+ <tr>
25
+ <td colspan="2" class="p-4 text-center text-sm text-base-content/40">No settings available</td>
26
+ </tr>
27
+ {{/each}}
28
+ </tbody>
29
+ </table>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <div class="lg:col-span-2 space-y-6">
34
+ <div class="app-card overflow-hidden flex flex-col h-[75vh]">
35
+ <div class="border-b border-base-200 bg-base-200/40 px-4 py-3 flex items-center justify-between">
36
+ <div class="flex items-center gap-3">
37
+ <h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Schema DDL</h2>
38
+ <span class="badge badge-sm badge-ghost font-mono text-[10px] uppercase font-bold">{{dialect}}</span>
39
+ </div>
40
+ <button id="btn-copy-ddl" class="btn btn-sm btn-ghost gap-1.5" disabled>
41
+ {{{icon "copy" class="h-4 w-4"}}}
42
+ Copy
43
+ </button>
44
+ </div>
45
+ <div class="bg-base-300 p-4 overflow-y-auto flex-1 relative">
46
+ <div id="ddl-loader" class="absolute inset-0 flex flex-col items-center justify-center text-base-content/50 gap-3">
47
+ {{{icon "spinner" class="h-6 w-6 animate-spin text-primary"}}}
48
+ <p class="text-sm font-medium">Extracting schema definitions...</p>
49
+ </div>
50
+ <div id="ddl-error" class="hidden absolute inset-0 flex flex-col items-center justify-center text-error gap-3 bg-base-300">
51
+ {{{icon "error" class="h-8 w-8"}}}
52
+ <p class="text-sm font-medium">Failed to load schema.</p>
53
+ </div>
54
+ <pre id="ddl-container" class="hidden m-0 h-full"><code class="language-sql text-sm text-base-content/80 whitespace-pre-wrap"></code></pre>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ <script>
61
+ document.addEventListener('DOMContentLoaded', async () => {
62
+ const loader = document.getElementById('ddl-loader');
63
+ const container = document.getElementById('ddl-container');
64
+ const codeBlock = container.querySelector('code');
65
+ const btnCopy = document.getElementById('btn-copy-ddl');
66
+ const errorBox = document.getElementById('ddl-error');
67
+ try {
68
+ const res = await fetch('{{basePath}}/api/info/ddl');
69
+ const json = await res.json();
70
+ loader.classList.add('hidden');
71
+ if (json.success && json.data) {
72
+ if (window.Utils && window.Utils.highlightSql) {
73
+ codeBlock.innerHTML = window.Utils.highlightSql(json.data);
74
+ } else {
75
+ codeBlock.textContent = json.data;
76
+ }
77
+ container.classList.remove('hidden');
78
+ btnCopy.disabled = false;
79
+ btnCopy.addEventListener('click', async () => {
80
+ try {
81
+ await navigator.clipboard.writeText(json.data);
82
+ const originalText = btnCopy.innerHTML;
83
+ btnCopy.innerHTML = `{{{icon "check" class="h-4 w-4"}}} Copied!`;
84
+ btnCopy.classList.add('text-success');
85
+ setTimeout(() => {
86
+ btnCopy.innerHTML = originalText;
87
+ btnCopy.classList.remove('text-success');
88
+ }, 2000);
89
+ } catch (err) {
90
+ console.error('Failed to copy', err);
91
+ }
92
+ });
93
+ } else {
94
+ if (json.success && !json.data) {
95
+ codeBlock.textContent = '-- No tables defined in the database.';
96
+ container.classList.remove('hidden');
97
+ } else {
98
+ throw new Error(json.error || 'Failed to fetch DDL');
99
+ }
100
+ }
101
+ } catch (err) {
102
+ loader.classList.add('hidden');
103
+ errorBox.classList.remove('hidden');
104
+ errorBox.querySelector('p').textContent = err.message || 'Failed to load schema.';
105
+ }
106
+ });
107
+ </script>
@@ -40,22 +40,64 @@
40
40
  {{/unless}}
41
41
  </div>
42
42
  <div class="app-card overflow-hidden">
43
- <div class="flex items-center justify-between border-b border-base-200 bg-base-200/40 px-4 py-2.5">
44
- <span class="flex items-center gap-2 text-sm font-semibold text-base-content/60">
45
- <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
46
- {{{icon "query" class="h-3.5 w-3.5"}}}
43
+ <div class="flex flex-wrap items-center justify-between gap-2 border-b border-base-200 bg-base-200/40 px-4 py-2">
44
+ <div class="flex items-center gap-2">
45
+ <span class="flex items-center gap-1.5 text-xs font-semibold text-base-content/70">
46
+ <span class="grid h-5 w-5 place-items-center rounded bg-primary/10 text-primary">
47
+ {{{icon "query" class="h-3.5 w-3.5"}}}
48
+ </span>
49
+ query.sql
47
50
  </span>
48
- query.sql
49
- </span>
50
- <span class="text-[11px] text-base-content/40">Ctrl/⌘ + Enter to run</span>
51
+ <span class="badge badge-sm badge-ghost font-mono text-[10px] uppercase font-bold">{{#if isPostgres}}Postgres{{else}}SQLite{{/if}}</span>
52
+ </div>
53
+ <div class="flex flex-wrap items-center gap-1.5">
54
+ <div class="dropdown dropdown-end">
55
+ <label tabindex="0" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
56
+ {{{icon "terminal" class="h-3.5 w-3.5"}}}
57
+ Snippets
58
+ </label>
59
+ <ul tabindex="0" class="dropdown-content z-30 menu p-1.5 shadow-2xl bg-base-100 rounded-xl w-56 border border-base-300 text-xs">
60
+ <li class="menu-title text-[10px] uppercase tracking-wider text-base-content/40">Query Templates</li>
61
+ <li><a class="js-snippet" data-snippet="SELECT * FROM table_name\nWHERE condition\nORDER BY id DESC\nLIMIT 50;">SELECT rows</a></li>
62
+ <li><a class="js-snippet" data-snippet="SELECT COUNT(*) AS total\nFROM table_name;">COUNT summary</a></li>
63
+ <li><a class="js-snippet" data-snippet="SELECT a.*, b.*\nFROM table_a a\nJOIN table_b b ON b.a_id = a.id\nLIMIT 50;">JOIN tables</a></li>
64
+ <li><a class="js-snippet" data-snippet="INSERT INTO table_name (col1, col2)\nVALUES ('value1', 'value2');">INSERT row</a></li>
65
+ <li><a class="js-snippet" data-snippet="UPDATE table_name\nSET col1 = 'value1'\nWHERE id = 1;">UPDATE row</a></li>
66
+ <li><a class="js-snippet" data-snippet="DELETE FROM table_name\nWHERE id = 1;">DELETE row</a></li>
67
+ <li><a class="js-snippet" data-snippet="CREATE TABLE new_table (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL,\n created_at TEXT DEFAULT (datetime('now'))\n);">CREATE TABLE</a></li>
68
+ </ul>
69
+ </div>
70
+ <button id="format-query" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" title="Format SQL (Beautify)">
71
+ {{{icon "format" class="h-3.5 w-3.5"}}}
72
+ Format
73
+ </button>
74
+ <button id="copy-query" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary" title="Copy SQL to clipboard">
75
+ {{{icon "copy" class="h-3.5 w-3.5"}}}
76
+ Copy
77
+ </button>
78
+ <button id="clear-query" type="button" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-error" title="Clear editor">
79
+ {{{icon "trash" class="h-3.5 w-3.5"}}}
80
+ Clear
81
+ </button>
82
+ <span class="hidden sm:inline-block text-[11px] text-base-content/35 border-l border-base-300 pl-2">Ctrl/⌘ + Enter to run</span>
83
+ </div>
51
84
  </div>
52
- <div>
53
- <div class="sql-editor-wrap">
54
- <pre id="query-gutter" class="sql-gutter" aria-hidden="true">1</pre>
55
- <textarea id="query-sql" class="sql-input" rows="10" placeholder="SELECT * FROM users WHERE …" spellcheck="false"></textarea>
85
+ <div class="sql-editor-wrap">
86
+ <div id="query-gutter" class="sql-gutter" aria-hidden="true">
87
+ <div class="sql-gutter-line">1</div>
88
+ </div>
89
+ <div id="query-sql" class="sql-code-editor" contenteditable="plaintext-only" spellcheck="false" data-placeholder="-- Write SQL here or choose a snippet/saved query&#10;SELECT * FROM table_name WHERE …"></div>
90
+ </div>
91
+ <div class="flex items-center justify-between border-t border-base-200 bg-base-200/30 px-3.5 py-1.5 text-[11px] font-mono text-base-content/50">
92
+ <div class="flex items-center gap-3">
93
+ <span id="editor-cursor-pos">Ln 1, Col 1</span>
94
+ <span id="editor-stats">0 chars</span>
95
+ </div>
96
+ <div class="flex items-center gap-2">
97
+ <span class="text-[10px] text-base-content/40">Tab to indent · Ctrl+Z / Ctrl+Y to undo/redo · Ctrl+/ to comment</span>
56
98
  </div>
57
- <div id="query-message"></div>
58
99
  </div>
100
+ <div id="query-message" class="p-3"></div>
59
101
  </div>
60
102
  <div id="query-result" class="hidden">
61
103
  <div class="app-card overflow-hidden">