admindb 1.2.1 → 2.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 (208) hide show
  1. package/README.md +262 -329
  2. package/dist/app.d.ts +25 -4
  3. package/dist/app.js +79 -15
  4. package/dist/app.js.map +1 -1
  5. package/dist/auth/config.d.ts +19 -0
  6. package/dist/auth/config.js +147 -0
  7. package/dist/auth/config.js.map +1 -0
  8. package/dist/auth/crypto.d.ts +27 -0
  9. package/dist/auth/crypto.js +133 -0
  10. package/dist/auth/crypto.js.map +1 -0
  11. package/dist/auth/index.d.ts +5 -0
  12. package/dist/auth/index.js +22 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/middleware.d.ts +14 -0
  15. package/dist/auth/middleware.js +100 -0
  16. package/dist/auth/middleware.js.map +1 -0
  17. package/dist/auth/routes.d.ts +7 -0
  18. package/dist/auth/routes.js +78 -0
  19. package/dist/auth/routes.js.map +1 -0
  20. package/dist/auth/types.d.ts +35 -0
  21. package/dist/auth/types.js +11 -0
  22. package/dist/auth/types.js.map +1 -0
  23. package/dist/cli/args.d.ts +45 -0
  24. package/dist/cli/args.js +328 -0
  25. package/dist/cli/args.js.map +1 -0
  26. package/dist/cli/config.d.ts +56 -0
  27. package/dist/cli/config.js +133 -0
  28. package/dist/cli/config.js.map +1 -0
  29. package/dist/cli/index.d.ts +4 -0
  30. package/dist/cli/index.js +21 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/runner.d.ts +1 -0
  33. package/dist/cli/runner.js +222 -0
  34. package/dist/cli/runner.js.map +1 -0
  35. package/dist/cli.js +2 -127
  36. package/dist/cli.js.map +1 -1
  37. package/dist/data/datasets.d.ts +17 -0
  38. package/dist/data/datasets.js +133 -0
  39. package/dist/data/datasets.js.map +1 -0
  40. package/dist/data/detector.d.ts +30 -0
  41. package/dist/data/detector.js +472 -0
  42. package/dist/data/detector.js.map +1 -0
  43. package/dist/data/engine.d.ts +10 -0
  44. package/dist/data/engine.js +211 -0
  45. package/dist/data/engine.js.map +1 -0
  46. package/dist/data/index.d.ts +5 -0
  47. package/dist/data/index.js +22 -0
  48. package/dist/data/index.js.map +1 -0
  49. package/dist/data/strategies.d.ts +30 -0
  50. package/dist/data/strategies.js +343 -0
  51. package/dist/data/strategies.js.map +1 -0
  52. package/dist/data/types.d.ts +73 -0
  53. package/dist/data/types.js +8 -0
  54. package/dist/data/types.js.map +1 -0
  55. package/dist/db/database.d.ts +14 -146
  56. package/dist/db/database.js +208 -461
  57. package/dist/db/database.js.map +1 -1
  58. package/dist/db/export.d.ts +2 -2
  59. package/dist/db/export.js +7 -2
  60. package/dist/db/export.js.map +1 -1
  61. package/dist/db/filters.d.ts +22 -0
  62. package/dist/db/filters.js +158 -0
  63. package/dist/db/filters.js.map +1 -0
  64. package/dist/db/index.d.ts +8 -0
  65. package/dist/db/index.js +25 -0
  66. package/dist/db/index.js.map +1 -0
  67. package/dist/db/introspection.d.ts +6 -0
  68. package/dist/db/introspection.js +172 -0
  69. package/dist/db/introspection.js.map +1 -0
  70. package/dist/db/manager.d.ts +32 -19
  71. package/dist/db/manager.js +203 -44
  72. package/dist/db/manager.js.map +1 -1
  73. package/dist/db/migrations.d.ts +5 -0
  74. package/dist/db/migrations.js +110 -0
  75. package/dist/db/migrations.js.map +1 -0
  76. package/dist/db/postgres.d.ts +85 -0
  77. package/dist/db/postgres.js +745 -0
  78. package/dist/db/postgres.js.map +1 -0
  79. package/dist/db/types.d.ts +206 -0
  80. package/dist/db/types.js +7 -0
  81. package/dist/db/types.js.map +1 -0
  82. package/dist/index.d.ts +9 -2
  83. package/dist/index.js +46 -4
  84. package/dist/index.js.map +1 -1
  85. package/dist/public/css/app.css +1 -1
  86. package/dist/public/css/input.css +74 -11
  87. package/dist/public/js/app.js +142 -0
  88. package/dist/public/js/browse.js +591 -104
  89. package/dist/public/js/databases.js +105 -13
  90. package/dist/public/js/designer.js +55 -2
  91. package/dist/public/js/forms.js +610 -28
  92. package/dist/public/js/icons.js +51 -0
  93. package/dist/public/js/inspector.js +638 -0
  94. package/dist/public/js/query.js +93 -3
  95. package/dist/public/js/schema.js +185 -52
  96. package/dist/public/js/seed.js +865 -152
  97. package/dist/routes/api/helpers.d.ts +42 -0
  98. package/dist/routes/api/helpers.js +133 -0
  99. package/dist/routes/api/helpers.js.map +1 -0
  100. package/dist/routes/api/import-export.d.ts +3 -0
  101. package/dist/routes/api/import-export.js +85 -0
  102. package/dist/routes/api/import-export.js.map +1 -0
  103. package/dist/routes/api/index.d.ts +4 -0
  104. package/dist/routes/api/index.js +37 -0
  105. package/dist/routes/api/index.js.map +1 -0
  106. package/dist/routes/api/query.d.ts +3 -0
  107. package/dist/routes/api/query.js +76 -0
  108. package/dist/routes/api/query.js.map +1 -0
  109. package/dist/routes/api/rows.d.ts +3 -0
  110. package/dist/routes/api/rows.js +373 -0
  111. package/dist/routes/api/rows.js.map +1 -0
  112. package/dist/routes/api/seed.d.ts +3 -0
  113. package/dist/routes/api/seed.js +82 -0
  114. package/dist/routes/api/seed.js.map +1 -0
  115. package/dist/routes/api/tables.d.ts +3 -0
  116. package/dist/routes/api/tables.js +160 -0
  117. package/dist/routes/api/tables.js.map +1 -0
  118. package/dist/routes/databases.d.ts +8 -11
  119. package/dist/routes/databases.js +100 -66
  120. package/dist/routes/databases.js.map +1 -1
  121. package/dist/routes/index.d.ts +3 -0
  122. package/dist/routes/index.js +20 -0
  123. package/dist/routes/index.js.map +1 -0
  124. package/dist/routes/pages.d.ts +3 -3
  125. package/dist/routes/pages.js +157 -64
  126. package/dist/routes/pages.js.map +1 -1
  127. package/dist/serverless.d.ts +40 -0
  128. package/dist/serverless.js +210 -0
  129. package/dist/serverless.js.map +1 -0
  130. package/dist/sql/generator.d.ts +7 -3
  131. package/dist/sql/generator.js +144 -7
  132. package/dist/sql/generator.js.map +1 -1
  133. package/dist/sql/index.d.ts +2 -0
  134. package/dist/sql/index.js +19 -0
  135. package/dist/sql/index.js.map +1 -0
  136. package/dist/types/api.d.ts +412 -0
  137. package/dist/types/api.js +9 -0
  138. package/dist/types/api.js.map +1 -0
  139. package/dist/utils/colors.d.ts +40 -0
  140. package/dist/utils/colors.js +64 -0
  141. package/dist/utils/colors.js.map +1 -0
  142. package/dist/{util.d.ts → utils/common.d.ts} +10 -6
  143. package/dist/{util.js → utils/common.js} +80 -13
  144. package/dist/utils/common.js.map +1 -0
  145. package/dist/utils/csv.js.map +1 -0
  146. package/dist/utils/datatype.d.ts +49 -0
  147. package/dist/utils/datatype.js +222 -0
  148. package/dist/utils/datatype.js.map +1 -0
  149. package/dist/utils/icons.d.ts +11 -0
  150. package/dist/utils/icons.js +72 -0
  151. package/dist/utils/icons.js.map +1 -0
  152. package/dist/utils/index.d.ts +4 -0
  153. package/dist/utils/index.js +21 -0
  154. package/dist/utils/index.js.map +1 -0
  155. package/dist/{logger.d.ts → utils/logger.d.ts} +1 -1
  156. package/dist/utils/logger.js +40 -0
  157. package/dist/utils/logger.js.map +1 -0
  158. package/dist/views/layouts/main.hbs +40 -11
  159. package/dist/views/pages/databases.hbs +182 -74
  160. package/dist/views/pages/designer.hbs +29 -11
  161. package/dist/views/pages/error.hbs +3 -3
  162. package/dist/views/pages/form.hbs +5 -3
  163. package/dist/views/pages/home.hbs +22 -13
  164. package/dist/views/pages/login.hbs +111 -0
  165. package/dist/views/pages/query.hbs +8 -6
  166. package/dist/views/pages/schema.hbs +41 -13
  167. package/dist/views/pages/seed.hbs +200 -54
  168. package/dist/views/pages/table.hbs +152 -72
  169. package/dist/views/partials/icon.hbs +2 -0
  170. package/dist/views/partials/navbar.hbs +69 -25
  171. package/dist/views/partials/sidebar.hbs +108 -94
  172. package/docs/API.md +144 -0
  173. package/docs/EXAMPLES.md +576 -0
  174. package/docs/SECURITY.md +265 -0
  175. package/package.json +15 -4
  176. package/dist/args.d.ts +0 -28
  177. package/dist/args.js +0 -187
  178. package/dist/args.js.map +0 -1
  179. package/dist/config.d.ts +0 -17
  180. package/dist/config.js +0 -23
  181. package/dist/config.js.map +0 -1
  182. package/dist/csv.js.map +0 -1
  183. package/dist/data/generator.d.ts +0 -86
  184. package/dist/data/generator.js +0 -1031
  185. package/dist/data/generator.js.map +0 -1
  186. package/dist/logger.js +0 -25
  187. package/dist/logger.js.map +0 -1
  188. package/dist/routes/api.d.ts +0 -9
  189. package/dist/routes/api.js +0 -848
  190. package/dist/routes/api.js.map +0 -1
  191. package/dist/test/classifier.test.d.ts +0 -1
  192. package/dist/test/classifier.test.js +0 -44
  193. package/dist/test/classifier.test.js.map +0 -1
  194. package/dist/test/csv.test.d.ts +0 -1
  195. package/dist/test/csv.test.js +0 -64
  196. package/dist/test/csv.test.js.map +0 -1
  197. package/dist/test/database.test.d.ts +0 -1
  198. package/dist/test/database.test.js +0 -402
  199. package/dist/test/database.test.js.map +0 -1
  200. package/dist/test/generator.test.d.ts +0 -1
  201. package/dist/test/generator.test.js +0 -132
  202. package/dist/test/generator.test.js.map +0 -1
  203. package/dist/test/manager.test.d.ts +0 -1
  204. package/dist/test/manager.test.js +0 -146
  205. package/dist/test/manager.test.js.map +0 -1
  206. package/dist/util.js.map +0 -1
  207. /package/dist/{csv.d.ts → utils/csv.d.ts} +0 -0
  208. /package/dist/{csv.js → utils/csv.js} +0 -0
