admindb 2.4.1 → 2.6.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 (170) hide show
  1. package/LICENSE +20 -20
  2. package/dist/app.js +48 -25
  3. package/dist/core/context.d.ts +1 -0
  4. package/dist/core/context.js +2 -0
  5. package/dist/core/diff/data-differ.d.ts +1 -0
  6. package/dist/core/diff/data-differ.js +243 -0
  7. package/dist/core/diff/patch-generator.d.ts +1 -0
  8. package/dist/core/diff/patch-generator.js +77 -0
  9. package/dist/core/diff/schema-differ.d.ts +1 -0
  10. package/dist/core/diff/schema-differ.js +229 -0
  11. package/dist/core/errors.d.ts +1 -0
  12. package/dist/core/errors.js +39 -0
  13. package/dist/core/index.d.ts +1 -0
  14. package/dist/core/index.js +20 -0
  15. package/dist/core/result.d.ts +1 -0
  16. package/dist/core/result.js +10 -0
  17. package/dist/core/router.d.ts +1 -0
  18. package/dist/core/router.js +37 -0
  19. package/dist/core/transfer/dialect-mapper.d.ts +1 -0
  20. package/dist/core/transfer/dialect-mapper.js +303 -0
  21. package/dist/core/transfer/masking.d.ts +1 -0
  22. package/dist/core/transfer/masking.js +49 -0
  23. package/dist/core/transfer/sync-engine.d.ts +1 -0
  24. package/dist/core/transfer/sync-engine.js +234 -0
  25. package/dist/core/transfer/topological-sort.d.ts +1 -0
  26. package/dist/core/transfer/topological-sort.js +55 -0
  27. package/dist/data/chain.js +1 -1
  28. package/dist/data/engine.js +1 -1
  29. package/dist/db/database.d.ts +1 -1
  30. package/dist/db/database.js +9 -31
  31. package/dist/db/dialects/index.d.ts +1 -0
  32. package/dist/db/dialects/index.js +58 -0
  33. package/dist/db/dialects/postgres/ddl.d.ts +1 -0
  34. package/dist/db/dialects/postgres/ddl.js +107 -0
  35. package/dist/db/dialects/postgres/dialect.d.ts +1 -0
  36. package/dist/db/dialects/postgres/dialect.js +28 -0
  37. package/dist/db/dialects/postgres/introspector.d.ts +1 -0
  38. package/dist/db/dialects/postgres/introspector.js +265 -0
  39. package/dist/db/dialects/postgres/types.d.ts +1 -0
  40. package/dist/db/dialects/postgres/types.js +83 -0
  41. package/dist/db/dialects/sqlite/ddl.d.ts +1 -0
  42. package/dist/db/dialects/sqlite/ddl.js +244 -0
  43. package/dist/db/dialects/sqlite/dialect.d.ts +1 -0
  44. package/dist/db/dialects/sqlite/dialect.js +25 -0
  45. package/dist/db/dialects/sqlite/introspector.d.ts +1 -0
  46. package/dist/db/dialects/sqlite/introspector.js +217 -0
  47. package/dist/db/dialects/sqlite/types.d.ts +1 -0
  48. package/dist/db/dialects/sqlite/types.js +69 -0
  49. package/dist/db/dialects/types.d.ts +1 -0
  50. package/dist/db/dialects/types.js +15 -0
  51. package/dist/db/export.js +1 -1
  52. package/dist/db/index.d.ts +1 -1
  53. package/dist/db/index.js +1 -1
  54. package/dist/db/manager.d.ts +1 -1
  55. package/dist/db/manager.js +101 -21
  56. package/dist/db/postgres.d.ts +1 -1
  57. package/dist/db/postgres.js +20 -284
  58. package/dist/db/types.d.ts +1 -1
  59. package/dist/db/types.js +0 -4
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.js +4 -1
  62. package/dist/modules/databases/databases.routes.d.ts +1 -0
  63. package/dist/modules/databases/databases.routes.js +150 -0
  64. package/dist/modules/databases/databases.service.d.ts +1 -0
  65. package/dist/modules/databases/databases.service.js +134 -0
  66. package/dist/modules/databases/index.d.ts +1 -0
  67. package/dist/{routes → modules/databases}/index.js +2 -3
  68. package/dist/modules/erd/erd.routes.d.ts +1 -0
  69. package/dist/modules/erd/erd.routes.js +32 -0
  70. package/dist/modules/erd/erd.service.d.ts +1 -0
  71. package/dist/modules/erd/erd.service.js +39 -0
  72. package/dist/modules/erd/index.d.ts +1 -0
  73. package/dist/modules/erd/index.js +18 -0
  74. package/dist/modules/index.d.ts +1 -0
  75. package/dist/modules/index.js +70 -0
  76. package/dist/modules/query/index.d.ts +1 -0
  77. package/dist/modules/query/index.js +18 -0
  78. package/dist/modules/query/query.routes.d.ts +1 -0
  79. package/dist/modules/query/query.routes.js +54 -0
  80. package/dist/modules/query/query.service.d.ts +1 -0
  81. package/dist/modules/query/query.service.js +95 -0
  82. package/dist/modules/rows/blob.helper.d.ts +1 -0
  83. package/dist/modules/rows/blob.helper.js +40 -0
  84. package/dist/modules/rows/display.helper.d.ts +1 -0
  85. package/dist/modules/rows/display.helper.js +73 -0
  86. package/dist/modules/rows/index.d.ts +1 -0
  87. package/dist/modules/rows/index.js +20 -0
  88. package/dist/modules/rows/rows.routes.d.ts +1 -0
  89. package/dist/modules/rows/rows.routes.js +555 -0
  90. package/dist/modules/rows/rows.service.d.ts +1 -0
  91. package/dist/modules/rows/rows.service.js +433 -0
  92. package/dist/modules/schema/index.d.ts +1 -0
  93. package/dist/modules/schema/index.js +18 -0
  94. package/dist/modules/schema/schema.routes.d.ts +1 -0
  95. package/dist/modules/schema/schema.routes.js +171 -0
  96. package/dist/modules/schema/schema.service.d.ts +1 -0
  97. package/dist/modules/schema/schema.service.js +58 -0
  98. package/dist/modules/search/index.d.ts +1 -0
  99. package/dist/modules/search/index.js +19 -0
  100. package/dist/modules/search/search.routes.d.ts +1 -0
  101. package/dist/modules/search/search.routes.js +38 -0
  102. package/dist/modules/search/search.service.d.ts +1 -0
  103. package/dist/modules/search/search.service.js +458 -0
  104. package/dist/modules/search/search.types.d.ts +1 -0
  105. package/dist/modules/search/search.types.js +2 -0
  106. package/dist/modules/seed/index.d.ts +1 -0
  107. package/dist/modules/seed/index.js +18 -0
  108. package/dist/modules/seed/seed.routes.d.ts +1 -0
  109. package/dist/modules/seed/seed.routes.js +212 -0
  110. package/dist/modules/seed/seed.service.d.ts +1 -0
  111. package/dist/{routes/api/helpers.js → modules/seed/seed.service.js} +86 -109
  112. package/dist/modules/sync/index.d.ts +1 -0
  113. package/dist/modules/sync/index.js +18 -0
  114. package/dist/modules/sync/sync.routes.d.ts +1 -0
  115. package/dist/modules/sync/sync.routes.js +135 -0
  116. package/dist/modules/sync/sync.service.d.ts +1 -0
  117. package/dist/modules/sync/sync.service.js +41 -0
  118. package/dist/modules/tables/index.d.ts +1 -0
  119. package/dist/modules/tables/index.js +18 -0
  120. package/dist/modules/tables/tables.routes.d.ts +1 -0
  121. package/dist/modules/tables/tables.routes.js +194 -0
  122. package/dist/modules/tables/tables.service.d.ts +1 -0
  123. package/dist/modules/tables/tables.service.js +218 -0
  124. package/dist/public/css/app.css +1 -1
  125. package/dist/public/js/browse.js +1 -1
  126. package/dist/public/js/query.js +1 -1
  127. package/dist/public/js/search.js +1 -0
  128. package/dist/public/js/sync.js +1 -0
  129. package/dist/types/api.d.ts +1 -1
  130. package/dist/utils/common.d.ts +1 -1
  131. package/dist/utils/common.js +1 -3
  132. package/dist/utils/icons.js +3 -0
  133. package/dist/utils/stream.d.ts +1 -0
  134. package/dist/utils/stream.js +131 -0
  135. package/dist/views/layouts/main.hbs +1 -1
  136. package/dist/views/pages/error.hbs +10 -1
  137. package/dist/views/pages/home.hbs +1 -1
  138. package/dist/views/pages/query.hbs +1 -1
  139. package/dist/views/pages/seed-select.hbs +1 -252
  140. package/dist/views/pages/seed.hbs +1 -307
  141. package/dist/views/pages/sync.hbs +409 -0
  142. package/dist/views/pages/table.hbs +1 -1
  143. package/dist/views/partials/navbar.hbs +1 -1
  144. package/dist/views/partials/sidebar.hbs +1 -1
  145. package/docs/API.md +4 -17
  146. package/docs/EXAMPLES.md +579 -579
  147. package/docs/SECURITY.md +265 -265
  148. package/package.json +10 -9
  149. package/dist/db/introspection.d.ts +0 -1
  150. package/dist/db/introspection.js +0 -164
  151. package/dist/routes/api/erd.d.ts +0 -1
  152. package/dist/routes/api/erd.js +0 -45
  153. package/dist/routes/api/helpers.d.ts +0 -1
  154. package/dist/routes/api/import-export.d.ts +0 -1
  155. package/dist/routes/api/import-export.js +0 -84
  156. package/dist/routes/api/index.d.ts +0 -1
  157. package/dist/routes/api/index.js +0 -55
  158. package/dist/routes/api/query.d.ts +0 -1
  159. package/dist/routes/api/query.js +0 -77
  160. package/dist/routes/api/rows.d.ts +0 -1
  161. package/dist/routes/api/rows.js +0 -373
  162. package/dist/routes/api/seed.d.ts +0 -1
  163. package/dist/routes/api/seed.js +0 -180
  164. package/dist/routes/api/tables.d.ts +0 -1
  165. package/dist/routes/api/tables.js +0 -230
  166. package/dist/routes/databases.d.ts +0 -1
  167. package/dist/routes/databases.js +0 -212
  168. package/dist/routes/index.d.ts +0 -1
  169. package/dist/routes/pages.d.ts +0 -1
  170. package/dist/routes/pages.js +0 -540
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.truncate = exports.decodePk = exports.encodePk = exports.isInternalTable = exports.isPostgresConnectionString = exports.errorMessage = void 0;
6
+ exports.truncate = exports.decodePk = exports.encodePk = exports.isPostgresConnectionString = exports.errorMessage = void 0;
7
7
  exports.sanitizeConnectionString = sanitizeConnectionString;
