admindb 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +354 -325
  3. package/dist/db/database.d.ts +61 -39
  4. package/dist/db/database.js +251 -51
  5. package/dist/db/database.js.map +1 -1
  6. package/dist/db/manager.d.ts +2 -2
  7. package/dist/db/manager.js +3 -2
  8. package/dist/db/manager.js.map +1 -1
  9. package/dist/public/css/app.css +1 -1
  10. package/dist/public/css/input.css +232 -179
  11. package/dist/public/js/api.js +47 -47
  12. package/dist/public/js/app.js +120 -120
  13. package/dist/public/js/browse.js +877 -123
  14. package/dist/public/js/databases.js +45 -45
  15. package/dist/public/js/designer.js +205 -205
  16. package/dist/public/js/forms.js +244 -244
  17. package/dist/public/js/query.js +232 -232
  18. package/dist/public/js/schema.js +314 -314
  19. package/dist/routes/api.js +261 -97
  20. package/dist/routes/api.js.map +1 -1
  21. package/dist/routes/pages.js +50 -30
  22. package/dist/routes/pages.js.map +1 -1
  23. package/dist/sql/generator.d.ts +0 -22
  24. package/dist/sql/generator.js +0 -48
  25. package/dist/sql/generator.js.map +1 -1
  26. package/dist/test/database.test.js +241 -63
  27. package/dist/test/database.test.js.map +1 -1
  28. package/dist/test/generator.test.js +0 -32
  29. package/dist/test/generator.test.js.map +1 -1
  30. package/dist/util.d.ts +13 -1
  31. package/dist/util.js +24 -2
  32. package/dist/util.js.map +1 -1
  33. package/dist/views/layouts/main.hbs +49 -49
  34. package/dist/views/pages/databases.hbs +102 -102
  35. package/dist/views/pages/designer.hbs +81 -81
  36. package/dist/views/pages/error.hbs +12 -12
  37. package/dist/views/pages/form.hbs +62 -62
  38. package/dist/views/pages/home.hbs +123 -123
  39. package/dist/views/pages/query.hbs +94 -94
  40. package/dist/views/pages/schema.hbs +290 -290
  41. package/dist/views/pages/table.hbs +256 -203
  42. package/dist/views/partials/navbar.hbs +50 -50
  43. package/dist/views/partials/sidebar.hbs +116 -128
  44. package/package.json +66 -62
  45. package/dist/public/js/triggers.js +0 -155
  46. package/dist/public/js/views.js +0 -176
  47. package/dist/views/pages/triggers.hbs +0 -162
  48. package/dist/views/pages/views.hbs +0 -134
