admindb 1.2.1 → 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.
Files changed (205) 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 +40 -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 +170 -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 +147 -62
  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 +4 -3
  131. package/dist/sql/generator.js +103 -6
  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 +33 -11
  159. package/dist/views/pages/databases.hbs +182 -74
  160. package/dist/views/pages/designer.hbs +9 -6
  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/package.json +11 -4
  173. package/dist/args.d.ts +0 -28
  174. package/dist/args.js +0 -187
  175. package/dist/args.js.map +0 -1
  176. package/dist/config.d.ts +0 -17
  177. package/dist/config.js +0 -23
  178. package/dist/config.js.map +0 -1
  179. package/dist/csv.js.map +0 -1
  180. package/dist/data/generator.d.ts +0 -86
  181. package/dist/data/generator.js +0 -1031
  182. package/dist/data/generator.js.map +0 -1
  183. package/dist/logger.js +0 -25
  184. package/dist/logger.js.map +0 -1
  185. package/dist/routes/api.d.ts +0 -9
  186. package/dist/routes/api.js +0 -848
  187. package/dist/routes/api.js.map +0 -1
  188. package/dist/test/classifier.test.d.ts +0 -1
  189. package/dist/test/classifier.test.js +0 -44
  190. package/dist/test/classifier.test.js.map +0 -1
  191. package/dist/test/csv.test.d.ts +0 -1
  192. package/dist/test/csv.test.js +0 -64
  193. package/dist/test/csv.test.js.map +0 -1
  194. package/dist/test/database.test.d.ts +0 -1
  195. package/dist/test/database.test.js +0 -402
  196. package/dist/test/database.test.js.map +0 -1
  197. package/dist/test/generator.test.d.ts +0 -1
  198. package/dist/test/generator.test.js +0 -132
  199. package/dist/test/generator.test.js.map +0 -1
  200. package/dist/test/manager.test.d.ts +0 -1
  201. package/dist/test/manager.test.js +0 -146
  202. package/dist/test/manager.test.js.map +0 -1
  203. package/dist/util.js.map +0 -1
  204. /package/dist/{csv.d.ts → utils/csv.d.ts} +0 -0
  205. /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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "admindb",