@@ -1,111 +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
- <div>
4
- <div class="text-base font-bold leading-tight">AdminDB <span style="font-size: x-small">{{#if version}} v{{version}}{{/if}}</span></div>
5
- <div class="text-[11px] text-neutral-content/50">{{#if databasesMode}}Database manager{{else}}Database: {{dbId}}{{/if}}</div>
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>
6
17
  </div>
7
18
  </div>
8
19
 
9
20
  {{#if databasesMode}}
10
- <nav class="flex-1 overflow-y-auto px-3 py-2">
11
- <ul class="space-y-0.5">
12
- <li>
13
- <a href="{{basePath}}/" class="side-link active">
14
- <svg xmlns="http://www.w3.org/2000/svg" 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>
15
- Databases
16
- </a>
17
- </li>
18
- </ul>
19
- </nav>
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>
20
31
  {{else}}
21
- <div class="px-4 pb-2">
22
- <label class="relative block">
23
- <svg xmlns="http://www.w3.org/2000/svg" class="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-neutral-content/40" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
24
- <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
25
- </svg>
26
- <input id="table-search" type="search" placeholder="Filter tables…" autocomplete="off"
27
- 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" />
28
- </label>
29
- </div>
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>
30
41
 
31
- <nav class="flex-1 overflow-y-auto px-3 py-2">
32
- <ul class="space-y-0.5">
33
- {{#if databasesUrl}}
34
- <li>
35
- <a href="{{databasesUrl}}" class="side-link">
36
- <svg xmlns="http://www.w3.org/2000/svg" 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>
37
- Databases
38
- </a>
39
- </li>
40
- {{/if}}
41
- <li>
42
- <a href="{{basePath}}/" class="side-link {{#if (eq currentPath '/')}}active{{/if}}">
43
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" /></svg>
44
- Home
45
- </a>
46
- </li>
47
- <li>
48
- <a href="{{basePath}}/query" class="side-link {{#if (startsWith currentPath '/query')}}active{{/if}}">
49
- <svg xmlns="http://www.w3.org/2000/svg" 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>
50
- Query editor
51
- </a>
52
- </li>
53
- {{#unless readonly}}
54
- <li>
55
- <a href="{{basePath}}/designer" class="side-link {{#if (startsWith currentPath '/designer')}}active{{/if}}">
56
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" /></svg>
57
- New table
58
- </a>
59
- </li>
60
- {{/unless}}
61
- </ul>
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>
62
73
 
63
- <div class="mb-2 mt-6 flex items-center justify-between px-3">
64
- <span class="text-[11px] font-semibold uppercase tracking-wider text-neutral-content/40">Tables</span>
65
- <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>
66
- </div>
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>
67
78
 
68
- <ul id="table-list" class="space-y-0.5">
69
- {{#each tables}}
70
- <li class="table-item" data-name="{{this}}">
71
- <a href="{{../basePath}}/tables/{{this}}" class="side-link {{#if (eq ../currentTable this)}}active{{/if}}">
72
- <span class="table-icon">
73
- <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="M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
74
- </span>
75
- <span class="truncate">{{this}}</span>
76
- </a>
77
- </li>
78
- {{else}}
79
- <li class="px-3 py-2 text-xs text-neutral-content/40">No tables yet</li>
80
- {{/each}}
81
- </ul>
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>
82
93
 
83
- {{#if internalTables.length}}
84
- <div class="mb-2 mt-6 px-3 text-[11px] font-semibold uppercase tracking-wider text-neutral-content/40">Internal</div>
85
- <ul class="space-y-0.5">
86
- {{#each internalTables}}
87
- <li>
88
- <a href="{{../basePath}}/tables/{{this}}" class="side-link {{#if (eq ../currentTable this)}}active{{/if}}">
89
- <span class="table-icon">
90
- <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 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /></svg>
91
- </span>
92
- <span class="truncate">{{this}}</span>
93
- </a>
94
- </li>
95
- {{/each}}
96
- </ul>
97
- {{/if}}
98
- </nav>
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>
99
110
  {{/if}}
100
111
 
101
112
  <div class="border-t border-white/10 px-5 py-3">
102
- <div class="text-[11px] font-medium uppercase tracking-wider text-neutral-content/40">{{#if databasesMode}}Directory{{else}}Database{{/if}}</div>
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>
103
123
  <div class="mt-0.5 truncate font-mono text-[11px] text-neutral-content/60" title="{{dbPath}}">{{dbPath}}</div>
104
- {{#if readonly}}
105
- <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">
106
- <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>
107
- Read-only
108
- </div>
109
- {{/if}}
110
124
  </div>
111
125
  </aside>
package/docs/API.md ADDED
@@ -0,0 +1,144 @@
1
+ # AdminDB REST API
2
+
3
+ Every route is under `basePath` and returns the consistent shape
4
+ `{ success, data?, error? }`. In multi-db mode, every route is scoped under the
5
+ database identifier, e.g. `/api/app.db/tables` or `/api/prod_pg/tables`.
6
+
7
+ AdminDB supports both **SQLite** and **PostgreSQL** database backends seamlessly.
8
+
9
+ ## Tables & rows
10
+
11
+ | Method | Path | Purpose |
12
+ | ------ | ---------------------------------------- | -------------------------------- |
13
+ | GET | `/api/tables` | List tables |
14
+ | GET | `/api/tables/:table/info` | Column + FK metadata, PK columns |
15
+ | GET | `/api/tables/:table/fk-options` | Values for FK dropdowns |
16
+ | GET | `/api/tables/:table/rows?page&limit&f` | Paginated rows (`f` = URL-encoded JSON filters — legacy strings like `{"age":">35"}` or structured conditions like `{"balance":{"op":"gte","value":"100"}}`) |
17
+ | GET | `/api/tables/:table/rows/count?f=` | Filtered row count |
18
+ | GET | `/api/tables/:table/row/:id` | Single row by (encoded) PK |
19
+ | GET | `/api/tables/:table/rows/:id/references` | Rows in other tables whose foreign keys reference this row |
20
+ | GET | `/api/tables/:table/row/:id/blob/:column` | Stream binary BLOB / BYTEA with MIME detection (add `?download=1` to force download) |
21
+ | GET | `/api/tables/:table/row/:id/blob/:column/meta` | Inspect BLOB / BYTEA metadata, MIME sniffing & 3-column hex dump |
22
+ | PUT | `/api/tables/:table/row/:id/blob/:column` | Update binary value (`{ data: base64/hex, format?: 'base64'|'hex'|'text' }`) |
23
+ | POST | `/api/tables/:table/rows` | Insert row (or batch of rows with `{ rows: [...] }`) |
24
+ | POST | `/api/tables/:table/rows/generate` | Generate INSERT SQL (no execute) |
25
+ | POST | `/api/tables/:table/rows/import` | Import CSV (`{ csv }`, header row must match columns) |
26
+ | GET | `/api/tables/:table/export?format=` | Download all rows as `csv` or `json` |
27
+ | PUT | `/api/tables/:table/row/:id` | Update row (`{ values, nulls? }` — `nulls` explicitly sets columns to NULL) |
28
+ | PUT | `/api/tables/:table/row/:id/generate` | Generate UPDATE SQL (no execute) |
29
+ | DELETE | `/api/tables/:table/row/:id` | Delete row |
30
+ | POST | `/api/tables/:table/rows/bulk-impact` | FK-impact preview: how many rows in other tables reference the selected rows |
31
+ | POST | `/api/tables/:table/rows/bulk-delete` | Delete selected rows (`{ ids, confirmImpact }`; transactional) |
32
+ | POST | `/api/tables/:table/rows/bulk-export` | Export only the selected rows as `csv`/`json` (`{ ids, format }`) |
33
+ | POST | `/api/tables/:table/rows/bulk-update` | Apply staged inline edits (`{ updates: [{ id, values?, nulls? }] }`; transactional) |
34
+ | GET | `/api/tables/:table/seed/config` | Per-column generator strategies + detected defaults |
35
+ | GET | `/api/tables/:table/seed/plan` | Detect intelligent seed plan heuristics |
36
+ | POST | `/api/tables/:table/seed/preview` | Generate preview sample rows for grid without executing |
37
+ | POST | `/api/tables/:table/seed/generate` | Generate seed INSERT SQL without executing (`{ count, plan }`) |
38
+ | POST | `/api/tables/:table/seed` | Generate and insert seed rows transactionally (`{ count, plan, truncate? }`) |
39
+
40
+ ## Schema & indexes
41
+
42
+ | Method | Path | Purpose |
43
+ | ------ | ------------------------------------ | -------------------------------- |
44
+ | POST | `/api/tables` | Create table |
45
+ | POST | `/api/tables/generate` | Generate CREATE SQL (no execute) |
46
+ | GET | `/api/tables/:table/schema` | Full schema (constraints, indexes, FK refs) |
47
+ | GET | `/api/tables/:table/ddl` | Get formatted `CREATE TABLE` and `INDEX` DDL |
48
+
49
+ | POST | `/api/tables/:table/rename` | Rename the table |
50
+ | POST | `/api/tables/:table/columns` | Add a column |
51
+ | PUT | `/api/tables/:table/columns/:column` | Modify/rename a column |
52
+ | DELETE | `/api/tables/:table/columns/:column` | Drop a column (safety-checked) |
53
+ | DELETE | `/api/tables/:table` | Drop the table (safety-checked) |
54
+ | POST | `/api/tables/:table/indexes` | Create an index (`{ name?, columns[], unique? }`) |
55
+ | DELETE | `/api/tables/:table/indexes/:index` | Drop an index (auto indexes refused) |
56
+
57
+ ## Queries
58
+
59
+ | Method | Path | Purpose |
60
+ | ------ | ----------------- | -------------------------- |
61
+ | POST | `/api/query` | Run arbitrary SQL |
62
+ | POST | `/api/query/export` | Run a SELECT and download as `csv`/`json` |
63
+ | GET | `/api/queries` | List saved queries |
64
+ | POST | `/api/queries` | Save a named query |
65
+ | DELETE | `/api/queries/:id`| Delete a saved query |
66
+
67
+ ## Manager mode (databases landing page)
68
+
69
+ These endpoints manage database files and power the filesystem browser:
70
+
71
+ | Method | Path | Purpose |
72
+ | ------ | ------------------------------- | ------------------------------------------- |
73
+ | GET | `/api/databases` | List managed databases |
74
+ | POST | `/api/databases` | Create a new SQLite database (`{ name }`) |
75
+ | POST | `/api/databases/connect-postgres` | Connect a PostgreSQL database (`{ name?, connectionString, readonly? }`) |
76
+ | POST | `/api/databases/:id/mode` | Toggle/set database mode (`{ readonly: boolean }`) |
77
+ | DELETE | `/api/databases/:id` | Delete SQLite database file or disconnect PostgreSQL connection |
78
+ | GET | `/api/fs/list?path=` | List subfolders + SQLite files under a path (sandboxed file browser) |
79
+ | POST | `/api/databases/open` | Open/register an existing database file by path (`{ path, readonly? }`) |
80
+
81
+ ## Authentication & Sessions
82
+
83
+ | Method | Path | Purpose |
84
+ | ------ | --------------------- | ------------------------------------------- |
85
+ | GET | `/login` | Web UI login page |
86
+ | POST | `/login` | Authenticate with `{ username, password }` and get session token |
87
+ | POST | `/logout` | Terminate session and clear cookie |
88
+ | GET | `/logout` | Terminate session and redirect to `/login` |
89
+
90
+ All API endpoints accept:
91
+ - **HTTP Basic Auth**: `Authorization: Basic <base64(username:password)>`
92
+ - **Bearer Token**: `Authorization: Bearer <sessionToken>`
93
+ - **Session Cookie**: `admindb_session=<sessionToken>`
94
+
95
+ ### Generating Password Hashes
96
+ Generate salted `scrypt` password hashes for custom credentials:
97
+ ```bash
98
+ npm run generatehash
99
+ # Enter password -> outputs scrypt:<salt>:<hash>
100
+ ```
101
+
102
+ Paste the generated hash into `ADMINDB_PASSWORD`, CLI `-P`, or `auth.password` option.
103
+
104
+ ### Disabling Native Authentication & Custom Application Auth
105
+ Pass `auth: false`, CLI `--no-auth`, or `ADMINDB_AUTH=false` to turn off built-in authentication when integrating your own security layer.
106
+
107
+ > [!WARNING]
108
+ > **Security & Responsibility Notice**:
109
+ > AdminDB's built-in authentication is designed for basic access control during local development. For production environments and internet-facing networks, **it is entirely the user's responsibility to protect AdminDB** by placing it behind your own application authentication (e.g. NextAuth, Passport, JWT, SSO/OAuth middleware), a VPN, an IP-allowlist reverse proxy (Nginx, Cloudflare Access), or HTTPS with rate limiting.
110
+
111
+
112
+ ## TypeScript API Types & Helpers
113
+
114
+ All request and response types, data inspection helpers, and serverless handlers are exported by the package entry point:
115
+
116
+ ```ts
117
+ import {
118
+ createRouter,
119
+ createServerlessHandler,
120
+ createLambdaHandler,
121
+ sniffMimeType,
122
+ generateHexDump,
123
+ analyzeBlob,
124
+ isJsonString,
125
+ formatJsonSafely,
126
+ type ApiResponse,
127
+ type GetRowsResponseData,
128
+ type BlobMetaResponseData,
129
+ type TableDdlResponseData,
130
+ } from 'admindb';
131
+
132
+ // 1. Sniff MIME type from binary magic bytes
133
+ const analysis = sniffMimeType(imageBuffer);
134
+ console.log(analysis.mime, analysis.ext, analysis.isImage);
135
+
136
+ // 2. Generate a 3-column hex dump
137
+ const dump = generateHexDump(binaryBuffer, 1024);
138
+ dump.lines.forEach((l) => console.log(`${l.offset} ${l.hex} |${l.ascii}|`));
139
+
140
+ // 3. Serverless request handler (Vercel, AWS Lambda, Cloudflare, etc.)
141
+ export default createServerlessHandler({ dbPath: './app.db' });
142
+ ```
143
+
144
+