@@ -1,49 +1,49 @@
1
- <!DOCTYPE html>
2
- <html lang="en" data-theme="admindb">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>{{title}} · AdminDB</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
10
- <link rel="stylesheet" href="{{basePath}}/css/app.css" />
11
- <script>
12
- window.APP = { basePath: {{{json basePath}}}, readonly: {{{json readonly}}} };
13
- // Apply the saved theme before first paint to avoid a flash.
14
- (function () {
15
- try {
16
- var t = localStorage.getItem('admindb-theme');
17
- if (t === 'dark') document.documentElement.setAttribute('data-theme', 'admindbDark');
18
- } catch (e) {}
19
- })();
20
- </script>
21
- <script src="{{basePath}}/js/api.js" defer></script>
22
- <script src="{{basePath}}/js/app.js" defer></script>
23
- </head>
24
- <body class="min-h-screen bg-base-200 text-base-content">
25
- {{#if readonly}}
26
- <div class="flex items-center justify-center gap-2 bg-warning/15 px-4 py-2 text-center text-sm font-semibold text-warning">
27
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0" 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>
28
- Read-only mode — this database is open without write access. All writes are disabled.
29
- </div>
30
- {{/if}}
31
- <div class="drawer lg:drawer-open">
32
- <input id="sidebar-toggle" type="checkbox" class="drawer-toggle" />
33
- <div class="drawer-content flex min-h-screen flex-col">
34
- {{> navbar}}
35
- <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
36
- {{{body}}}
37
- </main>
38
- <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
39
- AdminDB · a browser tool for SQLite databases
40
- </footer>
41
- </div>
42
- <div class="drawer-side z-40">
43
- <label for="sidebar-toggle" aria-label="close sidebar" class="drawer-overlay"></label>
44
- {{> sidebar}}
45
- </div>
46
- </div>
47
- <div id="toast-container" class="pointer-events-none fixed inset-x-0 top-4 z-50 flex flex-col items-center gap-2 px-4"></div>
48
- </body>
49
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="admindb">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{title}} · AdminDB</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
10
+ <link rel="stylesheet" href="{{basePath}}/css/app.css" />
11
+ <script>
12
+ window.APP = { basePath: {{{json basePath}}}, readonly: {{{json readonly}}} };
13
+ // Apply the saved theme before first paint to avoid a flash.
14
+ (function () {
15
+ try {
16
+ var t = localStorage.getItem('admindb-theme');
17
+ if (t === 'dark') document.documentElement.setAttribute('data-theme', 'admindbDark');
18
+ } catch (e) {}
19
+ })();
20
+ </script>
21
+ <script src="{{basePath}}/js/api.js" defer></script>
22
+ <script src="{{basePath}}/js/app.js" defer></script>
23
+ </head>
24
+ <body class="min-h-screen bg-base-200 text-base-content">
25
+ {{#if readonly}}
26
+ <div class="flex items-center justify-center gap-2 bg-warning/15 px-4 py-2 text-center text-sm font-semibold text-warning">
27
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0" 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>
28
+ Read-only mode — this database is open without write access. All writes are disabled.
29
+ </div>
30
+ {{/if}}
31
+ <div class="drawer lg:drawer-open">
32
+ <input id="sidebar-toggle" type="checkbox" class="drawer-toggle" />
33
+ <div class="drawer-content flex min-h-screen flex-col">
34
+ {{> navbar}}
35
+ <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
36
+ {{{body}}}
37
+ </main>
38
+ <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
39
+ AdminDB · a browser tool for SQLite databases
40
+ </footer>
41
+ </div>
42
+ <div class="drawer-side z-40">
43
+ <label for="sidebar-toggle" aria-label="close sidebar" class="drawer-overlay"></label>
44
+ {{> sidebar}}
45
+ </div>
46
+ </div>
47
+ <div id="toast-container" class="pointer-events-none fixed inset-x-0 top-4 z-50 flex flex-col items-center gap-2 px-4"></div>
48
+ </body>
49
+ </html>
@@ -1,102 +1,102 @@
1
- <div class="space-y-6">
2
- <!-- Header -->
3
- <div>
4
- <p class="text-sm font-semibold uppercase tracking-wider text-primary">Manager</p>
5
- <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Databases</h1>
6
- <p class="mt-1.5 text-sm text-base-content/55">Open a database to browse and edit it, or create a new one.</p>
7
- </div>
8
-
9
- <!-- New database -->
10
- <div class="app-card p-5">
11
- <div class="flex flex-wrap items-end gap-3">
12
- <div class="w-full max-w-sm">
13
- <label class="field-label" for="new-db-name">New database name</label>
14
- <input id="new-db-name" class="field-input font-mono" placeholder="e.g. analytics" autocomplete="off" spellcheck="false" />
15
- </div>
16
- {{#unless readonly}}
17
- <button id="create-db" type="button" class="btn btn-primary btn-sm mb-0.5 gap-1.5">
18
- <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="M12 4v16m8-8H4" /></svg>
19
- Create
20
- </button>
21
- {{else}}
22
- <span class="mb-1 text-sm font-medium text-warning">Read-only — creating databases is disabled.</span>
23
- {{/unless}}
24
- </div>
25
- <p class="mt-2 text-xs text-base-content/40">
26
- New databases are created in <code class="font-mono">{{dbDir}}</code>. Files already there are picked up
27
- automatically, and any explicitly configured database paths appear here too.
28
- </p>
29
- </div>
30
-
31
- <!-- List -->
32
- <div>
33
- <div class="mb-3 flex items-center justify-between">
34
- <h2 class="text-lg font-bold">Available databases</h2>
35
- <span class="text-sm text-base-content/45">{{databases.length}} total</span>
36
- </div>
37
-
38
- {{#if databases.length}}
39
- <div class="app-card overflow-hidden">
40
- <div class="overflow-x-auto">
41
- <table class="table table-sm">
42
- <thead>
43
- <tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
44
- <th class="font-semibold">Name</th>
45
- <th class="text-right font-semibold">Tables</th>
46
- <th class="text-right font-semibold">Size</th>
47
- <th class="font-semibold">Modified</th>
48
- <th class="text-right font-semibold">Actions</th>
49
- </tr>
50
- </thead>
51
- <tbody>
52
- {{#each databases}}
53
- <tr class="group hover:bg-primary/[0.04]">
54
- <td>
55
- <a href="{{../basePath}}/{{this.id}}" class="inline-flex items-center gap-2.5">
56
- <span class="grid h-8 w-8 shrink-0 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
57
- <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 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" /></svg>
58
- </span>
59
- <span class="min-w-0">
60
- <span class="block truncate font-mono text-[13.5px] font-semibold">{{this.name}}</span>
61
- <span class="block max-w-[220px] truncate text-[11px] text-base-content/40" title="{{this.path}}">{{this.path}}</span>
62
- </span>
63
- </a>
64
- </td>
65
- <td class="text-right tabular-nums text-base-content/60">{{this.tables}}</td>
66
- <td class="text-right tabular-nums text-base-content/60">{{this.sizeLabel}}</td>
67
- <td class="text-[13px] text-base-content/55">{{this.modifiedLabel}}</td>
68
- <td class="whitespace-nowrap text-right">
69
- <div class="row-actions">
70
- <a href="{{../basePath}}/{{this.id}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
71
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
72
- Open
73
- </a>
74
- {{#unless ../readonly}}
75
- <button type="button" class="btn btn-ghost btn-xs gap-1 text-error js-delete-db" data-id="{{this.id}}">
76
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /></svg>
77
- Delete
78
- </button>
79
- {{/unless}}
80
- </div>
81
- </td>
82
- </tr>
83
- {{/each}}
84
- </tbody>
85
- </table>
86
- </div>
87
- </div>
88
- {{else}}
89
- <div class="empty-state">
90
- <span class="empty-icon">
91
- <svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><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" /></svg>
92
- </span>
93
- <p class="text-sm font-medium text-base-content/70">No databases yet</p>
94
- <p class="max-w-sm text-sm text-base-content/45">
95
- Create one above, or drop <code class="font-mono">.db</code> files into
96
- <code class="font-mono">{{dbDir}}</code> and refresh.
97
- </p>
98
- </div>
99
- {{/if}}
100
- </div>
101
- </div>
102
- <script src="{{basePath}}/js/databases.js" defer></script>
1
+ <div class="space-y-6">
2
+ <!-- Header -->
3
+ <div>
4
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary">Manager</p>
5
+ <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Databases</h1>
6
+ <p class="mt-1.5 text-sm text-base-content/55">Open a database to browse and edit it, or create a new one.</p>
7
+ </div>
8
+
9
+ <!-- New database -->
10
+ <div class="app-card p-5">
11
+ <div class="flex flex-wrap items-end gap-3">
12
+ <div class="w-full max-w-sm">
13
+ <label class="field-label" for="new-db-name">New database name</label>
14
+ <input id="new-db-name" class="field-input font-mono" placeholder="e.g. analytics" autocomplete="off" spellcheck="false" />
15
+ </div>
16
+ {{#unless readonly}}
17
+ <button id="create-db" type="button" class="btn btn-primary btn-sm mb-0.5 gap-1.5">
18
+ <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="M12 4v16m8-8H4" /></svg>
19
+ Create
20
+ </button>
21
+ {{else}}
22
+ <span class="mb-1 text-sm font-medium text-warning">Read-only — creating databases is disabled.</span>
23
+ {{/unless}}
24
+ </div>
25
+ <p class="mt-2 text-xs text-base-content/40">
26
+ New databases are created in <code class="font-mono">{{dbDir}}</code>. Files already there are picked up
27
+ automatically, and any explicitly configured database paths appear here too.
28
+ </p>
29
+ </div>
30
+
31
+ <!-- List -->
32
+ <div>
33
+ <div class="mb-3 flex items-center justify-between">
34
+ <h2 class="text-lg font-bold">Available databases</h2>
35
+ <span class="text-sm text-base-content/45">{{databases.length}} total</span>
36
+ </div>
37
+
38
+ {{#if databases.length}}
39
+ <div class="app-card overflow-hidden">
40
+ <div class="overflow-x-auto">
41
+ <table class="table table-sm">
42
+ <thead>
43
+ <tr class="bg-base-200/70 text-xs uppercase tracking-wide text-base-content/50">
44
+ <th class="font-semibold">Name</th>
45
+ <th class="text-right font-semibold">Tables</th>
46
+ <th class="text-right font-semibold">Size</th>
47
+ <th class="font-semibold">Modified</th>
48
+ <th class="text-right font-semibold">Actions</th>
49
+ </tr>
50
+ </thead>
51
+ <tbody>
52
+ {{#each databases}}
53
+ <tr class="group hover:bg-primary/[0.04]">
54
+ <td>
55
+ <a href="{{../basePath}}/{{this.id}}" class="inline-flex items-center gap-2.5">
56
+ <span class="grid h-8 w-8 shrink-0 place-items-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary/20">
57
+ <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 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" /></svg>
58
+ </span>
59
+ <span class="min-w-0">
60
+ <span class="block truncate font-mono text-[13.5px] font-semibold">{{this.name}}</span>
61
+ <span class="block max-w-[220px] truncate text-[11px] text-base-content/40" title="{{this.path}}">{{this.path}}</span>
62
+ </span>
63
+ </a>
64
+ </td>
65
+ <td class="text-right tabular-nums text-base-content/60">{{this.tables}}</td>
66
+ <td class="text-right tabular-nums text-base-content/60">{{this.sizeLabel}}</td>
67
+ <td class="text-[13px] text-base-content/55">{{this.modifiedLabel}}</td>
68
+ <td class="whitespace-nowrap text-right">
69
+ <div class="row-actions">
70
+ <a href="{{../basePath}}/{{this.id}}" class="btn btn-ghost btn-xs gap-1 text-base-content/70 hover:text-primary">
71
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
72
+ Open
73
+ </a>
74
+ {{#unless ../readonly}}
75
+ <button type="button" class="btn btn-ghost btn-xs gap-1 text-error js-delete-db" data-id="{{this.id}}">
76
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /></svg>
77
+ Delete
78
+ </button>
79
+ {{/unless}}
80
+ </div>
81
+ </td>
82
+ </tr>
83
+ {{/each}}
84
+ </tbody>
85
+ </table>
86
+ </div>
87
+ </div>
88
+ {{else}}
89
+ <div class="empty-state">
90
+ <span class="empty-icon">
91
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><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" /></svg>
92
+ </span>
93
+ <p class="text-sm font-medium text-base-content/70">No databases yet</p>
94
+ <p class="max-w-sm text-sm text-base-content/45">
95
+ Create one above, or drop <code class="font-mono">.db</code> files into
96
+ <code class="font-mono">{{dbDir}}</code> and refresh.
97
+ </p>
98
+ </div>
99
+ {{/if}}
100
+ </div>
101
+ </div>
102
+ <script src="{{basePath}}/js/databases.js" defer></script>
@@ -1,81 +1,81 @@
1
- <div class="space-y-6">
2
- <!-- Header -->
3
- <div>
4
- <p class="text-sm font-semibold uppercase tracking-wider text-primary">Designer</p>
5
- <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Create table</h1>
6
- <p class="mt-1.5 text-sm text-base-content/55">Define columns visually — the SQL preview updates live as you type.</p>
7
- </div>
8
-
9
- <div class="grid gap-6 lg:grid-cols-[1fr_380px]">
10
- <!-- Left: editor -->
11
- <div class="space-y-5">
12
- <div class="app-card p-5">
13
- <label class="field-label">
14
- Table name
15
- <span class="chip chip-type">required</span>
16
- </label>
17
- <input id="table-name" type="text" class="field-input font-mono" placeholder="e.g. users" autocomplete="off" spellcheck="false" />
18
- </div>
19
-
20
- <div class="app-card">
21
- <div class="flex flex-wrap items-center justify-between gap-2 border-b border-base-200 px-5 py-4">
22
- <h2 class="text-sm font-semibold uppercase tracking-wide text-base-content/45">Columns</h2>
23
- <button id="add-column" type="button" class="btn btn-outline btn-sm gap-1.5">
24
- <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="M12 4v16m8-8H4" /></svg>
25
- Add column
26
- </button>
27
- </div>
28
- <div id="columns" class="space-y-3 p-4"></div>
29
- <div id="designer-error" class="hidden px-4 pb-4"></div>
30
- <div class="flex flex-wrap gap-2 border-t border-base-200 px-5 py-4">
31
- {{#unless readonly}}
32
- <button id="create-table" type="button" class="btn btn-primary gap-1.5">
33
- <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="M5 13l4 4L19 7" /></svg>
34
- Create table
35
- </button>
36
- {{else}}
37
- <span class="text-sm font-medium text-warning">Read-only — table creation is disabled.</span>
38
- {{/unless}}
39
- <button id="copy-sql" type="button" class="btn btn-outline gap-1.5" title="Copy the preview SQL">
40
- <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="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3" /></svg>
41
- Copy SQL
42
- </button>
43
- </div>
44
- </div>
45
- </div>
46
-
47
- <!-- Right: live preview + tips -->
48
- <aside class="space-y-4 self-start lg:sticky lg:top-24">
49
- <div class="app-card overflow-hidden">
50
- <div class="flex items-center justify-between border-b border-base-200 bg-base-200/40 px-4 py-3">
51
- <h2 class="flex items-center gap-2 text-sm font-semibold text-base-content/60">
52
- <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
53
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
54
- </span>
55
- SQL preview
56
- </h2>
57
- <span id="preview-status" class="text-[11px] font-medium text-base-content/40">waiting…</span>
58
- </div>
59
- <div class="p-4">
60
- <pre id="sql-preview" class="code-panel hidden"><code id="preview-code"></code></pre>
61
- <div id="preview-placeholder" class="rounded-xl border border-dashed border-base-300 px-4 py-8 text-center text-sm text-base-content/35">
62
- Your <code class="font-mono">CREATE TABLE</code> statement will appear here as you build it.
63
- </div>
64
- </div>
65
- </div>
66
-
67
- <div class="rounded-2xl border border-base-300/70 bg-base-100 p-4">
68
- <h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wider text-base-content/45">Type guide</h3>
69
- <ul class="space-y-1.5 text-[13px] text-base-content/60">
70
- <li class="flex items-center justify-between gap-2"><span class="font-mono">TEXT</span><span class="text-base-content/40">Free-form text</span></li>
71
- <li class="flex items-center justify-between gap-2"><span class="font-mono">INTEGER</span><span class="text-base-content/40">Whole numbers</span></li>
72
- <li class="flex items-center justify-between gap-2"><span class="font-mono">REAL</span><span class="text-base-content/40">Decimal numbers</span></li>
73
- <li class="flex items-center justify-between gap-2"><span class="font-mono">BLOB</span><span class="text-base-content/40">Binary data</span></li>
74
- <li class="flex items-center justify-between gap-2"><span class="font-mono">BOOLEAN</span><span class="text-base-content/40">Stored as 0/1</span></li>
75
- <li class="flex items-center justify-between gap-2"><span class="font-mono">DATE</span><span class="text-base-content/40">Datetime + now default</span></li>
76
- </ul>
77
- </div>
78
- </aside>
79
- </div>
80
- </div>
81
- <script src="{{basePath}}/js/designer.js" defer></script>
1
+ <div class="space-y-6">
2
+ <!-- Header -->
3
+ <div>
4
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary">Designer</p>
5
+ <h1 class="mt-1 text-3xl font-extrabold tracking-tight">Create table</h1>
6
+ <p class="mt-1.5 text-sm text-base-content/55">Define columns visually — the SQL preview updates live as you type.</p>
7
+ </div>
8
+
9
+ <div class="grid gap-6 lg:grid-cols-[1fr_380px]">
10
+ <!-- Left: editor -->
11
+ <div class="space-y-5">
12
+ <div class="app-card p-5">
13
+ <label class="field-label">
14
+ Table name
15
+ <span class="chip chip-type">required</span>
16
+ </label>
17
+ <input id="table-name" type="text" class="field-input font-mono" placeholder="e.g. users" autocomplete="off" spellcheck="false" />
18
+ </div>
19
+
20
+ <div class="app-card">
21
+ <div class="flex flex-wrap items-center justify-between gap-2 border-b border-base-200 px-5 py-4">
22
+ <h2 class="text-sm font-semibold uppercase tracking-wide text-base-content/45">Columns</h2>
23
+ <button id="add-column" type="button" class="btn btn-outline btn-sm gap-1.5">
24
+ <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="M12 4v16m8-8H4" /></svg>
25
+ Add column
26
+ </button>
27
+ </div>
28
+ <div id="columns" class="space-y-3 p-4"></div>
29
+ <div id="designer-error" class="hidden px-4 pb-4"></div>
30
+ <div class="flex flex-wrap gap-2 border-t border-base-200 px-5 py-4">
31
+ {{#unless readonly}}
32
+ <button id="create-table" type="button" class="btn btn-primary gap-1.5">
33
+ <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="M5 13l4 4L19 7" /></svg>
34
+ Create table
35
+ </button>
36
+ {{else}}
37
+ <span class="text-sm font-medium text-warning">Read-only — table creation is disabled.</span>
38
+ {{/unless}}
39
+ <button id="copy-sql" type="button" class="btn btn-outline gap-1.5" title="Copy the preview SQL">
40
+ <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="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3" /></svg>
41
+ Copy SQL
42
+ </button>
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ <!-- Right: live preview + tips -->
48
+ <aside class="space-y-4 self-start lg:sticky lg:top-24">
49
+ <div class="app-card overflow-hidden">
50
+ <div class="flex items-center justify-between border-b border-base-200 bg-base-200/40 px-4 py-3">
51
+ <h2 class="flex items-center gap-2 text-sm font-semibold text-base-content/60">
52
+ <span class="grid h-5 w-5 place-items-center rounded-md bg-primary/10 text-primary">
53
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
54
+ </span>
55
+ SQL preview
56
+ </h2>
57
+ <span id="preview-status" class="text-[11px] font-medium text-base-content/40">waiting…</span>
58
+ </div>
59
+ <div class="p-4">
60
+ <pre id="sql-preview" class="code-panel hidden"><code id="preview-code"></code></pre>
61
+ <div id="preview-placeholder" class="rounded-xl border border-dashed border-base-300 px-4 py-8 text-center text-sm text-base-content/35">
62
+ Your <code class="font-mono">CREATE TABLE</code> statement will appear here as you build it.
63
+ </div>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="rounded-2xl border border-base-300/70 bg-base-100 p-4">
68
+ <h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wider text-base-content/45">Type guide</h3>
69
+ <ul class="space-y-1.5 text-[13px] text-base-content/60">
70
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">TEXT</span><span class="text-base-content/40">Free-form text</span></li>
71
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">INTEGER</span><span class="text-base-content/40">Whole numbers</span></li>
72
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">REAL</span><span class="text-base-content/40">Decimal numbers</span></li>
73
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">BLOB</span><span class="text-base-content/40">Binary data</span></li>
74
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">BOOLEAN</span><span class="text-base-content/40">Stored as 0/1</span></li>
75
+ <li class="flex items-center justify-between gap-2"><span class="font-mono">DATE</span><span class="text-base-content/40">Datetime + now default</span></li>
76
+ </ul>
77
+ </div>
78
+ </aside>
79
+ </div>
80
+ </div>
81
+ <script src="{{basePath}}/js/designer.js" defer></script>
@@ -1,12 +1,12 @@
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
- <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
4
- <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 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" />
5
- </svg>
6
- </div>
7
- <div>
8
- <h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
9
- <p class="mt-2 text-base-content/60">{{error}}</p>
10
- </div>
11
- <a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
12
- </div>
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
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
4
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 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" />
5
+ </svg>
6
+ </div>
7
+ <div>
8
+ <h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
9
+ <p class="mt-2 text-base-content/60">{{error}}</p>
10
+ </div>
11
+ <a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
12
+ </div>