8
8
  exports.isPathWithinRoot = isPathWithinRoot;
9
9
  exports.parseFilters = parseFilters;
@@ -99,8 +99,6 @@ function filtersToQS(filters) {
99
99
  }
100
100
  return Object.keys(out).length ? `f=${encodeURIComponent(JSON.stringify(out))}` : '';
101
101
  }
102
- const isInternalTable = (name) => name.startsWith('_');
103
- exports.isInternalTable = isInternalTable;
104
102
  const encodePk = (values) => values.map((v) => encodeURIComponent(v == null ? '' : String(v))).join(',');
105
103
  exports.encodePk = encodePk;
106
104
  const decodePk = (encoded) => String(encoded)
@@ -13,6 +13,9 @@ exports.ICONS = {
13
13
  book: '<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>',
14
14
  schema: '<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="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg>',
15
15
  diagram: '<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"><rect x="2" y="3" width="6" height="5" rx="1" stroke-linecap="round" stroke-linejoin="round"/><rect x="16" y="3" width="6" height="5" rx="1" stroke-linecap="round" stroke-linejoin="round"/><rect x="9" y="16" width="6" height="5" rx="1" stroke-linecap="round" stroke-linejoin="round"/><path stroke-linecap="round" stroke-linejoin="round" d="M5 8v4h14V8M12 12v4"/></svg>',
16
+ diff: '<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 7h8M8 12h8m-8 5h4M4 4v16a2 2 0 002 2h12a2 2 0 002-2V4a2 2 0 00-2-2H6a2 2 0 00-2 2zM12 3v4m-3-2h6"/></svg>',
17
+ sync: '<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 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /></svg>',
18
+ swap: '<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 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" /></svg>',
16
19
  search: '<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="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>',
17
20
  filter: '<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 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414A1 1 0 0014 15.414V20a1 1 0 01-1 1h-2a1 1 0 01-1-1v-4.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /></svg>',
18
21
  export: '<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>',
@@ -0,0 +1 @@
1
+ import{Transform} from 'node:stream';export declare function createJsonStream():Transform;export declare function createCsvStream(columns:string[]):Transform;export declare function parseCsvStreamBatched(stream:AsyncIterable<string|Buffer>,onBatch:(rows:string[][])=>Promise<void>,batchSize?:number):Promise<number>;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createJsonStream = createJsonStream;
4
+ exports.createCsvStream = createCsvStream;
5
+ exports.parseCsvStreamBatched = parseCsvStreamBatched;
6
+ const node_stream_1 = require("node:stream");
7
+ const csv_1 = require("./csv");
8
+ function createJsonStream() {
9
+ let isFirst = true;
10
+ return new node_stream_1.Transform({
11
+ writableObjectMode: true,
12
+ readableObjectMode: false,
13
+ transform(chunk, _encoding, callback) {
14
+ try {
15
+ const str = JSON.stringify(chunk, null, 2);
16
+ if (isFirst) {
17
+ isFirst = false;
18
+ this.push(`[\n ${str.replace(/\n/g, '\n ')}`);
19
+ }
20
+ else {
21
+ this.push(`,\n ${str.replace(/\n/g, '\n ')}`);
22
+ }
23
+ callback();
24
+ }
25
+ catch (err) {
26
+ callback(err);
27
+ }
28
+ },
29
+ flush(callback) {
30
+ if (isFirst) {
31
+ this.push('[]');
32
+ }
33
+ else {
34
+ this.push('\n]');
35
+ }
36
+ callback();
37
+ },
38
+ });
39
+ }
40
+ function createCsvStream(columns) {
41
+ let headerSent = false;
42
+ return new node_stream_1.Transform({
43
+ writableObjectMode: true,
44
+ readableObjectMode: false,
45
+ transform(chunk, _encoding, callback) {
46
+ try {
47
+ if (!headerSent) {
48
+ headerSent = true;
49
+ const header = columns.map(csv_1.csvEscape).join(',');
50
+ this.push(`${header}\r\n`);
51
+ }
52
+ const line = columns.map((c) => (0, csv_1.csvEscape)(chunk[c])).join(',');
53
+ this.push(`${line}\r\n`);
54
+ callback();
55
+ }
56
+ catch (err) {
57
+ callback(err);
58
+ }
59
+ },
60
+ flush(callback) {
61
+ if (!headerSent) {
62
+ this.push(`${columns.map(csv_1.csvEscape).join(',')}\r\n`);
63
+ }
64
+ callback();
65
+ },
66
+ });
67
+ }
68
+ async function parseCsvStreamBatched(stream, onBatch, batchSize = 500) {
69
+ let buffer = '';
70
+ let inQuotes = false;
71
+ let row = [];
72
+ let field = '';
73
+ let totalRows = 0;
74
+ let batch = [];
75
+ for await (const chunk of stream) {
76
+ const text = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');
77
+ buffer += text;
78
+ for (let i = 0; i < buffer.length; i++) {
79
+ const ch = buffer[i];
80
+ if (inQuotes) {
81
+ if (ch === '"') {
82
+ if (buffer[i + 1] === '"') {
83
+ field += '"';
84
+ i++;
85
+ }
86
+ else {
87
+ inQuotes = false;
88
+ }
89
+ }
90
+ else {
91
+ field += ch;
92
+ }
93
+ }
94
+ else if (ch === '"') {
95
+ inQuotes = true;
96
+ }
97
+ else if (ch === ',') {
98
+ row.push(field);
99
+ field = '';
100
+ }
101
+ else if (ch === '\n') {
102
+ row.push(field);
103
+ field = '';
104
+ if (row.length > 1 || (row[0] !== undefined && row[0] !== '')) {
105
+ batch.push(row);
106
+ totalRows++;
107
+ if (batch.length >= batchSize) {
108
+ await onBatch(batch);
109
+ batch = [];
110
+ }
111
+ }
112
+ row = [];
113
+ }
114
+ else if (ch !== '\r') {
115
+ field += ch;
116
+ }
117
+ }
118
+ buffer = '';
119
+ }
120
+ if (field || row.length > 0) {
121
+ row.push(field);
122
+ if (row.length > 1 || (row[0] !== undefined && row[0] !== '')) {
123
+ batch.push(row);
124
+ totalRows++;
125
+ }
126
+ }
127
+ if (batch.length > 0) {
128
+ await onBatch(batch);
129
+ }
130
+ return totalRows;
131
+ }
@@ -1 +1 @@
1
- <!DOCTYPE html>
2
1
  <meta charset="utf-8" />
3
2
  <meta name="viewport" content="width=device-width, initial-scale=1" />
4
3
  <title>{{title}} · AdminDB</title>
5
4
  <link rel="preconnect" href="https://fonts.googleapis.com" />
6
5
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
7
6
  <link href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700;800&family=IBM+Plex+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
8
7
  <link rel="stylesheet" href="{{basePath}}/css/app.css" />
9
8
  <script>
10
9
  window.APP = {
11
10
  basePath: {{{json basePath}}},
12
11
  dbId: {{{json dbId}}},
13
12
  readonly: {{{json readonly}}},
14
13
  serverless: {{{json serverless}}},
15
14
  dialect: {{{json dialect}}},
16
15
  isSqlite: {{{json isSqlite}}},
17
16
  isPostgres: {{{json isPostgres}}}
18
17
  };
19
18
  // Apply the saved theme before first paint to avoid a flash.
20
19
  (function () {
21
20
  try {
22
21
  var t = localStorage.getItem('admindb-theme');
23
22
  if (t === 'dark') document.documentElement.setAttribute('data-theme', 'admindbDark');
24
23
  } catch (e) {}
25
24
  })();
26
25
  </script>
27
26
  <script>
28
27
  window.AdminIcons = {
29
28
  map: {{{json icons}}},
30
29
  get: function(name, customClass) {
31
30
  var svg = this.map[name] || '';
32
31
  if (!svg || !customClass) return svg;
33
32
  if (svg.indexOf('class="') !== -1) {
34
33
  return svg.replace(/class="[^"]*"/, 'class="' + customClass + '"');
35
34
  }
36
35
  return svg.replace('<svg', '<svg class="' + customClass + '"');
37
36
  }
38
37
  };
39
38
  </script>
40
39
  <script src="{{basePath}}/js/common.js" defer></script>
41
40
  <script src="{{basePath}}/js/api.js" defer></script>
42
41
  <script src="{{basePath}}/js/app.js" defer></script>
43
42
  <script src="{{basePath}}/js/inspector.js" defer></script>
44
43
  <div class="pointer-events-none fixed inset-0 -z-10 overflow-hidden">
45
44
  <div class="absolute -left-24 top-32 h-72 w-72 rounded-full bg-primary/15 blur-3xl"></div>
46
45
  <div class="absolute -right-24 bottom-20 h-80 w-80 rounded-full bg-orange-500/10 blur-3xl"></div>
47
46
  </div>
48
47
  {{#if readonly}}
49
48
  <div class="flex items-center justify-center gap-2 bg-warning/15 px-4 py-2 text-center text-sm font-semibold text-warning">
50
49
  <span class="shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
51
50
  {{#if serverless}}
52
51
  Serverless mode active — database is open in read-only mode. Writes and schema modifications are disabled.
53
52
  {{else}}
54
53
  Read-only mode — this database is open without write access. All writes are disabled.
55
54
  {{/if}}
56
55
  </div>
57
56
  {{/if}}
58
57
  {{#if noSidebar}}
59
58
  <div class="flex min-h-screen flex-col">
60
59
  {{> navbar}}
61
60
  <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
62
61
  {{{body}}}
63
62
  </main>
64
63
  <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
65
64
  AdminDB{{#if version}} v{{version}}{{/if}} · SQLite & PostgreSQL database administration
66
65
  </footer>
67
66
  </div>
68
67
  {{else}}
69
68
  <div class="drawer lg:drawer-open">
70
69
  <input id="sidebar-toggle" type="checkbox" class="drawer-toggle" />
71
70
  <div class="drawer-content flex min-h-screen flex-col">
72
71
  {{> navbar}}
73
72
  <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
74
73
  {{{body}}}
75
74
  </main>
76
75
  <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
77
76
  AdminDB{{#if version}} v{{version}}{{/if}} · SQLite & PostgreSQL database administration
78
77
  </footer>
79
78
  </div>
80
79
  <div class="drawer-side z-40 lg:sticky lg:top-0 lg:h-screen lg:max-h-screen">
81
80
  <label for="sidebar-toggle" aria-label="close sidebar" class="drawer-overlay"></label>
82
81
  {{> sidebar}}
83
82
  </div>
84
83
  </div>
85
84
  {{/if}}
86
85
  <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>
86
+ <!DOCTYPE html>
87
87
  <meta charset="utf-8" />
88
88
  <meta name="viewport" content="width=device-width, initial-scale=1" />
89
89
  <title>{{title}} · AdminDB</title>
90
90
  <link rel="preconnect" href="https://fonts.googleapis.com" />
91
91
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
92
92
  <link href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700;800&family=IBM+Plex+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
93
93
  <link rel="stylesheet" href="{{basePath}}/css/app.css" />
94
94
  <script>
95
95
  window.APP = {
96
96
  basePath: {{{json basePath}}},
97
97
  dbId: {{{json dbId}}},
98
98
  readonly: {{{json readonly}}},
99
99
  serverless: {{{json serverless}}},
100
100
  dialect: {{{json dialect}}},
101
101
  isSqlite: {{{json isSqlite}}},
102
102
  isPostgres: {{{json isPostgres}}}
103
103
  };
104
104
  // Apply the saved theme before first paint to avoid a flash.
105
105
  (function () {
106
106
  try {
107
107
  var t = localStorage.getItem('admindb-theme');
108
108
  if (t === 'dark') document.documentElement.setAttribute('data-theme', 'admindbDark');
109
109
  } catch (e) {}
110
110
  })();
111
111
  </script>
112
112
  <script>
113
113
  window.AdminIcons = {
114
114
  map: {{{json icons}}},
115
115
  get: function(name, customClass) {
116
116
  var svg = this.map[name] || '';
117
117
  if (!svg || !customClass) return svg;
118
118
  if (svg.indexOf('class="') !== -1) {
119
119
  return svg.replace(/class="[^"]*"/, 'class="' + customClass + '"');
120
120
  }
121
121
  return svg.replace('<svg', '<svg class="' + customClass + '"');
122
122
  }
123
123
  };
124
124
  </script>
125
125
  <script src="{{basePath}}/js/common.js" defer></script>
126
126
  <script src="{{basePath}}/js/api.js" defer></script>
127
127
  <script src="{{basePath}}/js/app.js" defer></script>
128
128
  <script src="{{basePath}}/js/inspector.js" defer></script>
129
129
  <script src="{{basePath}}/js/search.js" defer></script>
130
130
  <div class="pointer-events-none fixed inset-0 -z-10 overflow-hidden">
131
131
  <div class="absolute -left-24 top-32 h-72 w-72 rounded-full bg-primary/15 blur-3xl"></div>
132
132
  <div class="absolute -right-24 bottom-20 h-80 w-80 rounded-full bg-orange-500/10 blur-3xl"></div>
133
133
  </div>
134
134
  {{#if readonly}}
135
135
  <div class="flex items-center justify-center gap-2 bg-warning/15 px-4 py-2 text-center text-sm font-semibold text-warning">
136
136
  <span class="shrink-0">{{{icon "warning" class="h-4 w-4"}}}</span>
137
137
  {{#if serverless}}
138
138
  Serverless mode active — database is open in read-only mode. Writes and schema modifications are disabled.
139
139
  {{else}}
140
140
  Read-only mode — this database is open without write access. All writes are disabled.
141
141
  {{/if}}
142
142
  </div>
143
143
  {{/if}}
144
144
  {{#if noSidebar}}
145
145
  <div class="flex min-h-screen flex-col">
146
146
  {{> navbar}}
147
147
  <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
148
148
  {{{body}}}
149
149
  </main>
150
150
  <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
151
151
  AdminDB{{#if version}} v{{version}}{{/if}} · SQLite & PostgreSQL database administration
152
152
  </footer>
153
153
  </div>
154
154
  {{else}}
155
155
  <div class="drawer lg:drawer-open">
156
156
  <input id="sidebar-toggle" type="checkbox" class="drawer-toggle" />
157
157
  <div class="drawer-content flex min-h-screen flex-col">
158
158
  {{> navbar}}
159
159
  <main class="mx-auto w-full max-w-[1500px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
160
160
  {{{body}}}
161
161
  </main>
162
162
  <footer class="border-t border-base-300 px-6 py-4 text-center text-xs text-base-content/40">
163
163
  AdminDB{{#if version}} v{{version}}{{/if}} · SQLite & PostgreSQL database administration
164
164
  </footer>
165
165
  </div>
166
166
  <div class="drawer-side z-40 lg:sticky lg:top-0 lg:h-screen lg:max-h-screen">
167
167
  <label for="sidebar-toggle" aria-label="close sidebar" class="drawer-overlay"></label>
168
168
  {{> sidebar}}
169
169
  </div>
170
170
  </div>
171
171
  {{/if}}
172
172
  <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>
@@ -1 +1,10 @@
1
- <div class="mx-auto mt-16 max-w-md space-y-6 text-center">
2
1
  <div class="mx-auto grid h-20 w-20 place-items-center rounded-3xl bg-error/10 text-error">
3
2
  {{{icon "warning" class="h-10 w-10"}}}
4
3
  </div>
5
4
  <div>
6
5
  <h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
7
6
  <p class="mt-2 text-base-content/60">{{error}}</p>
8
7
  </div>
9
8
  <a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
9
+ <div class="mx-auto mt-16 max-w-md space-y-6 text-center">
10
+ <div class="mx-auto grid h-20 w-20 place-items-center rounded-3xl bg-error/10 text-error">
11
+ {{{icon "warning" class="h-10 w-10"}}}
12
+ </div>
13
+ <div>
14
+ <h1 class="text-5xl font-extrabold tracking-tight text-error">{{status}}</h1>
15
+ <p class="mt-2 text-base-content/60">{{error}}</p>
16
+ </div>
17
+ <a href="{{basePath}}/" class="btn btn-primary">Back to home</a>
18
+ </div>