admindb 1.2.0 → 2.0.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 +250 -352
- package/dist/app.d.ts +25 -4
- package/dist/app.js +79 -15
- package/dist/app.js.map +1 -1
- package/dist/auth/config.d.ts +19 -0
- package/dist/auth/config.js +147 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/crypto.d.ts +27 -0
- package/dist/auth/crypto.js +133 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.js +22 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +14 -0
- package/dist/auth/middleware.js +100 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/routes.d.ts +7 -0
- package/dist/auth/routes.js +78 -0
- package/dist/auth/routes.js.map +1 -0
- package/dist/auth/types.d.ts +35 -0
- package/dist/auth/types.js +11 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli/args.d.ts +45 -0
- package/dist/cli/args.js +328 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config.d.ts +56 -0
- package/dist/cli/config.js +133 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +21 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/runner.d.ts +1 -0
- package/dist/cli/runner.js +222 -0
- package/dist/cli/runner.js.map +1 -0
- package/dist/cli.js +2 -127
- package/dist/cli.js.map +1 -1
- package/dist/data/datasets.d.ts +17 -0
- package/dist/data/datasets.js +133 -0
- package/dist/data/datasets.js.map +1 -0
- package/dist/data/detector.d.ts +30 -0
- package/dist/data/detector.js +472 -0
- package/dist/data/detector.js.map +1 -0
- package/dist/data/engine.d.ts +10 -0
- package/dist/data/engine.js +211 -0
- package/dist/data/engine.js.map +1 -0
- package/dist/data/index.d.ts +5 -0
- package/dist/data/index.js +22 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data/strategies.d.ts +30 -0
- package/dist/data/strategies.js +343 -0
- package/dist/data/strategies.js.map +1 -0
- package/dist/data/types.d.ts +73 -0
- package/dist/data/types.js +8 -0
- package/dist/data/types.js.map +1 -0
- package/dist/db/database.d.ts +14 -142
- package/dist/db/database.js +209 -435
- package/dist/db/database.js.map +1 -1
- package/dist/db/export.d.ts +2 -2
- package/dist/db/export.js +7 -2
- package/dist/db/export.js.map +1 -1
- package/dist/db/filters.d.ts +22 -0
- package/dist/db/filters.js +158 -0
- package/dist/db/filters.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.js +25 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/introspection.d.ts +6 -0
- package/dist/db/introspection.js +172 -0
- package/dist/db/introspection.js.map +1 -0
- package/dist/db/manager.d.ts +32 -19
- package/dist/db/manager.js +203 -44
- package/dist/db/manager.js.map +1 -1
- package/dist/db/migrations.d.ts +5 -0
- package/dist/db/migrations.js +110 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/postgres.d.ts +85 -0
- package/dist/db/postgres.js +745 -0
- package/dist/db/postgres.js.map +1 -0
- package/dist/db/types.d.ts +206 -0
- package/dist/db/types.js +7 -0
- package/dist/db/types.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +46 -4
- package/dist/index.js.map +1 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/css/input.css +83 -13
- package/dist/public/js/app.js +142 -0
- package/dist/public/js/browse.js +591 -104
- package/dist/public/js/databases.js +105 -13
- package/dist/public/js/designer.js +40 -2
- package/dist/public/js/forms.js +610 -28
- package/dist/public/js/icons.js +51 -0
- package/dist/public/js/inspector.js +638 -0
- package/dist/public/js/query.js +93 -3
- package/dist/public/js/schema.js +170 -52
- package/dist/public/js/seed.js +1090 -0
- package/dist/routes/api/helpers.d.ts +42 -0
- package/dist/routes/api/helpers.js +133 -0
- package/dist/routes/api/helpers.js.map +1 -0
- package/dist/routes/api/import-export.d.ts +3 -0
- package/dist/routes/api/import-export.js +85 -0
- package/dist/routes/api/import-export.js.map +1 -0
- package/dist/routes/api/index.d.ts +4 -0
- package/dist/routes/api/index.js +37 -0
- package/dist/routes/api/index.js.map +1 -0
- package/dist/routes/api/query.d.ts +3 -0
- package/dist/routes/api/query.js +76 -0
- package/dist/routes/api/query.js.map +1 -0
- package/dist/routes/api/rows.d.ts +3 -0
- package/dist/routes/api/rows.js +373 -0
- package/dist/routes/api/rows.js.map +1 -0
- package/dist/routes/api/seed.d.ts +3 -0
- package/dist/routes/api/seed.js +82 -0
- package/dist/routes/api/seed.js.map +1 -0
- package/dist/routes/api/tables.d.ts +3 -0
- package/dist/routes/api/tables.js +160 -0
- package/dist/routes/api/tables.js.map +1 -0
- package/dist/routes/databases.d.ts +8 -11
- package/dist/routes/databases.js +100 -66
- package/dist/routes/databases.js.map +1 -1
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.js +20 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/pages.d.ts +3 -3
- package/dist/routes/pages.js +163 -54
- package/dist/routes/pages.js.map +1 -1
- package/dist/serverless.d.ts +40 -0
- package/dist/serverless.js +210 -0
- package/dist/serverless.js.map +1 -0
- package/dist/sql/generator.d.ts +4 -3
- package/dist/sql/generator.js +103 -6
- package/dist/sql/generator.js.map +1 -1
- package/dist/sql/index.d.ts +2 -0
- package/dist/sql/index.js +19 -0
- package/dist/sql/index.js.map +1 -0
- package/dist/types/api.d.ts +412 -0
- package/dist/types/api.js +9 -0
- package/dist/types/api.js.map +1 -0
- package/dist/utils/colors.d.ts +40 -0
- package/dist/utils/colors.js +64 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/{util.d.ts → utils/common.d.ts} +10 -6
- package/dist/{util.js → utils/common.js} +80 -13
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/csv.js.map +1 -0
- package/dist/utils/datatype.d.ts +49 -0
- package/dist/utils/datatype.js +222 -0
- package/dist/utils/datatype.js.map +1 -0
- package/dist/utils/icons.d.ts +11 -0
- package/dist/utils/icons.js +72 -0
- package/dist/utils/icons.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/{logger.d.ts → utils/logger.d.ts} +1 -1
- package/dist/utils/logger.js +40 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/views/layouts/main.hbs +33 -11
- package/dist/views/pages/databases.hbs +182 -74
- package/dist/views/pages/designer.hbs +9 -6
- package/dist/views/pages/error.hbs +3 -3
- package/dist/views/pages/form.hbs +5 -3
- package/dist/views/pages/home.hbs +22 -13
- package/dist/views/pages/login.hbs +111 -0
- package/dist/views/pages/query.hbs +10 -8
- package/dist/views/pages/schema.hbs +41 -13
- package/dist/views/pages/seed.hbs +232 -0
- package/dist/views/pages/table.hbs +155 -70
- package/dist/views/partials/icon.hbs +2 -0
- package/dist/views/partials/navbar.hbs +70 -31
- package/dist/views/partials/sidebar.hbs +108 -99
- package/package.json +12 -5
- package/dist/args.d.ts +0 -28
- package/dist/args.js +0 -187
- package/dist/args.js.map +0 -1
- package/dist/config.d.ts +0 -17
- package/dist/config.js +0 -23
- package/dist/config.js.map +0 -1
- package/dist/csv.js.map +0 -1
- package/dist/logger.js +0 -25
- package/dist/logger.js.map +0 -1
- package/dist/routes/api.d.ts +0 -9
- package/dist/routes/api.js +0 -786
- package/dist/routes/api.js.map +0 -1
- package/dist/test/classifier.test.d.ts +0 -1
- package/dist/test/classifier.test.js +0 -44
- package/dist/test/classifier.test.js.map +0 -1
- package/dist/test/csv.test.d.ts +0 -1
- package/dist/test/csv.test.js +0 -64
- package/dist/test/csv.test.js.map +0 -1
- package/dist/test/database.test.d.ts +0 -1
- package/dist/test/database.test.js +0 -402
- package/dist/test/database.test.js.map +0 -1
- package/dist/test/generator.test.d.ts +0 -1
- package/dist/test/generator.test.js +0 -132
- package/dist/test/generator.test.js.map +0 -1
- package/dist/test/manager.test.d.ts +0 -1
- package/dist/test/manager.test.js +0 -146
- package/dist/test/manager.test.js.map +0 -1
- package/dist/util.js.map +0 -1
- /package/dist/{csv.d.ts → utils/csv.d.ts} +0 -0
- /package/dist/{csv.js → utils/csv.js} +0 -0
|
@@ -1,50 +1,89 @@
|
|
|
1
|
+
{{!-- Partial: Top Navigation Bar Header --}}
|
|
1
2
|
<div class="sticky top-0 z-30 border-b border-base-300/80 bg-base-100/85 backdrop-blur-md">
|
|
3
|
+
|
|
2
4
|
<div class="navbar mx-auto w-full max-w-[1500px] px-4 sm:px-6 lg:px-8">
|
|
3
5
|
<div class="flex-none lg:hidden">
|
|
4
6
|
<label for="sidebar-toggle" class="btn btn-square btn-ghost" aria-label="open sidebar">
|
|
5
|
-
|
|
6
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
|
|
7
|
-
</svg>
|
|
7
|
+
{{{icon "menu" class="h-5 w-5"}}}
|
|
8
8
|
</label>
|
|
9
9
|
</div>
|
|
10
|
-
<div class="flex-1">
|
|
10
|
+
<div class="flex flex-1 items-center gap-3">
|
|
11
11
|
<a href="{{basePath}}/" class="flex items-center gap-2.5">
|
|
12
|
-
<span class="
|
|
13
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
14
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M4 7v10c0 1.1.9 2 2 2h12a2 2 0 002-2V7M4 7c0-1.1.9-2 2-2h12a2 2 0 012 2M4 7c0 1.1.9 2 2 2h12a2 2 0 002-2" />
|
|
15
|
-
</svg>
|
|
16
|
-
</span>
|
|
17
|
-
<span class="text-lg font-bold tracking-tight">DB<span class="text-primary">Admin</span></span>
|
|
12
|
+
<span class="text-lg font-bold tracking-tight">Admin<span class="text-primary">DB</span></span>
|
|
18
13
|
</a>
|
|
14
|
+
{{#unless databasesMode}}
|
|
15
|
+
{{#if isPostgres}}
|
|
16
|
+
<span class="inline-flex items-center gap-1.5 rounded-lg border border-info/40 bg-info/10 px-2.5 py-0.5 text-xs font-semibold text-info" title="Engine: PostgreSQL ({{dbPath}})">
|
|
17
|
+
<span class="h-2 w-2 rounded-full bg-info animate-pulse"></span>
|
|
18
|
+
PostgreSQL
|
|
19
|
+
</span>
|
|
20
|
+
{{else}}
|
|
21
|
+
<span class="inline-flex items-center gap-1.5 rounded-lg border border-emerald-500/40 bg-emerald-500/10 px-2.5 py-0.5 text-xs font-semibold text-emerald-600 dark:text-emerald-400" title="Engine: SQLite ({{dbPath}})">
|
|
22
|
+
<span class="h-2 w-2 rounded-full bg-emerald-500 animate-pulse"></span>
|
|
23
|
+
SQLite
|
|
24
|
+
</span>
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{/unless}}
|
|
19
27
|
</div>
|
|
28
|
+
|
|
20
29
|
<div class="flex items-center gap-1.5">
|
|
21
|
-
{{#unless
|
|
22
|
-
{{#
|
|
23
|
-
|
|
24
|
-
<
|
|
25
|
-
|
|
30
|
+
{{#unless noSidebar}}
|
|
31
|
+
{{#unless databasesMode}}
|
|
32
|
+
{{#if databasesUrl}}
|
|
33
|
+
<a href="{{databasesUrl}}" class="btn btn-ghost btn-sm hidden gap-1.5 sm:inline-flex">
|
|
34
|
+
{{{icon "database" class="h-4 w-4"}}}
|
|
35
|
+
Databases
|
|
36
|
+
</a>
|
|
37
|
+
{{/if}}
|
|
38
|
+
<a href="{{basePath}}/query" class="btn btn-ghost btn-sm hidden gap-1.5 sm:inline-flex">
|
|
39
|
+
{{{icon "query" class="h-4 w-4"}}}
|
|
40
|
+
Query
|
|
26
41
|
</a>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<a href="{{basePath}}/
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
{{#unless readonly}}
|
|
43
|
+
<a href="{{basePath}}/designer" class="btn btn-ghost btn-sm hidden gap-1.5 sm:inline-flex">
|
|
44
|
+
{{{icon "plus" class="h-4 w-4"}}}
|
|
45
|
+
New table
|
|
46
|
+
</a>
|
|
47
|
+
{{/unless}}
|
|
48
|
+
<a href="{{basePath}}/export" class="btn btn-ghost btn-sm hidden gap-1.5 md:inline-flex">
|
|
49
|
+
{{{icon "export" class="h-4 w-4"}}}
|
|
50
|
+
Export
|
|
36
51
|
</a>
|
|
37
52
|
{{/unless}}
|
|
38
|
-
<a href="{{basePath}}/export" class="btn btn-ghost btn-sm hidden gap-1.5 md:inline-flex">
|
|
39
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
|
|
40
|
-
Export
|
|
41
|
-
</a>
|
|
42
53
|
{{/unless}}
|
|
54
|
+
|
|
55
|
+
{{#if authEnabled}}
|
|
56
|
+
{{#if authUser}}
|
|
57
|
+
{{#if isDefaultPassword}}
|
|
58
|
+
<span class="badge badge-warning badge-sm gap-1 hidden sm:inline-flex font-mono text-[11px]" title="Using default password (admin). Set ADMINDB_PASSWORD in production.">
|
|
59
|
+
{{{icon "warning" class="h-3.5 w-3.5"}}}
|
|
60
|
+
default pass
|
|
61
|
+
</span>
|
|
62
|
+
{{/if}}
|
|
63
|
+
<div class="dropdown dropdown-end">
|
|
64
|
+
<label tabindex="0" class="btn btn-ghost btn-sm gap-1.5 normal-case font-medium">
|
|
65
|
+
{{{icon "user" class="h-4 w-4 text-base-content/70"}}}
|
|
66
|
+
<span class="max-w-[120px] truncate text-xs">{{authUser}}</span>
|
|
67
|
+
</label>
|
|
68
|
+
<ul tabindex="0" class="dropdown-content menu p-2 shadow-soft bg-base-100 rounded-xl w-48 border border-base-300 z-50 mt-1 text-sm">
|
|
69
|
+
<li class="menu-title px-2 py-1 text-xs text-base-content/50">Signed in as <strong class="text-base-content">{{authUser}}</strong></li>
|
|
70
|
+
<li>
|
|
71
|
+
<form method="POST" action="{{basePath}}/logout" class="p-0">
|
|
72
|
+
<button type="submit" class="w-full text-left flex items-center gap-2 px-3 py-2 text-error hover:bg-error/10 rounded-lg">
|
|
73
|
+
{{{icon "logout" class="h-4 w-4"}}}
|
|
74
|
+
Sign out
|
|
75
|
+
</button>
|
|
76
|
+
</form>
|
|
77
|
+
</li>
|
|
78
|
+
</ul>
|
|
79
|
+
</div>
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{/if}}
|
|
82
|
+
|
|
43
83
|
<button id="theme-toggle" type="button" class="btn btn-square btn-ghost btn-sm" aria-label="Toggle dark mode" title="Toggle dark mode">
|
|
44
|
-
|
|
45
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
|
|
46
|
-
</svg>
|
|
84
|
+
{{{icon "moon" class="h-5 w-5"}}}
|
|
47
85
|
</button>
|
|
86
|
+
|
|
48
87
|
</div>
|
|
49
88
|
</div>
|
|
50
89
|
</div>
|
|
@@ -1,116 +1,125 @@
|
|
|
1
|
+
{{!-- Partial: Left Navigation Sidebar --}}
|
|
1
2
|
<aside class="flex h-full min-h-full w-72 flex-col bg-neutral text-neutral-content">
|
|
3
|
+
|
|
2
4
|
<div class="flex items-center gap-2.5 px-5 pb-4 pt-5">
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
<div class="w-full">
|
|
6
|
+
<div class="flex items-center justify-between">
|
|
7
|
+
<div class="text-base font-bold leading-tight">AdminDB <span style="font-size: x-small">{{#if version}}v{{version}}{{/if}}</span></div>
|
|
8
|
+
{{#unless databasesMode}}
|
|
9
|
+
{{#if isPostgres}}
|
|
10
|
+
<span class="rounded bg-info/20 px-1.5 py-0.5 text-[10px] font-bold text-info">PostgreSQL</span>
|
|
11
|
+
{{else}}
|
|
12
|
+
<span class="rounded bg-emerald-500/20 px-1.5 py-0.5 text-[10px] font-bold text-emerald-400">SQLite</span>
|
|
13
|
+
{{/if}}
|
|
14
|
+
{{/unless}}
|
|
15
|
+
</div>
|
|
16
|
+
<div class="mt-0.5 text-[11px] text-neutral-content/50 truncate">{{#if databasesMode}}Database manager{{else}}{{dbId}}{{/if}}</div>
|
|
11
17
|
</div>
|
|
12
18
|
</div>
|
|
13
19
|
|
|
14
20
|
{{#if databasesMode}}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
<nav class="flex-1 overflow-y-auto px-3 py-2">
|
|
22
|
+
<ul class="space-y-0.5">
|
|
23
|
+
<li>
|
|
24
|
+
<a href="{{basePath}}/" class="side-link active">
|
|
25
|
+
{{{icon "database" class="h-4 w-4"}}}
|
|
26
|
+
Databases
|
|
27
|
+
</a>
|
|
28
|
+
</li>
|
|
29
|
+
</ul>
|
|
30
|
+
</nav>
|
|
25
31
|
{{else}}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
<div class="px-4 pb-2">
|
|
33
|
+
<label class="relative block">
|
|
34
|
+
<span class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-neutral-content/40">
|
|
35
|
+
{{{icon "search" class="h-4 w-4"}}}
|
|
36
|
+
</span>
|
|
37
|
+
<input id="table-search" type="search" placeholder="Filter tables…" autocomplete="off"
|
|
38
|
+
class="w-full rounded-lg border border-white/10 bg-white/[0.06] py-2 pl-9 pr-3 text-sm text-neutral-content outline-none transition placeholder:text-neutral-content/40 focus:border-primary/70 focus:ring-4 focus:ring-primary/20" />
|
|
39
|
+
</label>
|
|
40
|
+
</div>
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
42
|
+
<nav class="flex-1 overflow-y-auto px-3 py-2">
|
|
43
|
+
<ul class="space-y-0.5">
|
|
44
|
+
{{#if databasesUrl}}
|
|
45
|
+
<li>
|
|
46
|
+
<a href="{{databasesUrl}}" class="side-link">
|
|
47
|
+
{{{icon "database" class="h-4 w-4"}}}
|
|
48
|
+
Databases
|
|
49
|
+
</a>
|
|
50
|
+
</li>
|
|
51
|
+
{{/if}}
|
|
52
|
+
<li>
|
|
53
|
+
<a href="{{basePath}}/" class="side-link {{#if (eq currentPath '/')}}active{{/if}}">
|
|
54
|
+
{{{icon "home" class="h-4 w-4"}}}
|
|
55
|
+
Home
|
|
56
|
+
</a>
|
|
57
|
+
</li>
|
|
58
|
+
<li>
|
|
59
|
+
<a href="{{basePath}}/query" class="side-link {{#if (startsWith currentPath '/query')}}active{{/if}}">
|
|
60
|
+
{{{icon "query" class="h-4 w-4"}}}
|
|
61
|
+
Query editor
|
|
62
|
+
</a>
|
|
63
|
+
</li>
|
|
64
|
+
{{#unless readonly}}
|
|
65
|
+
<li>
|
|
66
|
+
<a href="{{basePath}}/designer" class="side-link {{#if (startsWith currentPath '/designer')}}active{{/if}}">
|
|
67
|
+
{{{icon "plus" class="h-4 w-4"}}}
|
|
68
|
+
New table
|
|
69
|
+
</a>
|
|
70
|
+
</li>
|
|
71
|
+
{{/unless}}
|
|
72
|
+
</ul>
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
<div class="mb-2 mt-6 flex items-center justify-between px-3">
|
|
75
|
+
<span class="text-[11px] font-semibold uppercase tracking-wider text-neutral-content/40">Tables</span>
|
|
76
|
+
<span id="table-count" class="rounded-md bg-white/[0.06] px-1.5 py-0.5 text-[10px] font-semibold text-neutral-content/50">{{tables.length}}</span>
|
|
77
|
+
</div>
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
<ul id="table-list" class="space-y-0.5">
|
|
80
|
+
{{#each tables}}
|
|
81
|
+
<li class="table-item" data-name="{{this}}">
|
|
82
|
+
<a href="{{../basePath}}/tables/{{this}}" class="side-link {{#if (eq ../currentTable this)}}active{{/if}}">
|
|
83
|
+
<span class="table-icon">
|
|
84
|
+
{{{icon "table" class="h-4 w-4"}}}
|
|
85
|
+
</span>
|
|
86
|
+
<span class="truncate">{{this}}</span>
|
|
87
|
+
</a>
|
|
88
|
+
</li>
|
|
89
|
+
{{else}}
|
|
90
|
+
<li class="px-3 py-2 text-xs text-neutral-content/40">No tables yet</li>
|
|
91
|
+
{{/each}}
|
|
92
|
+
</ul>
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
{{#if internalTables.length}}
|
|
95
|
+
<div class="mb-2 mt-6 px-3 text-[11px] font-semibold uppercase tracking-wider text-neutral-content/40">Internal</div>
|
|
96
|
+
<ul class="space-y-0.5">
|
|
97
|
+
{{#each internalTables}}
|
|
98
|
+
<li>
|
|
99
|
+
<a href="{{../basePath}}/tables/{{this}}" class="side-link {{#if (eq ../currentTable this)}}active{{/if}}">
|
|
100
|
+
<span class="table-icon">
|
|
101
|
+
{{{icon "book" class="h-4 w-4"}}}
|
|
102
|
+
</span>
|
|
103
|
+
<span class="truncate">{{this}}</span>
|
|
104
|
+
</a>
|
|
105
|
+
</li>
|
|
106
|
+
{{/each}}
|
|
107
|
+
</ul>
|
|
108
|
+
{{/if}}
|
|
109
|
+
</nav>
|
|
104
110
|
{{/if}}
|
|
105
111
|
|
|
106
112
|
<div class="border-t border-white/10 px-5 py-3">
|
|
107
|
-
<div class="
|
|
113
|
+
<div class="flex items-center justify-between">
|
|
114
|
+
<div class="text-[11px] font-medium uppercase tracking-wider text-neutral-content/40">{{#if databasesMode}}Directory{{else}}Engine: {{dialectName}}{{/if}}</div>
|
|
115
|
+
{{#unless databasesMode}}
|
|
116
|
+
{{#if readonly}}
|
|
117
|
+
<span class="rounded bg-warning/20 px-1.5 py-0.5 text-[9px] font-bold uppercase text-warning">Read-only</span>
|
|
118
|
+
{{else}}
|
|
119
|
+
<span class="rounded bg-success/20 px-1.5 py-0.5 text-[9px] font-bold uppercase text-success">Writable</span>
|
|
120
|
+
{{/if}}
|
|
121
|
+
{{/unless}}
|
|
122
|
+
</div>
|
|
108
123
|
<div class="mt-0.5 truncate font-mono text-[11px] text-neutral-content/60" title="{{dbPath}}">{{dbPath}}</div>
|
|
109
|
-
{{#if readonly}}
|
|
110
|
-
<div class="mt-2 inline-flex items-center gap-1 rounded-md bg-warning/20 px-2 py-1 text-[10px] font-bold uppercase tracking-wider text-warning">
|
|
111
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 15v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>
|
|
112
|
-
Read-only
|
|
113
|
-
</div>
|
|
114
|
-
{{/if}}
|
|
115
124
|
</div>
|
|
116
125
|
</aside>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "admindb",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Browser-based SQLite database administration tool — embed it in your Express app or run it standalone.",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Browser-based SQLite & PostgreSQL database administration tool — embed it in your Express app or run it standalone.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -32,10 +32,15 @@
|
|
|
32
32
|
"dev": "concurrently -k -n server,css \"tsx watch src/cli.ts\" \"npm run dev:css\"",
|
|
33
33
|
"dev:css": "cross-env BROWSERSLIST_IGNORE_OLD_DATA=1 tailwindcss -i ./src/public/css/input.css -o ./src/public/css/app.css --watch",
|
|
34
34
|
"prepack": "npm run build",
|
|
35
|
-
"test": "
|
|
35
|
+
"test": "tsx --test test/*.test.ts",
|
|
36
|
+
"test:smoke": "tsx --test test/smoke.test.ts",
|
|
37
|
+
"generatehash": "node scripts/generate-hash.mjs",
|
|
38
|
+
"lint": "tsc --noEmit"
|
|
36
39
|
},
|
|
37
40
|
"keywords": [
|
|
38
41
|
"sqlite",
|
|
42
|
+
"postgres",
|
|
43
|
+
"postgresql",
|
|
39
44
|
"admin",
|
|
40
45
|
"database",
|
|
41
46
|
"express",
|
|
@@ -50,14 +55,16 @@
|
|
|
50
55
|
"dependencies": {
|
|
51
56
|
"better-sqlite3": "^11.9.1",
|
|
52
57
|
"express": "^5.1.0",
|
|
53
|
-
"express-handlebars": "^8.0.3"
|
|
58
|
+
"express-handlebars": "^8.0.3",
|
|
59
|
+
"pg": "^8.23.0"
|
|
54
60
|
},
|
|
55
61
|
"devDependencies": {
|
|
56
62
|
"@types/better-sqlite3": "^9.6.0",
|
|
57
63
|
"@types/express": "^4.17.21",
|
|
58
64
|
"@types/node": "^22.10.0",
|
|
65
|
+
"@types/pg": "^8.23.1",
|
|
59
66
|
"concurrently": "^9.1.0",
|
|
60
|
-
"cross-env": "^
|
|
67
|
+
"cross-env": "^7.0.3",
|
|
61
68
|
"daisyui": "^4.12.0",
|
|
62
69
|
"tailwindcss": "^3.4.17",
|
|
63
70
|
"tsx": "^4.19.0",
|
package/dist/args.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { LogLevel } from './logger';
|
|
2
|
-
export interface CliArgs {
|
|
3
|
-
help: boolean;
|
|
4
|
-
version: boolean;
|
|
5
|
-
/** Bind host/interface. */
|
|
6
|
-
host?: string;
|
|
7
|
-
/** Port to listen on. */
|
|
8
|
-
port?: number;
|
|
9
|
-
/** A single database file to open directly (`--open`/`--db`/`--file`). */
|
|
10
|
-
dbPath?: string;
|
|
11
|
-
/** Directory of database files to manage (`--dir`). */
|
|
12
|
-
dbDir?: string;
|
|
13
|
-
/** Explicit database file paths (`--files a.db,b.db`). */
|
|
14
|
-
dbFiles?: string[];
|
|
15
|
-
/** URL prefix to serve under (`--base-path`). */
|
|
16
|
-
basePath?: string;
|
|
17
|
-
logLevel?: LogLevel;
|
|
18
|
-
/** Open databases read-only (`--readonly`). */
|
|
19
|
-
readonly: boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare function helpText(): string;
|
|
22
|
-
/** The installed `admindb` package version (from package.json), or '' when unknown. */
|
|
23
|
-
export declare function getPackageVersion(): string;
|
|
24
|
-
export declare function versionText(): string;
|
|
25
|
-
export declare function parseArgs(argv: string[]): {
|
|
26
|
-
args: CliArgs;
|
|
27
|
-
error?: string;
|
|
28
|
-
};
|
package/dist/args.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.helpText = helpText;
|
|
7
|
-
exports.getPackageVersion = getPackageVersion;
|
|
8
|
-
exports.versionText = versionText;
|
|
9
|
-
exports.parseArgs = parseArgs;
|
|
10
|
-
/**
|
|
11
|
-
* Command-line argument parsing for the standalone `admindb` server.
|
|
12
|
-
*
|
|
13
|
-
* The CLI supports flags to pick the port/host, open a single database file,
|
|
14
|
-
* manage a folder of databases, and more. Every flag has a matching
|
|
15
|
-
* environment variable; flags always win over the environment.
|
|
16
|
-
*/
|
|
17
|
-
const node_fs_1 = require("node:fs");
|
|
18
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
-
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
20
|
-
function helpText() {
|
|
21
|
-
return [
|
|
22
|
-
'AdminDB — browser-based SQLite administration tool.',
|
|
23
|
-
'',
|
|
24
|
-
'Usage:',
|
|
25
|
-
' admindb [options] [path]',
|
|
26
|
-
'',
|
|
27
|
-
'Starts a local server and opens a web UI where you can browse, select and',
|
|
28
|
-
'manage SQLite databases (.db / .sqlite / .sqlite3).',
|
|
29
|
-
'',
|
|
30
|
-
'With no path or options it runs in "manager" mode: the landing page lets',
|
|
31
|
-
'you browse the filesystem and open any database file, or create new ones.',
|
|
32
|
-
'',
|
|
33
|
-
'Arguments:',
|
|
34
|
-
' path Path to a database file (opens it directly) or to a',
|
|
35
|
-
' folder of databases (lists them). Default: the',
|
|
36
|
-
' current directory.',
|
|
37
|
-
'',
|
|
38
|
-
'Options:',
|
|
39
|
-
' -p, --port <port> Port to listen on (default: 3000)',
|
|
40
|
-
' -H, --host <host> Host/interface to bind (default: 0.0.0.0)',
|
|
41
|
-
' -o, --open <file> Open a single database file',
|
|
42
|
-
' -d, --dir <dir> Folder of database files to manage',
|
|
43
|
-
' --files <list> Comma-separated database file paths',
|
|
44
|
-
' -b, --base-path <p> URL prefix to serve under (default: /)',
|
|
45
|
-
' -r, --readonly Open databases read-only (all writes disabled)',
|
|
46
|
-
' -l, --log-level <l> debug | info | warn | error (default: info)',
|
|
47
|
-
' -h, --help Show this help',
|
|
48
|
-
' -v, --version Show the version',
|
|
49
|
-
'',
|
|
50
|
-
'Environment variables (used when the matching flag is not given):',
|
|
51
|
-
' PORT, HOST, DB_PATH, DB_DIR, DB_FILES, BASE_PATH, READONLY, LOG_LEVEL',
|
|
52
|
-
'',
|
|
53
|
-
'Examples:',
|
|
54
|
-
' admindb # manager UI on http://localhost:3000',
|
|
55
|
-
' admindb -p 8080 # same, on port 8080',
|
|
56
|
-
' admindb ./data/app.db # open a single database file',
|
|
57
|
-
' admindb --open ~/notes.sqlite # open a file (direct)',
|
|
58
|
-
' admindb -d ./dbs # manage a folder of databases',
|
|
59
|
-
' admindb --files a.db,b.db -r # open two files read-only',
|
|
60
|
-
].join('\n');
|
|
61
|
-
}
|
|
62
|
-
function packageVersion() {
|
|
63
|
-
try {
|
|
64
|
-
const raw = (0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, '..', 'package.json'), 'utf8');
|
|
65
|
-
const pkg = JSON.parse(raw);
|
|
66
|
-
return pkg.version ?? '';
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
return '';
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/** The installed `admindb` package version (from package.json), or '' when unknown. */
|
|
73
|
-
function getPackageVersion() {
|
|
74
|
-
return packageVersion();
|
|
75
|
-
}
|
|
76
|
-
function versionText() {
|
|
77
|
-
const v = packageVersion();
|
|
78
|
-
return v ? `admindb v${v}` : 'admindb';
|
|
79
|
-
}
|
|
80
|
-
/** True when a token is exactly a flag or `flag=value` (for long flags). */
|
|
81
|
-
function isFlag(tok, ...names) {
|
|
82
|
-
return names.includes(tok) || names.some((n) => n.length > 2 && tok.startsWith(n + '='));
|
|
83
|
-
}
|
|
84
|
-
function parseArgs(argv) {
|
|
85
|
-
const args = { help: false, version: false, readonly: false };
|
|
86
|
-
const positional = [];
|
|
87
|
-
let i = 0;
|
|
88
|
-
const invalid = (error) => ({ args, error });
|
|
89
|
-
// Read the value for the current flag token; supports `--flag=value` and
|
|
90
|
-
// `--flag value`. Leaves `i` pointing at the value token so the loop can
|
|
91
|
-
// advance past it.
|
|
92
|
-
const takeValue = (flag) => {
|
|
93
|
-
const eq = argv[i].indexOf('=');
|
|
94
|
-
if (eq !== -1)
|
|
95
|
-
return argv[i].slice(eq + 1);
|
|
96
|
-
i += 1;
|
|
97
|
-
return argv[i];
|
|
98
|
-
};
|
|
99
|
-
while (i < argv.length) {
|
|
100
|
-
const tok = argv[i];
|
|
101
|
-
if (tok === '-h' || tok === '--help') {
|
|
102
|
-
args.help = true;
|
|
103
|
-
}
|
|
104
|
-
else if (tok === '-v' || tok === '--version') {
|
|
105
|
-
args.version = true;
|
|
106
|
-
}
|
|
107
|
-
else if (isFlag(tok, '-p', '--port')) {
|
|
108
|
-
const v = takeValue('--port');
|
|
109
|
-
if (v === undefined)
|
|
110
|
-
return invalid('Missing value for --port.');
|
|
111
|
-
const n = Number.parseInt(v, 10);
|
|
112
|
-
if (!Number.isFinite(n) || n <= 0)
|
|
113
|
-
return invalid(`Invalid port: "${v}".`);
|
|
114
|
-
args.port = n;
|
|
115
|
-
}
|
|
116
|
-
else if (isFlag(tok, '-H', '--host')) {
|
|
117
|
-
const v = takeValue('--host');
|
|
118
|
-
if (v === undefined)
|
|
119
|
-
return invalid('Missing value for --host.');
|
|
120
|
-
args.host = v;
|
|
121
|
-
}
|
|
122
|
-
else if (isFlag(tok, '-o', '--open', '--db', '-f', '--file')) {
|
|
123
|
-
const v = takeValue('--open');
|
|
124
|
-
if (v === undefined)
|
|
125
|
-
return invalid('Missing value for --open.');
|
|
126
|
-
args.dbPath = v;
|
|
127
|
-
}
|
|
128
|
-
else if (isFlag(tok, '-d', '--dir', '--folder')) {
|
|
129
|
-
const v = takeValue('--dir');
|
|
130
|
-
if (v === undefined)
|
|
131
|
-
return invalid('Missing value for --dir.');
|
|
132
|
-
args.dbDir = v;
|
|
133
|
-
}
|
|
134
|
-
else if (isFlag(tok, '--files')) {
|
|
135
|
-
const v = takeValue('--files');
|
|
136
|
-
if (v === undefined)
|
|
137
|
-
return invalid('Missing value for --files.');
|
|
138
|
-
args.dbFiles = v
|
|
139
|
-
.split(',')
|
|
140
|
-
.map((s) => s.trim())
|
|
141
|
-
.filter(Boolean);
|
|
142
|
-
}
|
|
143
|
-
else if (isFlag(tok, '-b', '--base-path', '--base')) {
|
|
144
|
-
const v = takeValue('--base-path');
|
|
145
|
-
if (v === undefined)
|
|
146
|
-
return invalid('Missing value for --base-path.');
|
|
147
|
-
args.basePath = v;
|
|
148
|
-
}
|
|
149
|
-
else if (isFlag(tok, '-l', '--log-level')) {
|
|
150
|
-
const v = takeValue('--log-level');
|
|
151
|
-
if (v === undefined)
|
|
152
|
-
return invalid('Missing value for --log-level.');
|
|
153
|
-
if (!LOG_LEVELS.includes(v)) {
|
|
154
|
-
return invalid(`Invalid log level: "${v}". Expected one of: ${LOG_LEVELS.join(', ')}.`);
|
|
155
|
-
}
|
|
156
|
-
args.logLevel = v;
|
|
157
|
-
}
|
|
158
|
-
else if (tok === '-r' || tok === '--readonly') {
|
|
159
|
-
args.readonly = true;
|
|
160
|
-
}
|
|
161
|
-
else if (tok.startsWith('-') && tok.length > 1) {
|
|
162
|
-
return invalid(`Unknown option: "${tok}".`);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
positional.push(tok);
|
|
166
|
-
}
|
|
167
|
-
i += 1;
|
|
168
|
-
}
|
|
169
|
-
if (positional.length > 1) {
|
|
170
|
-
return invalid(`Unexpected extra arguments: ${positional.slice(1).join(' ')}.`);
|
|
171
|
-
}
|
|
172
|
-
const p = positional[0];
|
|
173
|
-
if (p) {
|
|
174
|
-
const abs = node_path_1.default.resolve(p);
|
|
175
|
-
try {
|
|
176
|
-
if ((0, node_fs_1.statSync)(abs).isDirectory())
|
|
177
|
-
args.dbDir = p;
|
|
178
|
-
else
|
|
179
|
-
args.dbPath = p;
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
args.dbPath = p;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return { args };
|
|
186
|
-
}
|
|
187
|
-
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|