3
- "version": "1.2.1",
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": "npm run build && node --test dist/test/*.test.js"
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,12 +55,14 @@
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
67
  "cross-env": "^7.0.3",
61
68
  "daisyui": "^4.12.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":";;;;;AAiCA,4BAyCC;AAaD,8CAEC;AAED,kCAGC;AAOD,8BAoFC;AAzLD;;;;;;GAMG;AACH,qCAA6D;AAC7D,0DAA6B;AAG7B,MAAM,UAAU,GAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAsBlE,SAAgB,QAAQ;IACtB,OAAO;QACL,qDAAqD;QACrD,EAAE;QACF,QAAQ;QACR,4BAA4B;QAC5B,EAAE;QACF,2EAA2E;QAC3E,qDAAqD;QACrD,EAAE;QACF,0EAA0E;QAC1E,2EAA2E;QAC3E,EAAE;QACF,YAAY;QACZ,4EAA4E;QAC5E,uEAAuE;QACvE,2CAA2C;QAC3C,EAAE;QACF,UAAU;QACV,2DAA2D;QAC3D,mEAAmE;QACnE,qDAAqD;QACrD,4DAA4D;QAC5D,6DAA6D;QAC7D,gEAAgE;QAChE,wEAAwE;QACxE,qEAAqE;QACrE,wCAAwC;QACxC,0CAA0C;QAC1C,EAAE;QACF,mEAAmE;QACnE,yEAAyE;QACzE,EAAE;QACF,WAAW;QACX,0EAA0E;QAC1E,yDAAyD;QACzD,kEAAkE;QAClE,2DAA2D;QAC3D,mEAAmE;QACnE,+DAA+D;KAChE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,sBAAY,EAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACpD,OAAO,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,uFAAuF;AACvF,SAAgB,iBAAiB;IAC/B,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC;AAED,SAAgB,WAAW;IACzB,MAAM,CAAC,GAAG,cAAc,EAAE,CAAC;IAC3B,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACzC,CAAC;AAED,4EAA4E;AAC5E,SAAS,MAAM,CAAC,GAAW,EAAE,GAAG,KAAe;IAC7C,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,SAAgB,SAAS,CAAC,IAAc;IACtC,MAAM,IAAI,GAAY,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACvE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,MAAM,OAAO,GAAG,CAAC,KAAa,EAAqC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAExF,yEAAyE;IACzE,yEAAyE;IACzE,mBAAmB;IACnB,MAAM,SAAS,GAAG,CAAC,IAAY,EAAsB,EAAE;QACrD,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5C,CAAC,IAAI,CAAC,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,2BAA2B,CAAC,CAAC;YACjE,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC3E,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAChB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,2BAA2B,CAAC,CAAC;YACjE,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAChB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC/D,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,2BAA2B,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,0BAA0B,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;YAC/B,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,4BAA4B,CAAC,CAAC;YAClE,IAAI,CAAC,OAAO,GAAG,CAAC;iBACb,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC;YACtD,MAAM,CAAC,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;YACnC,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,gCAAgC,CAAC,CAAC;YACtE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,CAAC;YAC5C,MAAM,CAAC,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;YACnC,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,gCAAgC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAa,CAAC,EAAE,CAAC;gBACxC,OAAO,OAAO,CAAC,uBAAuB,CAAC,uBAAuB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1F,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,CAAa,CAAC;QAChC,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YAChD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC,+BAA+B,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,GAAG,GAAG,mBAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC;YACH,IAAI,IAAA,kBAAQ,EAAC,GAAG,CAAC,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;;gBAC3C,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
package/dist/config.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { LogLevel } from './logger';
2
- export interface Config {
3
- host: string;
4
- port: number;
5
- /** Single-database file (used when no multi-db sources are configured). */
6
- dbPath: string;
7
- /** Directory of managed database files (multi-db mode source 1). */
8
- dbDir?: string;
9
- /** Explicit database file locations (multi-db mode source 2). */
10
- dbFiles?: string[];
11
- basePath: string;
12
- logLevel: LogLevel;
13
- /** Open the database read-only (writes disabled). */
14
- readonly: boolean;
15
- }
16
- /** Load configuration from environment variables with sensible defaults. */
17
- export declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
package/dist/config.js DELETED
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadConfig = loadConfig;
4
- /** Load configuration from environment variables with sensible defaults. */
5
- function loadConfig(env = process.env) {
6
- const port = Number.parseInt(env.PORT ?? '3000', 10);
7
- return {
8
- host: env.HOST ?? '0.0.0.0',
9
- port: Number.isFinite(port) ? port : 3000,
10
- dbPath: env.DB_PATH ?? 'admindb.db',
11
- dbDir: env.DB_DIR ? String(env.DB_DIR) : undefined,
12
- dbFiles: env.DB_FILES
13
- ? String(env.DB_FILES)
14
- .split(',')
15
- .map((s) => s.trim())
16
- .filter(Boolean)
17
- : undefined,
18
- basePath: (env.BASE_PATH ?? '').replace(/\/+$/, ''),
19
- logLevel: (env.LOG_LEVEL ?? 'info'),
20
- readonly: ['1', 'true', 'yes', 'on'].includes(String(env.READONLY ?? '').trim().toLowerCase()),
21
- };
22
- }
23
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;AAkBA,gCAiBC;AAlBD,4EAA4E;AAC5E,SAAgB,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,SAAS;QAC3B,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACzC,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,YAAY;QACnC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAClD,OAAO,EAAE,GAAG,CAAC,QAAQ;YACnB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;iBACjB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,OAAO,CAAC;YACpB,CAAC,CAAC,SAAS;QACb,QAAQ,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACnD,QAAQ,EAAE,CAAE,GAAG,CAAC,SAAsB,IAAI,MAAM,CAAC;QACjD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;KAC/F,CAAC;AACJ,CAAC"}
package/dist/csv.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"csv.js","sourceRoot":"","sources":["../src/csv.ts"],"names":[],"mappings":"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"}
@@ -1,86 +0,0 @@
1
- /**
2
- * Data generator / seeder engine.
3
- *
4
- * Given a table's schema, every column can be filled with realistic fake data
5
- * from a chosen "strategy" — first name, email, UUID, a random integer, a value
6
- * sampled from a referenced table's foreign key, a fixed value, and so on.
7
- *
8
- * Responsibilities:
9
- * - auto-detect a sensible default strategy per column (column name + type +
10
- * foreign key), so the "Seed data" page works with zero configuration;
11
- * - generate N rows of concrete, type-coerced values (ready for SQLite
12
- * binding via `db.insertRows`);
13
- * - render the generated rows as a multi-row INSERT for the "preview SQL"
14
- * mode that never executes.
15
- */
16
- import type { SqliteDatabase, TableInfoData, ForeignKeyInfo, WhereClause } from '../db/database';
17
- /** Hard cap on how many rows a single seed run may generate. */
18
- export declare const MAX_SEED_ROWS = 5000;
19
- export type GeneratorStrategyId = 'skip' | 'null' | 'fixed' | 'list' | 'first' | 'last' | 'fullname' | 'email' | 'username' | 'phone' | 'city' | 'country' | 'postal' | 'address' | 'url' | 'domain' | 'ip' | 'uuid' | 'words' | 'sentence' | 'int' | 'decimal' | 'date' | 'datetime' | 'time' | 'bool' | 'bytes' | 'json' | 'hash' | 'token' | 'fk';
20
- /** Per-column generator settings. Which options are meaningful depends on `strategy`. */
21
- export interface ColumnPlan {
22
- strategy: GeneratorStrategyId;
23
- /** `fixed` / `list` and the string-ish options. */
24
- value?: string;
25
- /** `list` — random value picked from this set. */
26
- values?: string[];
27
- /** `int` / `decimal` range. */
28
- min?: number;
29
- max?: number;
30
- /** `decimal` — digits after the decimal point. */
31
- precision?: number;
32
- /** `date` / `datetime` bounds (ISO strings). */
33
- from?: string;
34
- to?: string;
35
- /** `words` / `bytes` / `hash` / `token` — length bounds. */
36
- minLen?: number;
37
- maxLen?: number;
38
- /** `json` — object keys to include (comma-separated in the UI). */
39
- jsonKeys?: string[];
40
- /** `json` — per-key allowed values, derived from CHECK constraints. */
41
- jsonValues?: Record<string, string[]>;
42
- }
43
- /** A strategy choice offered to the UI for a column. */
44
- export interface StrategyDescriptor {
45
- id: GeneratorStrategyId;
46
- label: string;
47
- }
48
- /** Everything the "Seed data" page needs to render one column's controls. */
49
- export interface ColumnGeneratorConfig {
50
- name: string;
51
- type: string;
52
- pk: boolean;
53
- notnull: boolean;
54
- hasDefault: boolean;
55
- /** True when a single-column UNIQUE index enforces uniqueness on this column. */
56
- unique: boolean;
57
- /** The foreign key this column participates in (as the child), if any. */
58
- fk: ForeignKeyInfo | null;
59
- strategies: StrategyDescriptor[];
60
- defaultPlan: ColumnPlan;
61
- }
62
- export interface GenerateResult {
63
- /** One entry per generated row: the columns/values to bind (skipped columns are absent). */
64
- rows: WhereClause[][];
65
- /** Non-fatal notes surfaced to the user (e.g. a NOT NULL column being skipped). */
66
- warnings: string[];
67
- }
68
- /**
69
- * Compute per-column generator configuration for a table (default strategies,
70
- * available strategies, FK metadata). Pure — no DB access — so the page route
71
- * and the API can share it.
72
- */
73
- export declare function buildColumnConfigs(info: TableInfoData): ColumnGeneratorConfig[];
74
- /**
75
- * Validate/normalize a client-supplied per-column plan. Returns null when the
76
- * payload is not a usable plan. Strategy validity against the column's allowed
77
- * set is enforced later by `generateRows`.
78
- */
79
- export declare function sanitizeColumnPlan(raw: unknown): ColumnPlan | null;
80
- export declare function generateRows(db: SqliteDatabase, info: TableInfoData, configs: ColumnGeneratorConfig[], count: number, plan?: Record<string, ColumnPlan>): Promise<GenerateResult>;
81
- /**
82
- * Render generated rows as a sequence of INSERT statements for preview
83
- * ("generate but never execute"). Each row is its own statement so per-row
84
- * column lists (with skips) stay valid.
85
- */
86
- export declare function buildSeedInsertSql(table: string, rows: WhereClause[][]): string;