admindb 2.2.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.
- package/README.md +368 -364
- package/dist/app.js +6 -9
- package/dist/auth/config.d.ts +1 -1
- package/dist/auth/config.js +18 -30
- package/dist/auth/crypto.js +11 -21
- package/dist/auth/middleware.js +9 -16
- package/dist/auth/routes.js +9 -15
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +15 -26
- package/dist/cli/config.js +6 -16
- package/dist/cli/runner.js +4 -7
- package/dist/data/chain.d.ts +1 -1
- package/dist/data/chain.js +40 -617
- package/dist/data/datasets.d.ts +1 -1
- package/dist/data/datasets.js +43 -1
- package/dist/data/detector.js +45 -21
- package/dist/data/engine.d.ts +1 -1
- package/dist/data/engine.js +483 -142
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +8 -0
- package/dist/data/prng.d.ts +1 -0
- package/dist/data/prng.js +73 -0
- package/dist/data/registry.d.ts +1 -0
- package/dist/data/registry.js +805 -0
- package/dist/data/schema-graph.d.ts +1 -0
- package/dist/data/schema-graph.js +210 -0
- package/dist/data/strategies.d.ts +1 -1
- package/dist/data/strategies.js +44 -283
- package/dist/data/templates.d.ts +1 -0
- package/dist/data/templates.js +134 -0
- package/dist/data/types.d.ts +1 -1
- package/dist/data/validator.d.ts +1 -0
- package/dist/data/validator.js +160 -0
- package/dist/db/database.js +9 -14
- package/dist/db/export.js +32 -55
- package/dist/db/filters.d.ts +1 -1
- package/dist/db/filters.js +15 -38
- package/dist/db/introspection.js +4 -7
- package/dist/db/manager.js +27 -51
- package/dist/db/migrations.js +7 -14
- package/dist/db/postgres.js +30 -78
- package/dist/index.d.ts +1 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/inspector.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/public/js/seed.js +1 -1
- package/dist/routes/api/erd.js +3 -8
- package/dist/routes/api/helpers.d.ts +1 -1
- package/dist/routes/api/helpers.js +75 -25
- package/dist/routes/api/import-export.js +1 -2
- package/dist/routes/api/query.js +2 -6
- package/dist/routes/api/rows.js +4 -8
- package/dist/routes/api/seed.js +35 -21
- package/dist/routes/api/tables.js +15 -30
- package/dist/routes/databases.js +8 -26
- package/dist/routes/pages.js +67 -18
- package/dist/serverless.js +15 -40
- package/dist/sql/generator.d.ts +1 -1
- package/dist/sql/generator.js +35 -109
- package/dist/types/api.d.ts +1 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +45 -85
- package/dist/utils/csv.d.ts +1 -1
- package/dist/utils/csv.js +11 -17
- package/dist/utils/datatype.js +46 -60
- package/dist/utils/icons.js +8 -8
- package/dist/views/layouts/main.hbs +1 -87
- package/dist/views/pages/databases.hbs +1 -233
- package/dist/views/pages/designer.hbs +1 -89
- package/dist/views/pages/erd.hbs +1 -1241
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/form.hbs +1 -59
- package/dist/views/pages/home.hbs +1 -220
- package/dist/views/pages/info.hbs +1 -107
- package/dist/views/pages/login.hbs +1 -98
- package/dist/views/pages/query.hbs +1 -129
- package/dist/views/pages/schema.hbs +1 -298
- package/dist/views/pages/seed-select.hbs +251 -0
- package/dist/views/pages/seed.hbs +256 -414
- package/dist/views/pages/table.hbs +1 -327
- package/dist/views/partials/navbar.hbs +1 -83
- package/dist/views/partials/sidebar.hbs +1 -129
- package/docs/API.md +149 -149
- package/docs/EXAMPLES.md +579 -579
- package/docs/SECURITY.md +265 -265
- package/package.json +79 -79
|
@@ -1,10 +1 @@
|
|
|
1
|
-
<div class="mx-auto mt-16 max-w-md space-y-6 text-center">
|
|
2
|
-
<div class="mx-auto grid h-20 w-20 place-items-center rounded-3xl bg-error/10 text-error">
|
|
3
|
-
{{{icon "warning" class="h-10 w-10"}}}
|
|
4
|
-
</div>
|
|
5
|
-
<div>
|
|
6
|
-
<h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
|
|
7
|
-
<p class="mt-2 text-base-content/60">{{error}}</p>
|
|
8
|
-
</div>
|
|
9
|
-
<a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
|
|
10
|
-
</div>
|
|
1
|
+
<div class="mx-auto mt-16 max-w-md space-y-6 text-center">
|
|
11
2
|
<div class="mx-auto grid h-20 w-20 place-items-center rounded-3xl bg-error/10 text-error">
|
|
12
3
|
{{{icon "warning" class="h-10 w-10"}}}
|
|
13
4
|
</div>
|
|
14
5
|
<div>
|
|
15
6
|
<h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
|
|
16
7
|
<p class="mt-2 text-base-content/60">{{error}}</p>
|
|
17
8
|
</div>
|
|
18
9
|
<a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
|
|
@@ -1,59 +1 @@
|
|
|
1
|
-
<div class="mx-auto max-w-3xl space-y-5">
|
|
2
|
-
<div class="flex items-center gap-3">
|
|
3
|
-
<a href="{{basePath}}/tables/{{table}}" class="btn btn-circle btn-ghost btn-sm" aria-label="Back to table">
|
|
4
|
-
{{{icon "arrowLeft" class="h-5 w-5"}}}
|
|
5
|
-
</a>
|
|
6
|
-
<div>
|
|
7
|
-
<h1 class="text-2xl font-bold tracking-tight">
|
|
8
|
-
{{#if (eq mode 'edit')}}Edit row{{else}}New row{{/if}}
|
|
9
|
-
<span class="text-base-content/40">in</span> <span class="font-mono text-primary">{{table}}</span>
|
|
10
|
-
</h1>
|
|
11
|
-
<p class="text-sm text-base-content/55">{{infoSummary}}</p>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
<div class="app-card">
|
|
15
|
-
<div class="border-b border-base-200 px-6 py-4">
|
|
16
|
-
<h2 class="text-sm font-semibold uppercase tracking-wide text-base-content/45">Row fields</h2>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="p-6">
|
|
19
|
-
<div id="row-fields" class="grid grid-cols-1 gap-x-6 gap-y-5 md:grid-cols-2"></div>
|
|
20
|
-
<div id="form-error" class="hidden"></div>
|
|
21
|
-
<div class="mt-6 flex flex-wrap items-center gap-2 border-t border-base-200 pt-5">
|
|
22
|
-
{{#unless readonly}}
|
|
23
|
-
<button id="row-submit" type="button" class="btn btn-primary">
|
|
24
|
-
{{#if (eq mode 'edit')}}Update row{{else}}Insert row{{/if}}
|
|
25
|
-
</button>
|
|
26
|
-
<button id="row-generate" type="button" class="btn btn-outline gap-1.5">
|
|
27
|
-
{{{icon "sql" class="h-4 w-4"}}}
|
|
28
|
-
Get query
|
|
29
|
-
</button>
|
|
30
|
-
{{else}}
|
|
31
|
-
<span class="text-sm font-medium text-warning">This database is read-only — rows cannot be {{#if (eq mode 'edit')}}updated{{else}}inserted{{/if}}.</span>
|
|
32
|
-
{{/unless}}
|
|
33
|
-
<a href="{{basePath}}/tables/{{table}}" class="btn btn-ghost">Cancel</a>
|
|
34
|
-
</div>
|
|
35
|
-
<p class="mt-3 text-xs text-base-content/40">
|
|
36
|
-
Columns with defaults are pre-filled from the schema. Empty fields are treated as "not set" (DB defaults
|
|
37
|
-
apply). <code class="font-mono">0</code> is a valid value. "Get query" only previews the SQL — it never executes.
|
|
38
|
-
</p>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
<div id="generated-sql" class="hidden">
|
|
42
|
-
<div class="app-card">
|
|
43
|
-
<div class="flex items-center justify-between border-b border-base-200 px-6 py-4">
|
|
44
|
-
<h2 class="flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-base-content/45">
|
|
45
|
-
<span class="grid h-6 w-6 place-items-center rounded-md bg-primary/10 text-primary">
|
|
46
|
-
{{{icon "sql" class="h-4 w-4"}}}
|
|
47
|
-
</span>
|
|
48
|
-
Generated SQL
|
|
49
|
-
</h2>
|
|
50
|
-
<button id="copy-sql" type="button" class="btn btn-ghost btn-xs gap-1">Copy</button>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="p-4">
|
|
53
|
-
<pre class="code-panel"><code id="generated-sql-code"></code></pre>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
<script id="form-config" type="application/json">{{{json config}}}</script>
|
|
59
|
-
<script src="{{basePath}}/js/forms.js" defer></script>
|
|
1
|
+
<div class="mx-auto max-w-3xl space-y-5">
|
|
60
2
|
<div class="page-header">
|
|
61
3
|
<div class="page-header-row">
|
|
62
4
|
<div class="flex items-center gap-3">
|
|
63
5
|
<a href="{{basePath}}/tables/{{table}}" class="btn btn-circle btn-ghost btn-sm" aria-label="Back to table">
|
|
64
6
|
{{{icon "arrowLeft" class="h-4 w-4"}}}
|
|
65
7
|
</a>
|
|
66
8
|
<div>
|
|
67
9
|
<div class="page-pretitle">{{#if (eq mode 'edit')}}Record Editor{{else}}Record Inserter{{/if}}</div>
|
|
68
10
|
<h1 class="page-title text-xl sm:text-2xl">
|
|
69
11
|
{{#if (eq mode 'edit')}}Edit row{{else}}New row{{/if}}
|
|
70
12
|
<span class="text-base-content/40 font-normal">in</span> <span class="font-mono text-primary">{{table}}</span>
|
|
71
13
|
</h1>
|
|
72
14
|
<p class="text-xs text-base-content/55 mt-0.5">{{infoSummary}}</p>
|
|
73
15
|
</div>
|
|
74
16
|
</div>
|
|
75
17
|
</div>
|
|
76
18
|
</div>
|
|
77
19
|
<div class="app-card">
|
|
78
20
|
<div class="border-b border-base-200 px-6 py-4">
|
|
79
21
|
<h2 class="text-sm font-semibold uppercase tracking-wide text-base-content/45">Row fields</h2>
|
|
80
22
|
</div>
|
|
81
23
|
<div class="p-6">
|
|
82
24
|
<div id="row-fields" class="grid grid-cols-1 gap-x-6 gap-y-5 md:grid-cols-2"></div>
|
|
83
25
|
<div id="form-error" class="hidden"></div>
|
|
84
26
|
<div class="mt-6 flex flex-wrap items-center gap-2 border-t border-base-200 pt-5">
|
|
85
27
|
{{#unless readonly}}
|
|
86
28
|
<button id="row-submit" type="button" class="btn btn-primary">
|
|
87
29
|
{{#if (eq mode 'edit')}}Update row{{else}}Insert row{{/if}}
|
|
88
30
|
</button>
|
|
89
31
|
<button id="row-generate" type="button" class="btn btn-outline gap-1.5">
|
|
90
32
|
{{{icon "sql" class="h-4 w-4"}}}
|
|
91
33
|
Get query
|
|
92
34
|
</button>
|
|
93
35
|
{{else}}
|
|
94
36
|
<span class="text-sm font-medium text-warning">This database is read-only — rows cannot be {{#if (eq mode 'edit')}}updated{{else}}inserted{{/if}}.</span>
|
|
95
37
|
{{/unless}}
|
|
96
38
|
<a href="{{basePath}}/tables/{{table}}" class="btn btn-ghost">Cancel</a>
|
|
97
39
|
</div>
|
|
98
40
|
<p class="mt-3 text-xs text-base-content/40">
|
|
99
41
|
Columns with defaults are pre-filled from the schema. Empty fields are treated as "not set" (DB defaults
|
|
100
42
|
apply). <code class="font-mono">0</code> is a valid value. "Get query" only previews the SQL — it never executes.
|
|
101
43
|
</p>
|
|
102
44
|
</div>
|
|
103
45
|
</div>
|
|
104
46
|
<div id="generated-sql" class="hidden">
|
|
105
47
|
<div class="app-card">
|
|
106
48
|
<div class="flex items-center justify-between border-b border-base-200 px-6 py-4">
|
|
107
49
|
<h2 class="flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-base-content/45">
|
|
108
50
|
<span class="grid h-6 w-6 place-items-center rounded-md bg-primary/10 text-primary">
|
|
109
51
|
{{{icon "sql" class="h-4 w-4"}}}
|
|
110
52
|
</span>
|
|
111
53
|
Generated SQL
|
|
112
54
|
</h2>
|
|
113
55
|
<button id="copy-sql" type="button" class="btn btn-ghost btn-xs gap-1">Copy</button>
|
|
114
56
|
</div>
|
|
115
57
|
<div class="p-4">
|
|
116
58
|
<pre class="code-panel"><code id="generated-sql-code"></code></pre>
|
|
117
59
|
</div>
|
|
118
60
|
</div>
|
|
119
61
|
</div>
|
|
@@ -1,220 +1 @@
|
|
|
1
|
-
<div class="space-y-8">
|
|
2
|
-
<div class="flex flex-wrap items-end justify-between gap-4">
|
|
3
|
-
<div>
|
|
4
|
-
<p class="text-sm font-semibold uppercase tracking-wider text-primary">Overview</p>
|
|
5
|
-
<h1 class="mt-1 text-3xl font-extrabold tracking-tight">Database</h1>
|
|
6
|
-
<p class="mt-1.5 text-sm text-base-content/55">Browse, edit, and query the connected database from your browser.</p>
|
|
7
|
-
</div>
|
|
8
|
-
<div class="flex gap-2">
|
|
9
|
-
<a href="{{basePath}}/query" class="btn btn-ghost btn-sm gap-1.5">
|
|
10
|
-
{{{icon "query" class="h-4 w-4"}}}
|
|
11
|
-
Query
|
|
12
|
-
</a>
|
|
13
|
-
{{#unless readonly}}
|
|
14
|
-
<a href="{{basePath}}/designer" class="btn btn-primary btn-sm gap-1.5">
|
|
15
|
-
{{{icon "plus" class="h-4 w-4"}}}
|
|
16
|
-
New table
|
|
17
|
-
</a>
|
|
18
|
-
{{/unless}}
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
22
|
-
<div class="stat-card">
|
|
23
|
-
<span class="stat-icon bg-primary/10 text-primary">
|
|
24
|
-
{{{icon "table" class="h-6 w-6"}}}
|
|
25
|
-
</span>
|
|
26
|
-
<div>
|
|
27
|
-
<div class="text-2xl font-extrabold tabular-nums">{{tables.length}}</div>
|
|
28
|
-
<div class="text-[13px] text-base-content/50">Tables</div>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="stat-card">
|
|
32
|
-
<span class="stat-icon bg-secondary/10 text-secondary">
|
|
33
|
-
{{{icon "stats" class="h-6 w-6"}}}
|
|
34
|
-
</span>
|
|
35
|
-
<div>
|
|
36
|
-
<div class="text-2xl font-extrabold tabular-nums">{{totalRows}}</div>
|
|
37
|
-
<div class="text-[13px] text-base-content/50">Total rows</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
<div class="stat-card">
|
|
41
|
-
<span class="stat-icon bg-accent/10 text-accent">
|
|
42
|
-
{{{icon "seed" class="h-6 w-6"}}}
|
|
43
|
-
</span>
|
|
44
|
-
<div>
|
|
45
|
-
<div class="text-2xl font-extrabold tabular-nums">{{savedQueries}}</div>
|
|
46
|
-
<div class="text-[13px] text-base-content/50">Saved queries</div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
<div class="stat-card">
|
|
50
|
-
<span class="stat-icon {{#if isPostgres}}bg-info/10 text-info{{else}}bg-emerald-500/10 text-emerald-500{{/if}}">
|
|
51
|
-
{{{icon "database" class="h-6 w-6"}}}
|
|
52
|
-
</span>
|
|
53
|
-
<div>
|
|
54
|
-
<div class="flex items-center gap-1.5">
|
|
55
|
-
<span class="text-xl font-extrabold">{{dialectName}}</span>
|
|
56
|
-
{{#if readonly}}
|
|
57
|
-
<span class="rounded bg-warning/20 px-1.5 py-0.5 text-[10px] font-bold uppercase text-warning">Read-only</span>
|
|
58
|
-
{{else}}
|
|
59
|
-
<span class="rounded bg-success/20 px-1.5 py-0.5 text-[10px] font-bold uppercase text-success">Writable</span>
|
|
60
|
-
{{/if}}
|
|
61
|
-
</div>
|
|
62
|
-
<div class="truncate font-mono text-xs text-base-content/50" title="{{dbPath}}">{{dbPath}}</div>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
<div>
|
|
67
|
-
<div class="mb-3 flex items-center justify-between">
|
|
68
|
-
<h2 class="text-lg font-bold">Tables</h2>
|
|
69
|
-
<span class="text-sm text-base-content/45">{{tables.length}} total</span>
|
|
70
|
-
</div>
|
|
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}}
|
|
150
|
-
<div class="app-card overflow-hidden">
|
|
151
|
-
<div class="overflow-x-auto">
|
|
152
|
-
<table class="table table-sm" id="home-tables-table">
|
|
153
|
-
<thead>
|
|
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}}
|
|
162
|
-
<th class="font-semibold">Table</th>
|
|
163
|
-
<th class="text-right font-semibold">Columns</th>
|
|
164
|
-
<th class="text-right font-semibold">Rows</th>
|
|
165
|
-
<th class="text-right font-semibold">Actions</th>
|
|
166
|
-
</tr>
|
|
167
|
-
</thead>
|
|
168
|
-
<tbody>
|
|
169
|
-
{{#each tables}}
|
|
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}}
|
|
179
|
-
<td>
|
|
180
|
-
<a href="{{../basePath}}/tables/{{this}}" class="inline-flex items-center gap-2.5 font-medium">
|
|
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">
|
|
182
|
-
{{{icon "table" class="h-4 w-4"}}}
|
|
183
|
-
</span>
|
|
184
|
-
<span class="font-mono text-[13.5px]">{{this}}</span>
|
|
185
|
-
</a>
|
|
186
|
-
</td>
|
|
187
|
-
<td class="text-right tabular-nums text-base-content/60">{{lookup ../cols this}}</td>
|
|
188
|
-
<td class="text-right tabular-nums text-base-content/60">{{lookup ../counts this}}</td>
|
|
189
|
-
<td class="text-right">
|
|
190
|
-
<a href="{{../basePath}}/tables/{{this}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
|
|
191
|
-
Browse
|
|
192
|
-
{{{icon "arrowRight" class="h-3.5 w-3.5"}}}
|
|
193
|
-
</a>
|
|
194
|
-
</td>
|
|
195
|
-
</tr>
|
|
196
|
-
{{/each}}
|
|
197
|
-
</tbody>
|
|
198
|
-
</table>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
{{else}}
|
|
202
|
-
<div class="empty-state">
|
|
203
|
-
<span class="empty-icon">
|
|
204
|
-
{{{icon "table" class="h-7 w-7"}}}
|
|
205
|
-
</span>
|
|
206
|
-
<p class="text-sm font-medium text-base-content/70">No tables yet</p>
|
|
207
|
-
<p class="max-w-sm text-sm text-base-content/45">Create one with the table designer, or run a SQL statement in the query editor to get started.</p>
|
|
208
|
-
<div class="mt-2 flex gap-2">
|
|
209
|
-
{{#unless readonly}}
|
|
210
|
-
<a href="{{basePath}}/designer" class="btn btn-primary btn-sm">New table</a>
|
|
211
|
-
{{/unless}}
|
|
212
|
-
<a href="{{basePath}}/query" class="btn btn-outline btn-sm">Query editor</a>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
{{/if}}
|
|
216
|
-
</div>
|
|
217
|
-
</div>
|
|
218
|
-
{{#unless readonly}}
|
|
219
|
-
<script src="{{basePath}}/js/home.js" defer></script>
|
|
220
|
-
{{/unless}}
|
|
1
|
+
<div class="space-y-8">
|
|
221
2
|
<div class="page-header">
|
|
222
3
|
<div class="page-header-row">
|
|
223
4
|
<div>
|
|
224
5
|
<div class="page-pretitle">Overview</div>
|
|
225
6
|
<h1 class="page-title">Database</h1>
|
|
226
7
|
<p class="mt-0.5 text-xs text-base-content/60">Browse, edit, and query the connected database from your browser.</p>
|
|
227
8
|
</div>
|
|
228
9
|
<div class="page-actions">
|
|
229
10
|
<a href="{{basePath}}/query" class="btn btn-ghost btn-sm gap-1.5">
|
|
230
11
|
{{{icon "query" class="h-4 w-4"}}}
|
|
231
12
|
Query
|
|
232
13
|
</a>
|
|
233
14
|
{{#unless readonly}}
|
|
234
15
|
<a href="{{basePath}}/designer" class="btn btn-primary btn-sm gap-1.5">
|
|
235
16
|
{{{icon "plus" class="h-4 w-4"}}}
|
|
236
17
|
New table
|
|
237
18
|
</a>
|
|
238
19
|
{{/unless}}
|
|
239
20
|
</div>
|
|
240
21
|
</div>
|
|
241
22
|
</div>
|
|
242
23
|
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
243
24
|
<div class="stat-card">
|
|
244
25
|
<span class="stat-icon bg-primary/10 text-primary">
|
|
245
26
|
{{{icon "table" class="h-6 w-6"}}}
|
|
246
27
|
</span>
|
|
247
28
|
<div>
|
|
248
29
|
<div class="text-2xl font-extrabold tabular-nums">{{tables.length}}</div>
|
|
249
30
|
<div class="text-[13px] text-base-content/50">Tables</div>
|
|
250
31
|
</div>
|
|
251
32
|
</div>
|
|
252
33
|
<div class="stat-card">
|
|
253
34
|
<span class="stat-icon bg-secondary/10 text-secondary">
|
|
254
35
|
{{{icon "stats" class="h-6 w-6"}}}
|
|
255
36
|
</span>
|
|
256
37
|
<div>
|
|
257
38
|
<div class="text-2xl font-extrabold tabular-nums">{{totalRows}}</div>
|
|
258
39
|
<div class="text-[13px] text-base-content/50">Total rows</div>
|
|
259
40
|
</div>
|
|
260
41
|
</div>
|
|
261
42
|
<div class="stat-card">
|
|
262
43
|
<span class="stat-icon bg-accent/10 text-accent">
|
|
263
44
|
{{{icon "seed" class="h-6 w-6"}}}
|
|
264
45
|
</span>
|
|
265
46
|
<div>
|
|
266
47
|
<div class="text-2xl font-extrabold tabular-nums">{{savedQueries}}</div>
|
|
267
48
|
<div class="text-[13px] text-base-content/50">Saved queries</div>
|
|
268
49
|
</div>
|
|
269
50
|
</div>
|
|
270
51
|
<div class="stat-card">
|
|
271
52
|
<span class="stat-icon {{#if isPostgres}}bg-info/10 text-info{{else}}bg-emerald-500/10 text-emerald-500{{/if}}">
|
|
272
53
|
{{{icon "database" class="h-6 w-6"}}}
|
|
273
54
|
</span>
|
|
274
55
|
<div>
|
|
275
56
|
<div class="flex items-center gap-1.5">
|
|
276
57
|
<span class="text-xl font-extrabold">{{dialectName}}</span>
|
|
277
58
|
{{#if readonly}}
|
|
278
59
|
<span class="rounded bg-warning/20 px-1.5 py-0.5 text-[10px] font-bold uppercase text-warning">Read-only</span>
|
|
279
60
|
{{else}}
|
|
280
61
|
<span class="rounded bg-success/20 px-1.5 py-0.5 text-[10px] font-bold uppercase text-success">Writable</span>
|
|
281
62
|
{{/if}}
|
|
282
63
|
</div>
|
|
283
64
|
<div class="truncate font-mono text-xs text-base-content/50" title="{{dbPath}}">{{dbPath}}</div>
|
|
284
65
|
</div>
|
|
285
66
|
</div>
|
|
286
67
|
</div>
|
|
287
68
|
<div>
|
|
288
69
|
<div class="mb-3 flex items-center justify-between">
|
|
289
70
|
<h2 class="text-lg font-bold">Tables</h2>
|
|
290
71
|
<span class="text-sm text-base-content/45">{{tables.length}} total</span>
|
|
291
72
|
</div>
|
|
292
73
|
{{#if tables.length}}
|
|
293
74
|
{{#unless readonly}}
|
|
294
75
|
<div id="home-bulk-toolbar"
|
|
295
76
|
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;"
|
|
296
77
|
aria-hidden="true">
|
|
297
78
|
<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">
|
|
298
79
|
<span id="home-bulk-count"
|
|
299
80
|
class="inline-flex items-center gap-1.5 rounded-full bg-primary/10 px-3 py-1 text-xs font-bold text-primary">
|
|
300
81
|
<span id="home-bulk-count-num">0</span> selected
|
|
301
82
|
</span>
|
|
302
83
|
<div class="h-4 w-px bg-base-300"></div>
|
|
303
84
|
<div class="dropdown dropdown-bottom" id="home-dd-clear">
|
|
304
85
|
<button tabindex="0" id="home-btn-clear"
|
|
305
86
|
class="btn btn-sm btn-warning gap-1.5 font-semibold">
|
|
306
87
|
{{{icon "refresh" class="h-3.5 w-3.5"}}}
|
|
307
88
|
Clear Rows
|
|
308
89
|
{{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
|
|
309
90
|
</button>
|
|
310
91
|
<ul tabindex="0"
|
|
311
92
|
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">
|
|
312
93
|
<li>
|
|
313
94
|
<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">
|
|
314
95
|
<span class="mt-0.5 text-warning shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
|
|
315
96
|
<span>
|
|
316
97
|
<span class="block font-semibold">Clear rows</span>
|
|
317
98
|
<span class="block text-xs text-base-content/50">Deletes all rows; fails if FK references exist</span>
|
|
318
99
|
</span>
|
|
319
100
|
</button>
|
|
320
101
|
</li>
|
|
321
102
|
<li>
|
|
322
103
|
<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">
|
|
323
104
|
<span class="mt-0.5 shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
|
|
324
105
|
<span>
|
|
325
106
|
<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>
|
|
326
107
|
<span class="block text-xs text-error/60">Disables FK checks; deletes regardless of references</span>
|
|
327
108
|
</span>
|
|
328
109
|
</button>
|
|
329
110
|
</li>
|
|
330
111
|
</ul>
|
|
331
112
|
</div>
|
|
332
113
|
<div class="dropdown dropdown-bottom" id="home-dd-drop">
|
|
333
114
|
<button tabindex="0" id="home-btn-drop"
|
|
334
115
|
class="btn btn-sm btn-error gap-1.5 font-semibold text-white">
|
|
335
116
|
{{{icon "warning" class="h-3.5 w-3.5"}}}
|
|
336
117
|
Drop Tables
|
|
337
118
|
{{{icon "chevronDown" class="h-3 w-3 opacity-60"}}}
|
|
338
119
|
</button>
|
|
339
120
|
<ul tabindex="0"
|
|
340
121
|
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">
|
|
341
122
|
<li>
|
|
342
123
|
<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">
|
|
343
124
|
<span class="mt-0.5 text-error shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
|
|
344
125
|
<span>
|
|
345
126
|
<span class="block font-semibold">Drop tables</span>
|
|
346
127
|
<span class="block text-xs text-base-content/50">Permanently deletes tables and all data</span>
|
|
347
128
|
</span>
|
|
348
129
|
</button>
|
|
349
130
|
</li>
|
|
350
131
|
<li>
|
|
351
132
|
<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">
|
|
352
133
|
<span class="mt-0.5 shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
|
|
353
134
|
<span>
|
|
354
135
|
<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>
|
|
355
136
|
<span class="block text-xs text-error/60">Drops with FK checks disabled; cascades on Postgres</span>
|
|
356
137
|
</span>
|
|
357
138
|
</button>
|
|
358
139
|
</li>
|
|
359
140
|
</ul>
|
|
360
141
|
</div>
|
|
361
142
|
<div class="ml-auto">
|
|
362
143
|
<button id="home-bulk-deselect"
|
|
363
144
|
class="btn btn-ghost btn-sm gap-1 text-base-content/50 hover:text-base-content">
|
|
364
145
|
{{{icon "x" class="h-3.5 w-3.5"}}}
|
|
365
146
|
Deselect all
|
|
366
147
|
</button>
|
|
367
148
|
</div>
|
|
368
149
|
</div>
|
|
369
150
|
</div>
|
|
370
151
|
{{/unless}}
|
|
371
152
|
<div class="app-card overflow-hidden">
|
|
372
153
|
<div class="overflow-x-auto">
|
|
373
154
|
<table class="table table-sm" id="home-tables-table">
|
|
374
155
|
<thead>
|
|
375
156
|
<tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
|
|
376
157
|
{{#unless readonly}}
|
|
377
158
|
<th class="w-10">
|
|
378
159
|
<input type="checkbox" id="home-select-all"
|
|
379
160
|
class="checkbox checkbox-sm checkbox-primary"
|
|
380
161
|
title="Select all tables" />
|
|
381
162
|
</th>
|
|
382
163
|
{{/unless}}
|
|
383
164
|
<th class="font-semibold">Table</th>
|
|
384
165
|
<th class="text-right font-semibold">Columns</th>
|
|
385
166
|
<th class="text-right font-semibold">Rows</th>
|
|
386
167
|
<th class="text-right font-semibold">Actions</th>
|
|
387
168
|
</tr>
|
|
388
169
|
</thead>
|
|
389
170
|
<tbody>
|
|
390
171
|
{{#each tables}}
|
|
391
172
|
<tr class="group hover:bg-base-200/50 home-table-row" data-table="{{this}}">
|
|
392
173
|
{{#unless ../readonly}}
|
|
393
174
|
<td class="w-10">
|
|
394
175
|
<input type="checkbox"
|
|
395
176
|
class="checkbox checkbox-sm checkbox-primary home-table-checkbox"
|
|
396
177
|
data-table="{{this}}"
|
|
397
178
|
title="Select {{this}}" />
|
|
398
179
|
</td>
|
|
399
180
|
{{/unless}}
|
|
400
181
|
<td>
|
|
401
182
|
<a href="{{../basePath}}/tables/{{this}}" class="inline-flex items-center gap-2.5 font-medium">
|
|
402
183
|
<span class="grid h-8 w-8 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
|
|
403
184
|
{{{icon "table" class="h-4 w-4"}}}
|
|
404
185
|
</span>
|
|
405
186
|
<span class="font-mono text-[13.5px]">{{this}}</span>
|
|
406
187
|
</a>
|
|
407
188
|
</td>
|
|
408
189
|
<td class="text-right tabular-nums text-base-content/60">{{lookup ../cols this}}</td>
|
|
409
190
|
<td class="text-right tabular-nums text-base-content/60">{{lookup ../counts this}}</td>
|
|
410
191
|
<td class="text-right">
|
|
411
192
|
<a href="{{../basePath}}/tables/{{this}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
|
|
412
193
|
Browse
|
|
413
194
|
{{{icon "arrowRight" class="h-3.5 w-3.5"}}}
|
|
414
195
|
</a>
|
|
415
196
|
</td>
|
|
416
197
|
</tr>
|
|
417
198
|
{{/each}}
|
|
418
199
|
</tbody>
|
|
419
200
|
</table>
|
|
420
201
|
</div>
|
|
421
202
|
</div>
|
|
422
203
|
{{else}}
|
|
423
204
|
<div class="empty-state">
|
|
424
205
|
<span class="empty-icon">
|
|
425
206
|
{{{icon "table" class="h-7 w-7"}}}
|
|
426
207
|
</span>
|
|
427
208
|
<p class="text-sm font-medium text-base-content/70">No tables yet</p>
|
|
428
209
|
<p class="max-w-sm text-sm text-base-content/45">Create one with the table designer, or run a SQL statement in the query editor to get started.</p>
|
|
429
210
|
<div class="mt-2 flex gap-2">
|
|
430
211
|
{{#unless readonly}}
|
|
431
212
|
<a href="{{basePath}}/designer" class="btn btn-primary btn-sm">New table</a>
|
|
432
213
|
{{/unless}}
|
|
433
214
|
<a href="{{basePath}}/query" class="btn btn-outline btn-sm">Query editor</a>
|
|
434
215
|
</div>
|
|
435
216
|
</div>
|
|
436
217
|
{{/if}}
|
|
437
218
|
</div>
|