admindb 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +368 -335
- package/dist/app.js +227 -1
- package/dist/auth/config.d.ts +1 -1
- package/dist/auth/config.js +109 -1
- package/dist/auth/crypto.js +98 -1
- package/dist/auth/index.js +21 -1
- package/dist/auth/middleware.js +78 -1
- package/dist/auth/routes.js +64 -1
- package/dist/auth/types.js +7 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +309 -1
- package/dist/cli/config.js +118 -1
- package/dist/cli/index.js +20 -1
- package/dist/cli/runner.js +208 -1
- package/dist/cli.js +4 -1
- package/dist/data/chain.d.ts +1 -0
- package/dist/data/chain.js +130 -0
- package/dist/data/datasets.d.ts +1 -1
- package/dist/data/datasets.js +171 -1
- package/dist/data/detector.d.ts +1 -1
- package/dist/data/detector.js +535 -1
- package/dist/data/engine.d.ts +1 -1
- package/dist/data/engine.js +586 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +30 -1
- package/dist/data/prng.d.ts +1 -0
- package/dist/data/prng.js +73 -0
- package/dist/data/registry.d.ts +1 -0
- package/dist/data/registry.js +805 -0
- package/dist/data/schema-graph.d.ts +1 -0
- package/dist/data/schema-graph.js +210 -0
- package/dist/data/strategies.d.ts +1 -1
- package/dist/data/strategies.js +100 -1
- package/dist/data/templates.d.ts +1 -0
- package/dist/data/templates.js +134 -0
- package/dist/data/types.d.ts +1 -1
- package/dist/data/types.js +5 -1
- package/dist/data/validator.d.ts +1 -0
- package/dist/data/validator.js +160 -0
- package/dist/db/database.d.ts +1 -1
- package/dist/db/database.js +472 -1
- package/dist/db/export.d.ts +1 -1
- package/dist/db/export.js +67 -1
- package/dist/db/filters.d.ts +1 -1
- package/dist/db/filters.js +119 -1
- package/dist/db/index.js +24 -1
- package/dist/db/introspection.js +164 -1
- package/dist/db/manager.js +327 -1
- package/dist/db/migrations.js +100 -1
- package/dist/db/postgres.d.ts +1 -1
- package/dist/db/postgres.js +687 -1
- package/dist/db/types.d.ts +1 -1
- package/dist/db/types.js +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +52 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/api.js +1 -1
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/common.js +1 -0
- package/dist/public/js/databases.js +1 -1
- package/dist/public/js/designer.js +1 -1
- package/dist/public/js/forms.js +1 -1
- package/dist/public/js/home.js +1 -0
- package/dist/public/js/inspector.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/public/js/schema.js +1 -1
- package/dist/public/js/seed.js +1 -1
- package/dist/routes/api/erd.d.ts +1 -0
- package/dist/routes/api/erd.js +45 -0
- package/dist/routes/api/helpers.d.ts +1 -1
- package/dist/routes/api/helpers.js +213 -1
- package/dist/routes/api/import-export.js +82 -1
- package/dist/routes/api/index.js +48 -1
- package/dist/routes/api/query.js +74 -1
- package/dist/routes/api/rows.js +358 -1
- package/dist/routes/api/seed.js +167 -1
- package/dist/routes/api/tables.js +216 -1
- package/dist/routes/databases.js +210 -1
- package/dist/routes/index.js +19 -1
- package/dist/routes/pages.js +446 -1
- package/dist/serverless.js +149 -1
- package/dist/sql/classifier.js +24 -1
- package/dist/sql/error-analyzer.d.ts +1 -0
- package/dist/sql/error-analyzer.js +550 -0
- package/dist/sql/generator.d.ts +1 -1
- package/dist/sql/generator.js +245 -1
- package/dist/sql/index.js +18 -1
- package/dist/types/api.d.ts +1 -1
- package/dist/types/api.js +2 -1
- package/dist/utils/colors.js +54 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +185 -1
- package/dist/utils/csv.d.ts +1 -1
- package/dist/utils/csv.js +61 -1
- package/dist/utils/datatype.js +167 -1
- package/dist/utils/icons.js +81 -1
- package/dist/utils/index.js +20 -1
- package/dist/utils/logger.js +36 -1
- package/dist/views/layouts/main.hbs +1 -74
- package/dist/views/pages/databases.hbs +1 -233
- package/dist/views/pages/designer.hbs +1 -89
- package/dist/views/pages/erd.hbs +1 -0
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/form.hbs +1 -59
- package/dist/views/pages/home.hbs +1 -124
- package/dist/views/pages/info.hbs +1 -0
- package/dist/views/pages/login.hbs +1 -98
- package/dist/views/pages/query.hbs +1 -87
- package/dist/views/pages/schema.hbs +1 -298
- package/dist/views/pages/seed-select.hbs +251 -0
- package/dist/views/pages/seed.hbs +273 -167
- package/dist/views/pages/table.hbs +1 -327
- package/dist/views/partials/navbar.hbs +1 -83
- package/dist/views/partials/sidebar.hbs +1 -117
- package/docs/API.md +149 -144
- package/docs/EXAMPLES.md +579 -576
- package/docs/SECURITY.md +265 -265
- package/package.json +79 -78
- package/dist/public/js/icons.js +0 -1
package/dist/sql/generator.js
CHANGED
|
@@ -1 +1,245 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.escapeString = exports.quoteIdentifier = exports.getDesignerTypes = exports.DESIGNER_TYPES = exports.POSTGRES_DESIGNER_TYPES = exports.SQLITE_DESIGNER_TYPES = void 0;
|
|
4
|
+
exports.sqlValue = sqlValue;
|
|
5
|
+
exports.mapColumnType = mapColumnType;
|
|
6
|
+
exports.formatSqlDefault = formatSqlDefault;
|
|
7
|
+
exports.renderColumnDef = renderColumnDef;
|
|
8
|
+
exports.generateCreateTable = generateCreateTable;
|
|
9
|
+
exports.generateAddColumn = generateAddColumn;
|
|
10
|
+
exports.generateRenameTable = generateRenameTable;
|
|
11
|
+
exports.generateRenameColumn = generateRenameColumn;
|
|
12
|
+
exports.generateDropColumn = generateDropColumn;
|
|
13
|
+
exports.generateDropTable = generateDropTable;
|
|
14
|
+
exports.generateCreateIndex = generateCreateIndex;
|
|
15
|
+
exports.generateDropIndex = generateDropIndex;
|
|
16
|
+
exports.generateInsert = generateInsert;
|
|
17
|
+
exports.generateUpdate = generateUpdate;
|
|
18
|
+
exports.SQLITE_DESIGNER_TYPES = ['TEXT', 'INTEGER', 'REAL', 'BLOB', 'BOOLEAN', 'DATE', 'DATETIME', 'NUMERIC', 'VARCHAR(255)', 'JSON',];
|
|
19
|
+
exports.POSTGRES_DESIGNER_TYPES = ['TEXT', 'VARCHAR(255)', 'INTEGER', 'BIGINT', 'SMALLINT', 'SERIAL', 'BIGSERIAL', 'REAL', 'DECIMAL(10,2)', 'NUMERIC', 'BOOLEAN', 'DATE', 'DATETIME', 'TIMESTAMP', 'TIMESTAMPTZ', 'TIME', 'INTERVAL', 'JSON', 'JSONB', 'UUID', 'BYTEA', 'INET',];
|
|
20
|
+
exports.DESIGNER_TYPES = ['TEXT', 'VARCHAR(255)', 'INTEGER', 'BIGINT', 'SMALLINT', 'SERIAL', 'BIGSERIAL', 'REAL', 'DECIMAL(10,2)', 'NUMERIC', 'BOOLEAN', 'DATE', 'DATETIME', 'TIMESTAMP', 'TIMESTAMPTZ', 'TIME', 'INTERVAL', 'JSON', 'JSONB', 'UUID', 'BYTEA', 'BLOB', 'INET',];
|
|
21
|
+
const getDesignerTypes = (dialect = 'sqlite') => dialect === 'postgres' ? exports.POSTGRES_DESIGNER_TYPES : exports.SQLITE_DESIGNER_TYPES;
|
|
22
|
+
exports.getDesignerTypes = getDesignerTypes;
|
|
23
|
+
const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
24
|
+
const quoteIdentifier = (identifier) => `"${String(identifier).replace(/"/g, '""')}"`;
|
|
25
|
+
exports.quoteIdentifier = quoteIdentifier;
|
|
26
|
+
const escapeString = (value) => `'${String(value).replace(/'/g, "''")}'`;
|
|
27
|
+
exports.escapeString = escapeString;
|
|
28
|
+
function sqlValue(value) {
|
|
29
|
+
if (value == null)
|
|
30
|
+
return 'NULL';
|
|
31
|
+
if (typeof value === 'number')
|
|
32
|
+
return Number.isFinite(value) ? String(value) : 'NULL';
|
|
33
|
+
if (typeof value === 'bigint')
|
|
34
|
+
return String(value);
|
|
35
|
+
if (typeof value === 'boolean')
|
|
36
|
+
return value ? '1' : '0';
|
|
37
|
+
if (value instanceof Uint8Array)
|
|
38
|
+
return `X'${Buffer.from(value).toString('hex')}'`;
|
|
39
|
+
if (value instanceof Date)
|
|
40
|
+
return (0, exports.escapeString)(value.toISOString());
|
|
41
|
+
return (0, exports.escapeString)(String(value));
|
|
42
|
+
}
|
|
43
|
+
function mapColumnType(type) {
|
|
44
|
+
const t = String(type ?? '').trim().toUpperCase();
|
|
45
|
+
if (!t)
|
|
46
|
+
return { sqlType: 'TEXT' };
|
|
47
|
+
switch (t) {
|
|
48
|
+
case 'INTEGER':
|
|
49
|
+
case 'INT':
|
|
50
|
+
case 'TINYINT':
|
|
51
|
+
return { sqlType: 'INTEGER' };
|
|
52
|
+
case 'BIGINT':
|
|
53
|
+
case 'SMALLINT':
|
|
54
|
+
case 'SERIAL':
|
|
55
|
+
case 'BIGSERIAL':
|
|
56
|
+
case 'SMALLSERIAL':
|
|
57
|
+
return { sqlType: t };
|
|
58
|
+
case 'TEXT':
|
|
59
|
+
case 'VARCHAR':
|
|
60
|
+
case 'CHAR':
|
|
61
|
+
case 'CLOB':
|
|
62
|
+
case 'STRING':
|
|
63
|
+
case 'CITEXT':
|
|
64
|
+
return { sqlType: 'TEXT' };
|
|
65
|
+
case 'REAL':
|
|
66
|
+
case 'FLOAT':
|
|
67
|
+
case 'DOUBLE':
|
|
68
|
+
case 'DECIMAL':
|
|
69
|
+
case 'NUMERIC':
|
|
70
|
+
case 'NUMBER':
|
|
71
|
+
case 'MONEY':
|
|
72
|
+
return { sqlType: 'REAL' };
|
|
73
|
+
case 'BLOB':
|
|
74
|
+
case 'BINARY':
|
|
75
|
+
case 'VARBINARY':
|
|
76
|
+
return { sqlType: 'BLOB' };
|
|
77
|
+
case 'BYTEA':
|
|
78
|
+
return { sqlType: 'BYTEA' };
|
|
79
|
+
case 'BOOLEAN':
|
|
80
|
+
case 'BOOL':
|
|
81
|
+
return { sqlType: 'INTEGER' };
|
|
82
|
+
case 'DATE':
|
|
83
|
+
return { sqlType: 'DATETIME', defaultAuto: 'CURRENT_TIMESTAMP' };
|
|
84
|
+
case 'DATETIME':
|
|
85
|
+
return { sqlType: 'DATETIME' };
|
|
86
|
+
case 'TIMESTAMP':
|
|
87
|
+
case 'TIMESTAMPTZ':
|
|
88
|
+
case 'TIMESTAMP WITHOUT TIME ZONE':
|
|
89
|
+
case 'TIMESTAMP WITH TIME ZONE':
|
|
90
|
+
case 'TIME':
|
|
91
|
+
case 'TIMETZ':
|
|
92
|
+
case 'TIME WITHOUT TIME ZONE':
|
|
93
|
+
case 'TIME WITH TIME ZONE':
|
|
94
|
+
case 'INTERVAL':
|
|
95
|
+
case 'JSON':
|
|
96
|
+
case 'JSONB':
|
|
97
|
+
case 'UUID':
|
|
98
|
+
case 'INET':
|
|
99
|
+
case 'CIDR':
|
|
100
|
+
case 'MACADDR':
|
|
101
|
+
return { sqlType: t };
|
|
102
|
+
default:
|
|
103
|
+
if (/^[A-Za-z0-9_(),\s\[\]]+$/.test(t))
|
|
104
|
+
return { sqlType: t };
|
|
105
|
+
throw new Error(`Unsupported column type: "${type}". Supported types include: ${exports.DESIGNER_TYPES.join(', ')} or standard SQL types.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function validateIdentifier(kind, name) {
|
|
109
|
+
const label = kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
110
|
+
const trimmed = String(name ?? '').trim();
|
|
111
|
+
if (!trimmed)
|
|
112
|
+
throw new Error(`${label} name is required.`);
|
|
113
|
+
if (!IDENTIFIER_RE.test(trimmed)) {
|
|
114
|
+
throw new Error(`Invalid ${label.toLowerCase()} name: "${trimmed}". Use letters, digits and underscores.`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function formatSqlDefault(raw, colType) {
|
|
118
|
+
const s = String(raw ?? '').trim().replace(/;/g, '');
|
|
119
|
+
if (!s)
|
|
120
|
+
return '';
|
|
121
|
+
if (/^null$/i.test(s))
|
|
122
|
+
return 'NULL';
|
|
123
|
+
if (/^[-+]?\d+(\.\d+)?$/.test(s))
|
|
124
|
+
return s;
|
|
125
|
+
if (/^(true|false)$/i.test(s))
|
|
126
|
+
return s.toUpperCase() === 'TRUE' ? '1' : '0';
|
|
127
|
+
if (/^'.*'$/s.test(s) || /^".*"$/s.test(s) || /^[a-zA-Z_]\w*\s*\(.*\)$/s.test(s))
|
|
128
|
+
return s;
|
|
129
|
+
if (/^CURRENT_TIMESTAMP|CURRENT_DATE|CURRENT_TIME$/i.test(s))
|
|
130
|
+
return s.toUpperCase();
|
|
131
|
+
const t = (colType || '').toUpperCase();
|
|
132
|
+
if (t.includes('TEXT') || t.includes('CHAR') || t.includes('CLOB') || t.includes('VARCHAR') || t.includes('STRING')) {
|
|
133
|
+
return (0, exports.escapeString)(s);
|
|
134
|
+
}
|
|
135
|
+
return s;
|
|
136
|
+
}
|
|
137
|
+
function renderColumnDef(col, opts = {}) {
|
|
138
|
+
const colName = String(col?.name ?? '').trim();
|
|
139
|
+
validateIdentifier('column', colName);
|
|
140
|
+
const mapped = mapColumnType(col.type);
|
|
141
|
+
if (opts.forAddColumn) {
|
|
142
|
+
if (col.primaryKey) {
|
|
143
|
+
throw new Error(`Cannot add "${colName}" as PRIMARY KEY: ALTER TABLE ADD COLUMN does not support primary keys.`);
|
|
144
|
+
}
|
|
145
|
+
if (col.unique) {
|
|
146
|
+
throw new Error(`Cannot add "${colName}" with UNIQUE: ALTER TABLE ADD COLUMN does not support UNIQUE constraints.`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
let def = `${(0, exports.quoteIdentifier)(colName)} ${mapped.sqlType}`;
|
|
150
|
+
if (!opts.forAddColumn && col.primaryKey)
|
|
151
|
+
def += ' PRIMARY KEY';
|
|
152
|
+
if (col.notNull)
|
|
153
|
+
def += ' NOT NULL';
|
|
154
|
+
if (!opts.forAddColumn && col.unique)
|
|
155
|
+
def += ' UNIQUE';
|
|
156
|
+
const rawDefault = formatSqlDefault(String(col.defaultValue ?? ''), col.type);
|
|
157
|
+
const dflt = rawDefault || mapped.defaultAuto || '';
|
|
158
|
+
if (dflt) {
|
|
159
|
+
def += ` DEFAULT ${dflt}`;
|
|
160
|
+
}
|
|
161
|
+
else if (opts.forAddColumn && col.notNull) {
|
|
162
|
+
throw new Error(`Cannot add "${colName}" as NOT NULL without a default value.`);
|
|
163
|
+
}
|
|
164
|
+
if (col.foreignKey?.table && col.foreignKey.column) {
|
|
165
|
+
if (opts.forAddColumn && (col.notNull || dflt)) {
|
|
166
|
+
throw new Error(`Cannot add "${colName}" as a foreign key with NOT NULL or a non-NULL default.`);
|
|
167
|
+
}
|
|
168
|
+
def += ` REFERENCES ${(0, exports.quoteIdentifier)(col.foreignKey.table)}(${(0, exports.quoteIdentifier)(col.foreignKey.column)})`;
|
|
169
|
+
}
|
|
170
|
+
return def;
|
|
171
|
+
}
|
|
172
|
+
function generateCreateTable(tableName, columns) {
|
|
173
|
+
const table = String(tableName ?? '').trim();
|
|
174
|
+
validateIdentifier('table', table);
|
|
175
|
+
if (!Array.isArray(columns) || columns.length === 0) {
|
|
176
|
+
throw new Error('At least one column is required.');
|
|
177
|
+
}
|
|
178
|
+
const seen = new Set();
|
|
179
|
+
let pkCount = 0;
|
|
180
|
+
const parts = [];
|
|
181
|
+
for (const col of columns) {
|
|
182
|
+
const colName = String(col?.name ?? '').trim();
|
|
183
|
+
validateIdentifier('column', colName);
|
|
184
|
+
if (seen.has(colName))
|
|
185
|
+
throw new Error(`Duplicate column name: "${colName}".`);
|
|
186
|
+
seen.add(colName);
|
|
187
|
+
if (col.primaryKey)
|
|
188
|
+
pkCount++;
|
|
189
|
+
parts.push(renderColumnDef(col));
|
|
190
|
+
}
|
|
191
|
+
if (pkCount > 1)
|
|
192
|
+
throw new Error('At most one primary key column is allowed.');
|
|
193
|
+
return `CREATE TABLE ${(0, exports.quoteIdentifier)(table)} (\n ${parts.join(',\n ')}\n);`;
|
|
194
|
+
}
|
|
195
|
+
function generateAddColumn(tableName, col) {
|
|
196
|
+
const table = String(tableName ?? '').trim();
|
|
197
|
+
validateIdentifier('table', table);
|
|
198
|
+
return `ALTER TABLE ${(0, exports.quoteIdentifier)(table)} ADD COLUMN ${renderColumnDef(col, { forAddColumn: true })};`;
|
|
199
|
+
}
|
|
200
|
+
function generateRenameTable(tableName, newName) {
|
|
201
|
+
validateIdentifier('table', tableName);
|
|
202
|
+
validateIdentifier('table', newName);
|
|
203
|
+
return `ALTER TABLE ${(0, exports.quoteIdentifier)(tableName)} RENAME TO ${(0, exports.quoteIdentifier)(newName)};`;
|
|
204
|
+
}
|
|
205
|
+
function generateRenameColumn(tableName, oldName, newName) {
|
|
206
|
+
validateIdentifier('table', tableName);
|
|
207
|
+
validateIdentifier('column', oldName);
|
|
208
|
+
validateIdentifier('column', newName);
|
|
209
|
+
return `ALTER TABLE ${(0, exports.quoteIdentifier)(tableName)} RENAME COLUMN ${(0, exports.quoteIdentifier)(oldName)} TO ${(0, exports.quoteIdentifier)(newName)};`;
|
|
210
|
+
}
|
|
211
|
+
function generateDropColumn(tableName, column) {
|
|
212
|
+
validateIdentifier('table', tableName);
|
|
213
|
+
validateIdentifier('column', column);
|
|
214
|
+
return `ALTER TABLE ${(0, exports.quoteIdentifier)(tableName)} DROP COLUMN ${(0, exports.quoteIdentifier)(column)};`;
|
|
215
|
+
}
|
|
216
|
+
function generateDropTable(tableName) {
|
|
217
|
+
validateIdentifier('table', tableName);
|
|
218
|
+
return `DROP TABLE ${(0, exports.quoteIdentifier)(tableName)};`;
|
|
219
|
+
}
|
|
220
|
+
function generateCreateIndex(tableName, index) {
|
|
221
|
+
validateIdentifier('table', tableName);
|
|
222
|
+
const cols = Array.isArray(index?.columns) ? index.columns : [];
|
|
223
|
+
if (!cols.length)
|
|
224
|
+
throw new Error('At least one column is required for an index.');
|
|
225
|
+
for (const c of cols)
|
|
226
|
+
validateIdentifier('column', c);
|
|
227
|
+
const unique = index.unique ? 'UNIQUE ' : '';
|
|
228
|
+
const name = String(index?.name ?? '').trim() || `idx_${tableName}_${cols.join('_')}`;
|
|
229
|
+
validateIdentifier('index', name);
|
|
230
|
+
return `CREATE ${unique}INDEX ${(0, exports.quoteIdentifier)(name)} ON ${(0, exports.quoteIdentifier)(tableName)} (${cols.map(exports.quoteIdentifier).join(', ')});`;
|
|
231
|
+
}
|
|
232
|
+
function generateDropIndex(indexName) {
|
|
233
|
+
validateIdentifier('index', indexName);
|
|
234
|
+
return `DROP INDEX ${(0, exports.quoteIdentifier)(indexName)};`;
|
|
235
|
+
}
|
|
236
|
+
function generateInsert(table, fields) {
|
|
237
|
+
const cols = fields.map((f) => (0, exports.quoteIdentifier)(f.column));
|
|
238
|
+
const vals = fields.map((f) => sqlValue(f.value));
|
|
239
|
+
return `INSERT INTO ${(0, exports.quoteIdentifier)(table)} (${cols.join(', ')}) VALUES (${vals.join(', ')});`;
|
|
240
|
+
}
|
|
241
|
+
function generateUpdate(table, fields, where) {
|
|
242
|
+
const sets = fields.map((f) => `${(0, exports.quoteIdentifier)(f.column)} = ${sqlValue(f.value)}`);
|
|
243
|
+
const conds = where.map((w) => `${(0, exports.quoteIdentifier)(w.column)} = ${sqlValue(w.value)}`);
|
|
244
|
+
return `UPDATE ${(0, exports.quoteIdentifier)(table)} SET ${sets.join(', ')} WHERE ${conds.join(' AND ')};`;
|
|
245
|
+
}
|
package/dist/sql/index.js
CHANGED
|
@@ -1 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./classifier"), exports);
|
|
18
|
+
__exportStar(require("./generator"), exports);
|
package/dist/types/api.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import type {ColumnInfo,ForeignKeyInfo,IndexInfo,SavedQuery,SchemaInfo,TableInfoData,TableListItem,WhereClause,RowFilters} from '../db/database';import type {DatabaseEntry} from '../db/manager';import type {ColumnDef,IndexDef} from '../sql/generator';import type {ColumnGeneratorConfig,ColumnPlan,GeneratorStrategyId,StrategyDescriptor,StrategyCategory} from '../data/index';export type {ColumnInfo,ForeignKeyInfo,IndexInfo,SavedQuery,SchemaInfo,TableInfoData,TableListItem,WhereClause,RowFilters,ColumnDef,IndexDef,ColumnGeneratorConfig,ColumnPlan,GeneratorStrategyId,StrategyDescriptor,StrategyCategory
|
|
1
|
+
import type {ColumnInfo,ForeignKeyInfo,IndexInfo,SavedQuery,SchemaInfo,TableInfoData,TableListItem,WhereClause,RowFilters} from '../db/database';import type {DatabaseEntry} from '../db/manager';import type {ColumnDef,IndexDef} from '../sql/generator';import type {ColumnGeneratorConfig,ColumnPlan,GeneratorStrategyId,StrategyDescriptor,StrategyCategory} from '../data/index';export type {ColumnInfo,ForeignKeyInfo,IndexInfo,SavedQuery,SchemaInfo,TableInfoData,TableListItem,WhereClause,RowFilters,ColumnDef,IndexDef,ColumnGeneratorConfig,ColumnPlan,GeneratorStrategyId,StrategyDescriptor,StrategyCategory};export interface ApiSuccessResponse<T=unknown>{success:true;data:T;}export interface ApiErrorResponse<T=unknown>{success:false;error:string;data?:T;}export type ApiResponse<T=unknown>=ApiSuccessResponse<T>|ApiErrorResponse<T>;export type ListTablesResponseData=TableListItem[];export type ListTablesResponse=ApiResponse<ListTablesResponseData>;export type TableInfoResponseData=TableInfoData;export type TableInfoResponse=ApiResponse<TableInfoResponseData>;export type FkOptionsResponseData=Record<string,{value:unknown;label:string;}[]>;export type FkOptionsResponse=ApiResponse<FkOptionsResponseData>;export interface GetRowsResponseData{rows:Record<string,unknown>[];count:number;page:number;limit:number;filters:RowFilters;}export type GetRowsResponse=ApiResponse<GetRowsResponseData>;export type GetRowResponseData=Record<string,unknown>;export type GetRowResponse=ApiResponse<GetRowResponseData>;export interface RowReferenceGroup{table:string; from :string;to:string;value:unknown;count:number;columns:string[];rows:Record<string,unknown>[];}export interface GetRowReferencesResponseData{references:RowReferenceGroup[];}export type GetRowReferencesResponse=ApiResponse<GetRowReferencesResponseData>;export interface InsertRowRequestBody{values:Record<string,unknown>;}export interface InsertRowResponseData{message:string;rowId?:number|bigint;sql:string;}export type InsertRowResponse=ApiResponse<InsertRowResponseData>;export interface GenerateInsertRequestBody{values:Record<string,unknown>;}export interface GenerateInsertResponseData{sql:string;}export type GenerateInsertResponse=ApiResponse<GenerateInsertResponseData>;export interface ImportCsvRequestBody{csv:string;}export interface ImportCsvResponseData{message:string;inserted?:number;skipped?:number;}export type ImportCsvResponse=ApiResponse<ImportCsvResponseData>;export interface UpdateRowRequestBody{values:Record<string,unknown>;nulls?:string[];}export interface UpdateRowResponseData{message:string;sql:string;}export type UpdateRowResponse=ApiResponse<UpdateRowResponseData>;export interface GenerateUpdateRequestBody{values:Record<string,unknown>;nulls?:string[];}export interface GenerateUpdateResponseData{sql:string;}export type GenerateUpdateResponse=ApiResponse<GenerateUpdateResponseData>;export interface DeleteRowResponseData{message:string;}export type DeleteRowResponse=ApiResponse<DeleteRowResponseData>;export interface BlobMetaResponseData{isNull:boolean;mime?:string;ext?:string;isImage?:boolean;isText?:boolean;isPdf?:boolean;isAudio?:boolean;isVideo?:boolean;size:number;sizeFormatted:string;hexDump?:{lines:{offset:string;hex:string;ascii:string;}[];totalBytes:number;truncated:boolean;};textPreview?:string|null;}export type BlobMetaResponse=ApiResponse<BlobMetaResponseData>;export interface UpdateBlobRequestBody{data:string;format?:'base64'|'hex'|'text';}export interface UpdateBlobResponseData{message:string;size:number;}export type UpdateBlobResponse=ApiResponse<UpdateBlobResponseData>;export interface TableDdlResponseData{table:string;ddl:string;}export type TableDdlResponse=ApiResponse<TableDdlResponseData>;export interface BulkImpactRequestBody{ids:(string|number)[];}export interface BulkImpactReference{table:string; from :string;to:string;count:number;}export interface BulkImpactResponseData{selected:number;references:BulkImpactReference[];total:number;}export type BulkImpactResponse=ApiResponse<BulkImpactResponseData>;export interface BulkDeleteRequestBody{ids:(string|number)[];confirmImpact?:boolean;}export interface BulkDeleteResponseData{message:string;deleted:number;}export type BulkDeleteResponse=ApiResponse<BulkDeleteResponseData>;export interface BulkExportRequestBody{ids:(string|number)[];format?:'csv'|'json';}export interface BulkExportResponseData{format:string;filename:string;content:string;rowCount:number;}export type BulkExportResponse=ApiResponse<BulkExportResponseData>;export interface BulkUpdateItem{id:string|number;values?:Record<string,unknown>;nulls?:string[];}export interface BulkUpdateRequestBody{updates:BulkUpdateItem[];}export interface BulkUpdateResponseData{message:string;updated:number;}export type BulkUpdateResponse=ApiResponse<BulkUpdateResponseData>;export interface SeedConfigResponseData{table:string;columns:ColumnGeneratorConfig[];maxRows:number;}export type SeedConfigResponse=ApiResponse<SeedConfigResponseData>;export interface SeedGenerateRequestBody{count?:number;plan?:Record<string,ColumnPlan>;}export interface SeedGenerateResponseData{table:string;count:number;sql:string;previewRows?:Record<string,unknown>[];warnings:string[];}export type SeedGenerateResponse=ApiResponse<SeedGenerateResponseData>;export interface SeedInsertRequestBody{count?:number;plan?:Record<string,ColumnPlan>;truncate?:boolean;}export interface SeedInsertResponseData{message:string;inserted:number;skipped:number;warnings:string[];elapsedMs?:number;}export type SeedInsertResponse=ApiResponse<SeedInsertResponseData>;export interface CreateTableRequestBody{name:string;columns:ColumnDef[];}export interface CreateTableResponseData{message:string;sql:string;}export type CreateTableResponse=ApiResponse<CreateTableResponseData>;export interface GenerateCreateTableRequestBody{name:string;columns:ColumnDef[];}export interface GenerateCreateTableResponseData{sql:string;}export type GenerateCreateTableResponse=ApiResponse<GenerateCreateTableResponseData>;export type GetSchemaResponseData=SchemaInfo;export type GetSchemaResponse=ApiResponse<GetSchemaResponseData>;export interface RenameTableRequestBody{name:string;}export interface RenameTableResponseData{message:string;sql:string;table:string;}export type RenameTableResponse=ApiResponse<RenameTableResponseData>;export interface AddColumnRequestBody{column:ColumnDef;}export interface AddColumnResponseData{message:string;sql:string;}export type AddColumnResponse=ApiResponse<AddColumnResponseData>;export interface RenameColumnRequestBody{name:string;}export interface RenameColumnResponseData{message:string;sql:string;}export type RenameColumnResponse=ApiResponse<RenameColumnResponseData>;export interface DropColumnResponseData{message:string;sql:string;}export type DropColumnResponse=ApiResponse<DropColumnResponseData>;export interface DropTableResponseData{message:string;sql:string;}export type DropTableResponse=ApiResponse<DropTableResponseData>;export interface CreateIndexRequestBody{name?:string;columns:string[];unique?:boolean;}export interface CreateIndexResponseData{message:string;sql:string;}export type CreateIndexResponse=ApiResponse<CreateIndexResponseData>;export interface DropIndexResponseData{message:string;sql:string;}export type DropIndexResponse=ApiResponse<DropIndexResponseData>;export interface ExecuteQueryRequestBody{sql:string;}export interface QueryCountResult{kind:'count';count:number;message:string;}export interface QuerySelectResult{kind:'select';columns:string[];rows:Record<string,unknown>[];}export interface QueryWriteResult{kind:'write';changes:number|null;message:string;}export type ExecuteQueryResponseData=QueryCountResult|QuerySelectResult|QueryWriteResult;export type ExecuteQueryResponse=ApiResponse<ExecuteQueryResponseData>;export interface ExportQueryRequestBody{sql:string;format?:'csv'|'json';}export type ListSavedQueriesResponseData=SavedQuery[];export type ListSavedQueriesResponse=ApiResponse<ListSavedQueriesResponseData>;export interface SaveQueryRequestBody{name:string;sql:string;}export interface SaveQueryResponseData{message:string;}export type SaveQueryResponse=ApiResponse<SaveQueryResponseData>;export interface DeleteSavedQueryResponseData{message:string;}export type DeleteSavedQueryResponse=ApiResponse<DeleteSavedQueryResponseData>;export interface DatabaseRow extends DatabaseEntry{sizeLabel:string;modifiedLabel:string;tables:number;}export type ListDatabasesResponseData=DatabaseRow[];export type ListDatabasesResponse=ApiResponse<ListDatabasesResponseData>;export interface CreateDatabaseRequestBody{name:string;}export interface CreateDatabaseResponseData{id:string;message:string;}export type CreateDatabaseResponse=ApiResponse<CreateDatabaseResponseData>;export interface OpenDatabaseRequestBody{path:string;}export interface OpenDatabaseResponseData{id:string;message:string;}export type OpenDatabaseResponse=ApiResponse<OpenDatabaseResponseData>;export interface DeleteDatabaseResponseData{message:string;}export type DeleteDatabaseResponse=ApiResponse<DeleteDatabaseResponseData>;export interface FsEntry{name:string;path:string;isDir:boolean;isDb:boolean;size:number;}export interface ListFsResponseData{path:string;name:string;parent:string|null;entries:FsEntry[];}export type ListFsResponse=ApiResponse<ListFsResponseData>;
|
package/dist/types/api.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/utils/colors.js
CHANGED
|
@@ -1 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.c = void 0;
|
|
4
|
+
exports.supportsColor = supportsColor;
|
|
5
|
+
function supportsColor() {
|
|
6
|
+
if (process.env.NO_COLOR || process.env.NODE_DISABLE_COLORS)
|
|
7
|
+
return false;
|
|
8
|
+
if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0')
|
|
9
|
+
return true;
|
|
10
|
+
if (process.env.TERM === 'dumb')
|
|
11
|
+
return false;
|
|
12
|
+
if (process.env.CI)
|
|
13
|
+
return true;
|
|
14
|
+
return Boolean(process.stdout && process.stdout.isTTY);
|
|
15
|
+
}
|
|
16
|
+
const wrap = (open, close) => (str) => {
|
|
17
|
+
const text = String(str ?? '');
|
|
18
|
+
if (!supportsColor() || !text)
|
|
19
|
+
return text;
|
|
20
|
+
return `${open}${text}${close}`;
|
|
21
|
+
};
|
|
22
|
+
exports.c = {
|
|
23
|
+
reset: wrap('\x1b[0m', '\x1b[0m'),
|
|
24
|
+
bold: wrap('\x1b[1m', '\x1b[22m'),
|
|
25
|
+
dim: wrap('\x1b[2m', '\x1b[22m'),
|
|
26
|
+
italic: wrap('\x1b[3m', '\x1b[23m'),
|
|
27
|
+
underline: wrap('\x1b[4m', '\x1b[24m'),
|
|
28
|
+
inverse: wrap('\x1b[7m', '\x1b[27m'),
|
|
29
|
+
black: wrap('\x1b[30m', '\x1b[39m'),
|
|
30
|
+
red: wrap('\x1b[31m', '\x1b[39m'),
|
|
31
|
+
green: wrap('\x1b[32m', '\x1b[39m'),
|
|
32
|
+
yellow: wrap('\x1b[33m', '\x1b[39m'),
|
|
33
|
+
blue: wrap('\x1b[34m', '\x1b[39m'),
|
|
34
|
+
magenta: wrap('\x1b[35m', '\x1b[39m'),
|
|
35
|
+
cyan: wrap('\x1b[36m', '\x1b[39m'),
|
|
36
|
+
white: wrap('\x1b[37m', '\x1b[39m'),
|
|
37
|
+
gray: wrap('\x1b[90m', '\x1b[39m'),
|
|
38
|
+
brightRed: wrap('\x1b[91m', '\x1b[39m'),
|
|
39
|
+
brightGreen: wrap('\x1b[92m', '\x1b[39m'),
|
|
40
|
+
brightYellow: wrap('\x1b[93m', '\x1b[39m'),
|
|
41
|
+
brightBlue: wrap('\x1b[94m', '\x1b[39m'),
|
|
42
|
+
brightMagenta: wrap('\x1b[95m', '\x1b[39m'),
|
|
43
|
+
brightCyan: wrap('\x1b[96m', '\x1b[39m'),
|
|
44
|
+
brightWhite: wrap('\x1b[97m', '\x1b[39m'),
|
|
45
|
+
bgBlack: wrap('\x1b[40m', '\x1b[49m'),
|
|
46
|
+
bgRed: wrap('\x1b[41m', '\x1b[49m'),
|
|
47
|
+
bgGreen: wrap('\x1b[42m', '\x1b[49m'),
|
|
48
|
+
bgYellow: wrap('\x1b[43m', '\x1b[49m'),
|
|
49
|
+
bgBlue: wrap('\x1b[44m', '\x1b[49m'),
|
|
50
|
+
bgMagenta: wrap('\x1b[45m', '\x1b[49m'),
|
|
51
|
+
bgCyan: wrap('\x1b[46m', '\x1b[49m'),
|
|
52
|
+
bgWhite: wrap('\x1b[47m', '\x1b[49m'),
|
|
53
|
+
bgGray: wrap('\x1b[100m', '\x1b[49m'),
|
|
54
|
+
};
|
package/dist/utils/common.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const errorMessage:(err:unknown)=>string;export declare const isPostgresConnectionString:(target:unknown)=>boolean;export declare function sanitizeConnectionString(conn:string):string;export declare function isPathWithinRoot(root:string,p:string):boolean;export type FilterOp='eq'|'neq'|'gt'|'gte'|'lt'|'lte'|'like'|'prefix'|'between'|'null'|'notnull';export interface FilterCondition{op:FilterOp;value?:string;max?:string;}export type FilterValue=string|FilterCondition|FilterCondition[];export interface RowFilters{[column:string]:FilterValue;}export declare function parseFilters(raw:unknown):RowFilters;export declare function filtersToQS(filters:RowFilters|undefined):string;export declare const isInternalTable:(name:string)=>boolean;export declare const encodePk:(values:unknown[])=>string;export declare const decodePk:(encoded:string)=>string[];export declare function normalizeCell(value:unknown):unknown;export declare function normalizeRow(row:Record<string,unknown>):Record<string,unknown>;export declare function coerceFormValue(raw:unknown,columnType:string,dialect?:'sqlite'|'postgres'):unknown;export declare function formatBytes(bytes:number):string;export declare const truncate:(str:string,maxLength:number)=>string;
|
package/dist/utils/common.js
CHANGED
|
@@ -1 +1,185 @@
|
|
|
1
|
-
|
|
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.truncate = exports.decodePk = exports.encodePk = exports.isInternalTable = exports.isPostgresConnectionString = exports.errorMessage = void 0;
|
|
7
|
+
exports.sanitizeConnectionString = sanitizeConnectionString;
|
|
8
|
+
exports.isPathWithinRoot = isPathWithinRoot;
|
|
9
|
+
exports.parseFilters = parseFilters;
|
|
10
|
+
exports.filtersToQS = filtersToQS;
|
|
11
|
+
exports.normalizeCell = normalizeCell;
|
|
12
|
+
exports.normalizeRow = normalizeRow;
|
|
13
|
+
exports.coerceFormValue = coerceFormValue;
|
|
14
|
+
exports.formatBytes = formatBytes;
|
|
15
|
+
const node_fs_1 = require("node:fs");
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
+
const errorMessage = (err) => (err instanceof Error ? err.message : String(err));
|
|
18
|
+
exports.errorMessage = errorMessage;
|
|
19
|
+
const isPostgresConnectionString = (target) => typeof target === 'string' && /^(postgres|postgresql):\/\//.test(target);
|
|
20
|
+
exports.isPostgresConnectionString = isPostgresConnectionString;
|
|
21
|
+
function sanitizeConnectionString(conn) {
|
|
22
|
+
if (!conn || typeof conn !== 'string')
|
|
23
|
+
return '';
|
|
24
|
+
try {
|
|
25
|
+
const u = new URL(conn);
|
|
26
|
+
if (u.password) {
|
|
27
|
+
u.password = '****';
|
|
28
|
+
return u.toString();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch { }
|
|
32
|
+
return conn.replace(/:([^:@]+)@/, ':****@');
|
|
33
|
+
}
|
|
34
|
+
function isPathWithinRoot(root, p) {
|
|
35
|
+
if (!root || !p || typeof root !== 'string' || typeof p !== 'string' || p.includes('\0') || root.includes('\0')) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const resolveReal = (target) => {
|
|
39
|
+
const abs = node_path_1.default.resolve(target);
|
|
40
|
+
try {
|
|
41
|
+
if ((0, node_fs_1.existsSync)(abs))
|
|
42
|
+
return (0, node_fs_1.realpathSync)(abs);
|
|
43
|
+
}
|
|
44
|
+
catch { }
|
|
45
|
+
return abs;
|
|
46
|
+
};
|
|
47
|
+
const rel = node_path_1.default.relative(resolveReal(root), resolveReal(p));
|
|
48
|
+
return rel === '' || (!rel.startsWith('..') && !node_path_1.default.isAbsolute(rel));
|
|
49
|
+
}
|
|
50
|
+
function parseFilters(raw) {
|
|
51
|
+
const out = {};
|
|
52
|
+
const add = (obj) => {
|
|
53
|
+
if (obj && typeof obj === 'object') {
|
|
54
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
55
|
+
if (v === undefined || v === null || v === '')
|
|
56
|
+
continue;
|
|
57
|
+
if (Array.isArray(v)) {
|
|
58
|
+
if (v.length)
|
|
59
|
+
out[k] = v;
|
|
60
|
+
}
|
|
61
|
+
else if (typeof v === 'object') {
|
|
62
|
+
out[k] = v;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
out[k] = String(v);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
if (typeof raw === 'string' && raw) {
|
|
71
|
+
try {
|
|
72
|
+
add(JSON.parse(raw));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
add(raw);
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
function filtersToQS(filters) {
|
|
84
|
+
const out = {};
|
|
85
|
+
for (const [k, v] of Object.entries(filters ?? {})) {
|
|
86
|
+
if (v === undefined || v === null)
|
|
87
|
+
continue;
|
|
88
|
+
if (Array.isArray(v)) {
|
|
89
|
+
if (v.length)
|
|
90
|
+
out[k] = v;
|
|
91
|
+
}
|
|
92
|
+
else if (typeof v === 'object') {
|
|
93
|
+
if (Object.keys(v).length)
|
|
94
|
+
out[k] = v;
|
|
95
|
+
}
|
|
96
|
+
else if (String(v).trim() !== '') {
|
|
97
|
+
out[k] = String(v).trim();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return Object.keys(out).length ? `f=${encodeURIComponent(JSON.stringify(out))}` : '';
|
|
101
|
+
}
|
|
102
|
+
const isInternalTable = (name) => name.startsWith('_');
|
|
103
|
+
exports.isInternalTable = isInternalTable;
|
|
104
|
+
const encodePk = (values) => values.map((v) => encodeURIComponent(v == null ? '' : String(v))).join(',');
|
|
105
|
+
exports.encodePk = encodePk;
|
|
106
|
+
const decodePk = (encoded) => String(encoded)
|
|
107
|
+
.split(',')
|
|
108
|
+
.map((s) => {
|
|
109
|
+
try {
|
|
110
|
+
return decodeURIComponent(s);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return s;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
exports.decodePk = decodePk;
|
|
117
|
+
function normalizeCell(value) {
|
|
118
|
+
if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
|
|
119
|
+
return `0x${Buffer.from(value).toString('hex')}`;
|
|
120
|
+
}
|
|
121
|
+
if (value instanceof Date)
|
|
122
|
+
return value.toISOString();
|
|
123
|
+
if (typeof value === 'object' && value !== null)
|
|
124
|
+
return JSON.stringify(value);
|
|
125
|
+
return value ?? null;
|
|
126
|
+
}
|
|
127
|
+
function normalizeRow(row) {
|
|
128
|
+
const out = {};
|
|
129
|
+
for (const [k, v] of Object.entries(row ?? {}))
|
|
130
|
+
out[k] = normalizeCell(v);
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
function coerceFormValue(raw, columnType, dialect = 'sqlite') {
|
|
134
|
+
if (raw === undefined || raw === null)
|
|
135
|
+
return null;
|
|
136
|
+
const type = (columnType || '').toUpperCase();
|
|
137
|
+
if (type === 'BOOLEAN' || type === 'BOOL') {
|
|
138
|
+
const s = String(raw).trim().toLowerCase();
|
|
139
|
+
if (s === '')
|
|
140
|
+
return null;
|
|
141
|
+
const boolVal = s === 'true' || s === '1' || s === 'on' || s === 'yes' || s === 'checked';
|
|
142
|
+
return dialect === 'postgres' ? boolVal : (boolVal ? 1 : 0);
|
|
143
|
+
}
|
|
144
|
+
if (type.startsWith('INT') ||
|
|
145
|
+
type === 'REAL' ||
|
|
146
|
+
type === 'NUMERIC' ||
|
|
147
|
+
type.startsWith('DECIMAL') ||
|
|
148
|
+
type === 'FLOAT' ||
|
|
149
|
+
type === 'DOUBLE' ||
|
|
150
|
+
type.startsWith('BIGINT') ||
|
|
151
|
+
type.startsWith('SMALLINT') ||
|
|
152
|
+
type.startsWith('SERIAL')) {
|
|
153
|
+
const s = String(raw).trim();
|
|
154
|
+
if (s === '')
|
|
155
|
+
return null;
|
|
156
|
+
const n = Number(s);
|
|
157
|
+
return Number.isFinite(n) ? n : s;
|
|
158
|
+
}
|
|
159
|
+
if (type === 'BLOB' || type === 'BYTEA') {
|
|
160
|
+
const s = String(raw);
|
|
161
|
+
return /^(0x|\\x)[0-9a-f]*$/i.test(s) ? Buffer.from(s.slice(2), 'hex') : Buffer.from(s, 'utf8');
|
|
162
|
+
}
|
|
163
|
+
if (type === 'JSON' || type === 'JSONB') {
|
|
164
|
+
const s = String(raw).trim();
|
|
165
|
+
return s === '' ? null : s;
|
|
166
|
+
}
|
|
167
|
+
if (type.endsWith('[]') || type.startsWith('_') || type.includes('ARRAY')) {
|
|
168
|
+
if (Array.isArray(raw))
|
|
169
|
+
return raw;
|
|
170
|
+
const s = String(raw).trim();
|
|
171
|
+
return s === '' ? null : s;
|
|
172
|
+
}
|
|
173
|
+
const s = String(raw);
|
|
174
|
+
return s === '' ? null : s;
|
|
175
|
+
}
|
|
176
|
+
function formatBytes(bytes) {
|
|
177
|
+
if (bytes === 0)
|
|
178
|
+
return '0 B';
|
|
179
|
+
const k = 1024;
|
|
180
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
181
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
182
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
|
183
|
+
}
|
|
184
|
+
const truncate = (str, maxLength) => !str || str.length <= maxLength ? str : `${str.slice(0, maxLength)}…`;
|
|
185
|
+
exports.truncate = truncate;
|
package/dist/utils/csv.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function csvEscape(value:unknown):string;export declare
|
|
1
|
+
export declare function csvEscape(value:unknown):string;export declare const toCsv:(rows:Record<string,unknown>[],columns:string[])=>string;export declare const toJson:(rows:Record<string,unknown>[])=>string;export declare function parseCsv(text:string):string[][];
|