admindb 2.1.1 → 2.2.1

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 (91) hide show
  1. package/README.md +41 -12
  2. package/dist/app.js +230 -1
  3. package/dist/auth/config.js +121 -1
  4. package/dist/auth/crypto.js +108 -1
  5. package/dist/auth/index.js +21 -1
  6. package/dist/auth/middleware.js +85 -1
  7. package/dist/auth/routes.js +70 -1
  8. package/dist/auth/types.js +7 -1
  9. package/dist/cli/args.js +320 -1
  10. package/dist/cli/config.js +128 -1
  11. package/dist/cli/index.js +20 -1
  12. package/dist/cli/runner.js +211 -1
  13. package/dist/cli.js +4 -1
  14. package/dist/data/chain.d.ts +1 -0
  15. package/dist/data/chain.js +707 -0
  16. package/dist/data/datasets.js +129 -1
  17. package/dist/data/detector.d.ts +1 -1
  18. package/dist/data/detector.js +511 -1
  19. package/dist/data/engine.d.ts +1 -1
  20. package/dist/data/engine.js +245 -1
  21. package/dist/data/index.d.ts +1 -1
  22. package/dist/data/index.js +22 -1
  23. package/dist/data/strategies.d.ts +1 -1
  24. package/dist/data/strategies.js +339 -1
  25. package/dist/data/types.d.ts +1 -1
  26. package/dist/data/types.js +5 -1
  27. package/dist/db/database.d.ts +1 -1
  28. package/dist/db/database.js +477 -1
  29. package/dist/db/export.d.ts +1 -1
  30. package/dist/db/export.js +90 -1
  31. package/dist/db/filters.js +142 -1
  32. package/dist/db/index.js +24 -1
  33. package/dist/db/introspection.js +167 -1
  34. package/dist/db/manager.js +351 -1
  35. package/dist/db/migrations.js +107 -1
  36. package/dist/db/postgres.d.ts +1 -1
  37. package/dist/db/postgres.js +735 -1
  38. package/dist/db/types.d.ts +1 -1
  39. package/dist/db/types.js +6 -1
  40. package/dist/index.js +52 -1
  41. package/dist/public/css/app.css +1 -1
  42. package/dist/public/js/api.js +1 -1
  43. package/dist/public/js/browse.js +1 -1
  44. package/dist/public/js/common.js +1 -0
  45. package/dist/public/js/databases.js +1 -1
  46. package/dist/public/js/designer.js +1 -1
  47. package/dist/public/js/forms.js +1 -1
  48. package/dist/public/js/home.js +1 -0
  49. package/dist/public/js/inspector.js +1 -1
  50. package/dist/public/js/query.js +1 -1
  51. package/dist/public/js/schema.js +1 -1
  52. package/dist/public/js/seed.js +1 -1
  53. package/dist/routes/api/erd.d.ts +1 -0
  54. package/dist/routes/api/erd.js +50 -0
  55. package/dist/routes/api/helpers.d.ts +1 -1
  56. package/dist/routes/api/helpers.js +163 -1
  57. package/dist/routes/api/import-export.js +83 -1
  58. package/dist/routes/api/index.js +48 -1
  59. package/dist/routes/api/query.js +78 -1
  60. package/dist/routes/api/rows.js +362 -1
  61. package/dist/routes/api/seed.js +153 -1
  62. package/dist/routes/api/tables.js +231 -1
  63. package/dist/routes/databases.js +228 -1
  64. package/dist/routes/index.js +19 -1
  65. package/dist/routes/pages.js +397 -1
  66. package/dist/serverless.js +174 -1
  67. package/dist/sql/classifier.js +24 -1
  68. package/dist/sql/error-analyzer.d.ts +1 -0
  69. package/dist/sql/error-analyzer.js +550 -0
  70. package/dist/sql/generator.js +319 -1
  71. package/dist/sql/index.js +18 -1
  72. package/dist/types/api.js +2 -1
  73. package/dist/utils/colors.js +54 -1
  74. package/dist/utils/common.d.ts +1 -1
  75. package/dist/utils/common.js +225 -1
  76. package/dist/utils/csv.js +67 -1
  77. package/dist/utils/datatype.js +181 -1
  78. package/dist/utils/icons.js +81 -1
  79. package/dist/utils/index.js +20 -1
  80. package/dist/utils/logger.js +36 -1
  81. package/dist/views/layouts/main.hbs +14 -1
  82. package/dist/views/pages/erd.hbs +1241 -0
  83. package/dist/views/pages/home.hbs +98 -2
  84. package/dist/views/pages/info.hbs +107 -0
  85. package/dist/views/pages/query.hbs +54 -12
  86. package/dist/views/pages/seed.hbs +435 -171
  87. package/dist/views/partials/sidebar.hbs +12 -0
  88. package/docs/API.md +6 -1
  89. package/docs/EXAMPLES.md +3 -0
  90. package/package.json +5 -4
  91. package/dist/public/js/icons.js +0 -1
@@ -1 +1,319 @@
1
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.DESIGNER_TYPES=exports.POSTGRES_DESIGNER_TYPES=exports.SQLITE_DESIGNER_TYPES=void 0,exports.getDesignerTypes=function(dialect="sqlite"){return"postgres"===dialect?exports.POSTGRES_DESIGNER_TYPES:exports.SQLITE_DESIGNER_TYPES},exports.quoteIdentifier=quoteIdentifier,exports.escapeString=escapeString,exports.sqlValue=sqlValue,exports.mapColumnType=mapColumnType,exports.formatSqlDefault=formatSqlDefault,exports.renderColumnDef=renderColumnDef,exports.generateCreateTable=function(tableName,columns){const table=String(tableName??"").trim();if(validateIdentifier("table",table),!Array.isArray(columns)||0===columns.length)throw new Error("At least one column is required.");const seen=new Set;let pkCount=0;const parts=[];for(const col of columns){const colName=String(col?.name??"").trim();if(validateIdentifier("column",colName),seen.has(colName))throw new Error(`Duplicate column name: "${colName}".`);seen.add(colName),col.primaryKey&&(pkCount+=1),parts.push(renderColumnDef(col))}if(pkCount>1)throw new Error("At most one primary key column is allowed.");return`CREATE TABLE ${quoteIdentifier(table)} (\n ${parts.join(",\n ")}\n);`},exports.generateAddColumn=function(tableName,col){const table=String(tableName??"").trim();validateIdentifier("table",table);const def=renderColumnDef(col,{forAddColumn:!0});return`ALTER TABLE ${quoteIdentifier(table)} ADD COLUMN ${def};`},exports.generateRenameTable=function(tableName,newName){return validateIdentifier("table",tableName),validateIdentifier("table",newName),`ALTER TABLE ${quoteIdentifier(tableName)} RENAME TO ${quoteIdentifier(newName)};`},exports.generateRenameColumn=function(tableName,oldName,newName){return validateIdentifier("table",tableName),validateIdentifier("column",oldName),validateIdentifier("column",newName),`ALTER TABLE ${quoteIdentifier(tableName)} RENAME COLUMN ${quoteIdentifier(oldName)} TO ${quoteIdentifier(newName)};`},exports.generateDropColumn=function(tableName,column){return validateIdentifier("table",tableName),validateIdentifier("column",column),`ALTER TABLE ${quoteIdentifier(tableName)} DROP COLUMN ${quoteIdentifier(column)};`},exports.generateDropTable=function(tableName){return validateIdentifier("table",tableName),`DROP TABLE ${quoteIdentifier(tableName)};`},exports.generateCreateIndex=function(tableName,index){validateIdentifier("table",tableName);const cols=Array.isArray(index?.columns)?index.columns:[];if(!cols.length)throw new Error("At least one column is required for an index.");for(const c of cols)validateIdentifier("column",c);const unique=index.unique?"UNIQUE ":"";let name=String(index?.name??"").trim();name||(name=`idx_${tableName}_${cols.join("_")}`);return validateIdentifier("index",name),`CREATE ${unique}INDEX ${quoteIdentifier(name)} ON ${quoteIdentifier(tableName)} (${cols.map(quoteIdentifier).join(", ")});`},exports.generateDropIndex=function(indexName){return validateIdentifier("index",indexName),`DROP INDEX ${quoteIdentifier(indexName)};`},exports.generateInsert=function(table,fields){const cols=fields.map(f=>quoteIdentifier(f.column)),vals=fields.map(f=>sqlValue(f.value));return`INSERT INTO ${quoteIdentifier(table)} (${cols.join(", ")}) VALUES (${vals.join(", ")});`},exports.generateUpdate=function(table,fields,where){const sets=fields.map(f=>`${quoteIdentifier(f.column)} = ${sqlValue(f.value)}`),conds=where.map(w=>`${quoteIdentifier(w.column)} = ${sqlValue(w.value)}`);return`UPDATE ${quoteIdentifier(table)} SET ${sets.join(", ")} WHERE ${conds.join(" AND ")};`},exports.SQLITE_DESIGNER_TYPES=["TEXT","INTEGER","REAL","BLOB","BOOLEAN","DATE","DATETIME","NUMERIC","VARCHAR(255)","JSON"],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"],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"];const IDENTIFIER_RE=/^[A-Za-z_][A-Za-z0-9_$]*$/;function quoteIdentifier(identifier){return`"${String(identifier).replace(/"/g,'""')}"`}function escapeString(value){return`'${String(value).replace(/'/g,"''")}'`}function sqlValue(value){return null==value?"NULL":"number"==typeof value?Number.isFinite(value)?String(value):"NULL":"bigint"==typeof value?String(value):"boolean"==typeof value?value?"1":"0":value instanceof Uint8Array?`X'${Buffer.from(value).toString("hex")}'`:value instanceof Date?escapeString(value.toISOString()):escapeString(String(value))}function mapColumnType(type){const t=String(type??"").trim().toUpperCase();if(!t)return{sqlType:"TEXT"};switch(t){case"INTEGER":case"INT":case"TINYINT":case"BOOLEAN":case"BOOL":return{sqlType:"INTEGER"};case"BIGINT":case"SMALLINT":case"SERIAL":case"BIGSERIAL":case"SMALLSERIAL":case"TIMESTAMP":case"TIMESTAMPTZ":case"TIMESTAMP WITHOUT TIME ZONE":case"TIMESTAMP WITH TIME ZONE":case"TIME":case"TIMETZ":case"TIME WITHOUT TIME ZONE":case"TIME WITH TIME ZONE":case"INTERVAL":case"JSON":case"JSONB":case"UUID":case"INET":case"CIDR":case"MACADDR":case"SERIAL":case"BIGSERIAL":case"SMALLSERIAL":return{sqlType:t};case"TEXT":case"VARCHAR":case"CHAR":case"CLOB":case"STRING":case"CITEXT":return{sqlType:"TEXT"};case"REAL":case"FLOAT":case"DOUBLE":case"DECIMAL":case"NUMERIC":case"NUMBER":case"MONEY":return{sqlType:"REAL"};case"BLOB":case"BINARY":case"VARBINARY":return{sqlType:"BLOB"};case"BYTEA":return{sqlType:"BYTEA"};case"DATE":return{sqlType:"DATETIME",defaultAuto:"CURRENT_TIMESTAMP"};case"DATETIME":return{sqlType:"DATETIME"};default:if(/^[A-Za-z0-9_(),\s\[\]]+$/.test(t))return{sqlType:t};throw new Error(`Unsupported column type: "${type}". Supported types include: ${exports.DESIGNER_TYPES.join(", ")} or standard SQL types.`)}}function validateIdentifier(kind,name){const label=kind.charAt(0).toUpperCase()+kind.slice(1),trimmed=String(name??"").trim();if(!trimmed)throw new Error(`${label} name is required.`);if(!IDENTIFIER_RE.test(trimmed))throw new Error(`Invalid ${label.toLowerCase()} name: "${trimmed}". Use letters, digits and underscores.`)}function formatSqlDefault(raw,colType){const s=String(raw??"").trim().replace(/;/g,"");if(!s)return"";if(/^null$/i.test(s))return"NULL";if(/^[-+]?\d+(\.\d+)?$/.test(s))return s;if(/^(true|false)$/i.test(s))return"TRUE"===s.toUpperCase()?"1":"0";if(/^'.*'$/s.test(s)||/^".*"$/s.test(s))return s;if(/^[a-zA-Z_]\w*\s*\(.*\)$/s.test(s))return s;if(/^CURRENT_TIMESTAMP|CURRENT_DATE|CURRENT_TIME$/i.test(s))return s.toUpperCase();const t=(colType||"").toUpperCase();return t.includes("TEXT")||t.includes("CHAR")||t.includes("CLOB")||t.includes("VARCHAR")||t.includes("STRING")?escapeString(s):s}function renderColumnDef(col,opts={}){const colName=String(col?.name??"").trim();validateIdentifier("column",colName);const mapped=mapColumnType(col.type);if(opts.forAddColumn){if(col.primaryKey)throw new Error(`Cannot add "${colName}" as PRIMARY KEY: ALTER TABLE ADD COLUMN does not support primary keys.`);if(col.unique)throw new Error(`Cannot add "${colName}" with UNIQUE: ALTER TABLE ADD COLUMN does not support UNIQUE constraints.`)}let def=`${quoteIdentifier(colName)} ${mapped.sqlType}`;!opts.forAddColumn&&col.primaryKey&&(def+=" PRIMARY KEY"),col.notNull&&(def+=" NOT NULL"),!opts.forAddColumn&&col.unique&&(def+=" UNIQUE");const dflt=formatSqlDefault(String(col.defaultValue??""),col.type)||mapped.defaultAuto||"";if(dflt)def+=` DEFAULT ${dflt}`;else if(opts.forAddColumn&&col.notNull)throw new Error(`Cannot add "${colName}" as NOT NULL without a default value.`);if(col.foreignKey?.table&&col.foreignKey.column){if(opts.forAddColumn&&(col.notNull||dflt))throw new Error(`Cannot add "${colName}" as a foreign key with NOT NULL or a non-NULL default.`);def+=` REFERENCES ${quoteIdentifier(col.foreignKey.table)}(${quoteIdentifier(col.foreignKey.column)})`}return def}
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DESIGNER_TYPES = exports.POSTGRES_DESIGNER_TYPES = exports.SQLITE_DESIGNER_TYPES = void 0;
4
+ exports.getDesignerTypes = getDesignerTypes;
5
+ exports.quoteIdentifier = quoteIdentifier;
6
+ exports.escapeString = escapeString;
7
+ exports.sqlValue = sqlValue;
8
+ exports.mapColumnType = mapColumnType;
9
+ exports.formatSqlDefault = formatSqlDefault;
10
+ exports.renderColumnDef = renderColumnDef;
11
+ exports.generateCreateTable = generateCreateTable;
12
+ exports.generateAddColumn = generateAddColumn;
13
+ exports.generateRenameTable = generateRenameTable;
14
+ exports.generateRenameColumn = generateRenameColumn;
15
+ exports.generateDropColumn = generateDropColumn;
16
+ exports.generateDropTable = generateDropTable;
17
+ exports.generateCreateIndex = generateCreateIndex;
18
+ exports.generateDropIndex = generateDropIndex;
19
+ exports.generateInsert = generateInsert;
20
+ exports.generateUpdate = generateUpdate;
21
+ exports.SQLITE_DESIGNER_TYPES = [
22
+ 'TEXT',
23
+ 'INTEGER',
24
+ 'REAL',
25
+ 'BLOB',
26
+ 'BOOLEAN',
27
+ 'DATE',
28
+ 'DATETIME',
29
+ 'NUMERIC',
30
+ 'VARCHAR(255)',
31
+ 'JSON',
32
+ ];
33
+ exports.POSTGRES_DESIGNER_TYPES = [
34
+ 'TEXT',
35
+ 'VARCHAR(255)',
36
+ 'INTEGER',
37
+ 'BIGINT',
38
+ 'SMALLINT',
39
+ 'SERIAL',
40
+ 'BIGSERIAL',
41
+ 'REAL',
42
+ 'DECIMAL(10,2)',
43
+ 'NUMERIC',
44
+ 'BOOLEAN',
45
+ 'DATE',
46
+ 'DATETIME',
47
+ 'TIMESTAMP',
48
+ 'TIMESTAMPTZ',
49
+ 'TIME',
50
+ 'INTERVAL',
51
+ 'JSON',
52
+ 'JSONB',
53
+ 'UUID',
54
+ 'BYTEA',
55
+ 'INET',
56
+ ];
57
+ exports.DESIGNER_TYPES = [
58
+ 'TEXT',
59
+ 'VARCHAR(255)',
60
+ 'INTEGER',
61
+ 'BIGINT',
62
+ 'SMALLINT',
63
+ 'SERIAL',
64
+ 'BIGSERIAL',
65
+ 'REAL',
66
+ 'DECIMAL(10,2)',
67
+ 'NUMERIC',
68
+ 'BOOLEAN',
69
+ 'DATE',
70
+ 'DATETIME',
71
+ 'TIMESTAMP',
72
+ 'TIMESTAMPTZ',
73
+ 'TIME',
74
+ 'INTERVAL',
75
+ 'JSON',
76
+ 'JSONB',
77
+ 'UUID',
78
+ 'BYTEA',
79
+ 'BLOB',
80
+ 'INET',
81
+ ];
82
+ function getDesignerTypes(dialect = 'sqlite') {
83
+ return dialect === 'postgres' ? exports.POSTGRES_DESIGNER_TYPES : exports.SQLITE_DESIGNER_TYPES;
84
+ }
85
+ const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_$]*$/;
86
+ function quoteIdentifier(identifier) {
87
+ return `"${String(identifier).replace(/"/g, '""')}"`;
88
+ }
89
+ function escapeString(value) {
90
+ return `'${String(value).replace(/'/g, "''")}'`;
91
+ }
92
+ function sqlValue(value) {
93
+ if (value === null || value === undefined)
94
+ return 'NULL';
95
+ if (typeof value === 'number')
96
+ return Number.isFinite(value) ? String(value) : 'NULL';
97
+ if (typeof value === 'bigint')
98
+ return String(value);
99
+ if (typeof value === 'boolean')
100
+ return value ? '1' : '0';
101
+ if (value instanceof Uint8Array)
102
+ return `X'${Buffer.from(value).toString('hex')}'`;
103
+ if (value instanceof Date)
104
+ return escapeString(value.toISOString());
105
+ return escapeString(String(value));
106
+ }
107
+ function mapColumnType(type) {
108
+ const t = String(type ?? '').trim().toUpperCase();
109
+ if (!t)
110
+ return { sqlType: 'TEXT' };
111
+ switch (t) {
112
+ case 'INTEGER':
113
+ case 'INT':
114
+ case 'TINYINT':
115
+ return { sqlType: 'INTEGER' };
116
+ case 'BIGINT':
117
+ case 'SMALLINT':
118
+ case 'SERIAL':
119
+ case 'BIGSERIAL':
120
+ case 'SMALLSERIAL':
121
+ return { sqlType: t };
122
+ case 'TEXT':
123
+ case 'VARCHAR':
124
+ case 'CHAR':
125
+ case 'CLOB':
126
+ case 'STRING':
127
+ case 'CITEXT':
128
+ return { sqlType: 'TEXT' };
129
+ case 'REAL':
130
+ case 'FLOAT':
131
+ case 'DOUBLE':
132
+ case 'DECIMAL':
133
+ case 'NUMERIC':
134
+ case 'NUMBER':
135
+ case 'MONEY':
136
+ return { sqlType: 'REAL' };
137
+ case 'BLOB':
138
+ case 'BINARY':
139
+ case 'VARBINARY':
140
+ return { sqlType: 'BLOB' };
141
+ case 'BYTEA':
142
+ return { sqlType: 'BYTEA' };
143
+ case 'BOOLEAN':
144
+ case 'BOOL':
145
+ return { sqlType: 'INTEGER' };
146
+ case 'DATE':
147
+ return { sqlType: 'DATETIME', defaultAuto: 'CURRENT_TIMESTAMP' };
148
+ case 'DATETIME':
149
+ return { sqlType: 'DATETIME' };
150
+ case 'TIMESTAMP':
151
+ case 'TIMESTAMPTZ':
152
+ case 'TIMESTAMP WITHOUT TIME ZONE':
153
+ case 'TIMESTAMP WITH TIME ZONE':
154
+ return { sqlType: t };
155
+ case 'TIME':
156
+ case 'TIMETZ':
157
+ case 'TIME WITHOUT TIME ZONE':
158
+ case 'TIME WITH TIME ZONE':
159
+ return { sqlType: t };
160
+ case 'INTERVAL':
161
+ case 'JSON':
162
+ case 'JSONB':
163
+ case 'UUID':
164
+ case 'INET':
165
+ case 'CIDR':
166
+ case 'MACADDR':
167
+ case 'SERIAL':
168
+ case 'BIGSERIAL':
169
+ case 'SMALLSERIAL':
170
+ return { sqlType: t };
171
+ default:
172
+ if (/^[A-Za-z0-9_(),\s\[\]]+$/.test(t)) {
173
+ return { sqlType: t };
174
+ }
175
+ throw new Error(`Unsupported column type: "${type}". Supported types include: ${exports.DESIGNER_TYPES.join(', ')} or standard SQL types.`);
176
+ }
177
+ }
178
+ function validateIdentifier(kind, name) {
179
+ const label = kind.charAt(0).toUpperCase() + kind.slice(1);
180
+ const trimmed = String(name ?? '').trim();
181
+ if (!trimmed)
182
+ throw new Error(`${label} name is required.`);
183
+ if (!IDENTIFIER_RE.test(trimmed)) {
184
+ throw new Error(`Invalid ${label.toLowerCase()} name: "${trimmed}". Use letters, digits and underscores.`);
185
+ }
186
+ }
187
+ function formatSqlDefault(raw, colType) {
188
+ const s = String(raw ?? '').trim().replace(/;/g, '');
189
+ if (!s)
190
+ return '';
191
+ if (/^null$/i.test(s))
192
+ return 'NULL';
193
+ if (/^[-+]?\d+(\.\d+)?$/.test(s))
194
+ return s;
195
+ if (/^(true|false)$/i.test(s))
196
+ return s.toUpperCase() === 'TRUE' ? '1' : '0';
197
+ if (/^'.*'$/s.test(s) || /^".*"$/s.test(s))
198
+ return s;
199
+ if (/^[a-zA-Z_]\w*\s*\(.*\)$/s.test(s))
200
+ return s;
201
+ if (/^CURRENT_TIMESTAMP|CURRENT_DATE|CURRENT_TIME$/i.test(s))
202
+ return s.toUpperCase();
203
+ const t = (colType || '').toUpperCase();
204
+ if (t.includes('TEXT') || t.includes('CHAR') || t.includes('CLOB') || t.includes('VARCHAR') || t.includes('STRING')) {
205
+ return escapeString(s);
206
+ }
207
+ return s;
208
+ }
209
+ function renderColumnDef(col, opts = {}) {
210
+ const colName = String(col?.name ?? '').trim();
211
+ validateIdentifier('column', colName);
212
+ const mapped = mapColumnType(col.type);
213
+ if (opts.forAddColumn) {
214
+ if (col.primaryKey) {
215
+ throw new Error(`Cannot add "${colName}" as PRIMARY KEY: ALTER TABLE ADD COLUMN does not support primary keys.`);
216
+ }
217
+ if (col.unique) {
218
+ throw new Error(`Cannot add "${colName}" with UNIQUE: ALTER TABLE ADD COLUMN does not support UNIQUE constraints.`);
219
+ }
220
+ }
221
+ let def = `${quoteIdentifier(colName)} ${mapped.sqlType}`;
222
+ if (!opts.forAddColumn && col.primaryKey)
223
+ def += ' PRIMARY KEY';
224
+ if (col.notNull)
225
+ def += ' NOT NULL';
226
+ if (!opts.forAddColumn && col.unique)
227
+ def += ' UNIQUE';
228
+ const rawDefault = formatSqlDefault(String(col.defaultValue ?? ''), col.type);
229
+ const dflt = rawDefault || mapped.defaultAuto || '';
230
+ if (dflt)
231
+ def += ` DEFAULT ${dflt}`;
232
+ else if (opts.forAddColumn && col.notNull) {
233
+ throw new Error(`Cannot add "${colName}" as NOT NULL without a default value.`);
234
+ }
235
+ if (col.foreignKey?.table && col.foreignKey.column) {
236
+ if (opts.forAddColumn && (col.notNull || dflt)) {
237
+ throw new Error(`Cannot add "${colName}" as a foreign key with NOT NULL or a non-NULL default.`);
238
+ }
239
+ def += ` REFERENCES ${quoteIdentifier(col.foreignKey.table)}(${quoteIdentifier(col.foreignKey.column)})`;
240
+ }
241
+ return def;
242
+ }
243
+ function generateCreateTable(tableName, columns) {
244
+ const table = String(tableName ?? '').trim();
245
+ validateIdentifier('table', table);
246
+ if (!Array.isArray(columns) || columns.length === 0) {
247
+ throw new Error('At least one column is required.');
248
+ }
249
+ const seen = new Set();
250
+ let pkCount = 0;
251
+ const parts = [];
252
+ for (const col of columns) {
253
+ const colName = String(col?.name ?? '').trim();
254
+ validateIdentifier('column', colName);
255
+ if (seen.has(colName))
256
+ throw new Error(`Duplicate column name: "${colName}".`);
257
+ seen.add(colName);
258
+ if (col.primaryKey)
259
+ pkCount += 1;
260
+ parts.push(renderColumnDef(col));
261
+ }
262
+ if (pkCount > 1)
263
+ throw new Error('At most one primary key column is allowed.');
264
+ return `CREATE TABLE ${quoteIdentifier(table)} (\n ${parts.join(',\n ')}\n);`;
265
+ }
266
+ function generateAddColumn(tableName, col) {
267
+ const table = String(tableName ?? '').trim();
268
+ validateIdentifier('table', table);
269
+ const def = renderColumnDef(col, { forAddColumn: true });
270
+ return `ALTER TABLE ${quoteIdentifier(table)} ADD COLUMN ${def};`;
271
+ }
272
+ function generateRenameTable(tableName, newName) {
273
+ validateIdentifier('table', tableName);
274
+ validateIdentifier('table', newName);
275
+ return `ALTER TABLE ${quoteIdentifier(tableName)} RENAME TO ${quoteIdentifier(newName)};`;
276
+ }
277
+ function generateRenameColumn(tableName, oldName, newName) {
278
+ validateIdentifier('table', tableName);
279
+ validateIdentifier('column', oldName);
280
+ validateIdentifier('column', newName);
281
+ return `ALTER TABLE ${quoteIdentifier(tableName)} RENAME COLUMN ${quoteIdentifier(oldName)} TO ${quoteIdentifier(newName)};`;
282
+ }
283
+ function generateDropColumn(tableName, column) {
284
+ validateIdentifier('table', tableName);
285
+ validateIdentifier('column', column);
286
+ return `ALTER TABLE ${quoteIdentifier(tableName)} DROP COLUMN ${quoteIdentifier(column)};`;
287
+ }
288
+ function generateDropTable(tableName) {
289
+ validateIdentifier('table', tableName);
290
+ return `DROP TABLE ${quoteIdentifier(tableName)};`;
291
+ }
292
+ function generateCreateIndex(tableName, index) {
293
+ validateIdentifier('table', tableName);
294
+ const cols = Array.isArray(index?.columns) ? index.columns : [];
295
+ if (!cols.length)
296
+ throw new Error('At least one column is required for an index.');
297
+ for (const c of cols)
298
+ validateIdentifier('column', c);
299
+ const unique = index.unique ? 'UNIQUE ' : '';
300
+ let name = String(index?.name ?? '').trim();
301
+ if (!name)
302
+ name = `idx_${tableName}_${cols.join('_')}`;
303
+ validateIdentifier('index', name);
304
+ return `CREATE ${unique}INDEX ${quoteIdentifier(name)} ON ${quoteIdentifier(tableName)} (${cols.map(quoteIdentifier).join(', ')});`;
305
+ }
306
+ function generateDropIndex(indexName) {
307
+ validateIdentifier('index', indexName);
308
+ return `DROP INDEX ${quoteIdentifier(indexName)};`;
309
+ }
310
+ function generateInsert(table, fields) {
311
+ const cols = fields.map((f) => quoteIdentifier(f.column));
312
+ const vals = fields.map((f) => sqlValue(f.value));
313
+ return `INSERT INTO ${quoteIdentifier(table)} (${cols.join(', ')}) VALUES (${vals.join(', ')});`;
314
+ }
315
+ function generateUpdate(table, fields, where) {
316
+ const sets = fields.map((f) => `${quoteIdentifier(f.column)} = ${sqlValue(f.value)}`);
317
+ const conds = where.map((w) => `${quoteIdentifier(w.column)} = ${sqlValue(w.value)}`);
318
+ return `UPDATE ${quoteIdentifier(table)} SET ${sets.join(', ')} WHERE ${conds.join(' AND ')};`;
319
+ }
package/dist/sql/index.js CHANGED
@@ -1 +1,18 @@
1
- var __createBinding=this&&this.__createBinding||(Object.create?function(o,m,k,k2){void 0===k2&&(k2=k);var desc=Object.getOwnPropertyDescriptor(m,k);desc&&!("get"in desc?!m.__esModule:desc.writable||desc.configurable)||(desc={enumerable:!0,get:function(){return m[k]}}),Object.defineProperty(o,k2,desc)}:function(o,m,k,k2){void 0===k2&&(k2=k),o[k2]=m[k]}),__exportStar=this&&this.__exportStar||function(m,exports){for(var p in m)"default"===p||Object.prototype.hasOwnProperty.call(exports,p)||__createBinding(exports,m,p)};Object.defineProperty(exports,"__esModule",{value:!0}),__exportStar(require("./classifier"),exports),__exportStar(require("./generator"),exports);
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.js CHANGED
@@ -1 +1,2 @@
1
- Object.defineProperty(exports,"__esModule",{value:!0});
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1 +1,54 @@
1
- function supportsColor(){return!process.env.NO_COLOR&&!process.env.NODE_DISABLE_COLORS&&(!(!process.env.FORCE_COLOR||"0"===process.env.FORCE_COLOR)||"dumb"!==process.env.TERM&&(!!process.env.CI||Boolean(process.stdout&&process.stdout.isTTY)))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.c=void 0,exports.supportsColor=supportsColor;const wrap=(open,close)=>str=>{const text=String(str??"");return supportsColor()&&text?`${open}${text}${close}`:text};exports.c={reset:wrap("",""),bold:wrap("",""),dim:wrap("",""),italic:wrap("",""),underline:wrap("",""),inverse:wrap("",""),black:wrap("",""),red:wrap("",""),green:wrap("",""),yellow:wrap("",""),blue:wrap("",""),magenta:wrap("",""),cyan:wrap("",""),white:wrap("",""),gray:wrap("",""),brightRed:wrap("",""),brightGreen:wrap("",""),brightYellow:wrap("",""),brightBlue:wrap("",""),brightMagenta:wrap("",""),brightCyan:wrap("",""),brightWhite:wrap("",""),bgBlack:wrap("",""),bgRed:wrap("",""),bgGreen:wrap("",""),bgYellow:wrap("",""),bgBlue:wrap("",""),bgMagenta:wrap("",""),bgCyan:wrap("",""),bgWhite:wrap("",""),bgGray:wrap("","")};
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
+ };
@@ -1 +1 @@
1
- export declare function errorMessage(err:unknown):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 function isInternalTable(name:string):boolean;export declare function encodePk(values:unknown[]):string;export declare function 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 function truncate(str:string,maxLength:number):string;
1
+ export declare function errorMessage(err:unknown):string;export declare function 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 function isInternalTable(name:string):boolean;export declare function encodePk(values:unknown[]):string;export declare function 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 function truncate(str:string,maxLength:number):string;
@@ -1 +1,225 @@
1
- var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorMessage=function(err){return err instanceof Error?err.message:String(err)},exports.isPathWithinRoot=function(root,p){if(!root||!p||"string"!=typeof root||"string"!=typeof p)return!1;if(p.includes("\0")||root.includes("\0"))return!1;const absRoot=node_path_1.default.resolve(root),absPath=node_path_1.default.resolve(p);let realRoot=absRoot,realPath=absPath;try{(0,node_fs_1.existsSync)(absRoot)&&(realRoot=(0,node_fs_1.realpathSync)(absRoot))}catch{}try{(0,node_fs_1.existsSync)(absPath)&&(realPath=(0,node_fs_1.realpathSync)(absPath))}catch{}const rel=node_path_1.default.relative(realRoot,realPath);return""===rel||!rel.startsWith("..")&&!node_path_1.default.isAbsolute(rel)},exports.parseFilters=function(raw){const out={},add=obj=>{if(obj&&"object"==typeof obj)for(const[k,v]of Object.entries(obj))null!=v&&""!==v&&(Array.isArray(v)?v.length&&(out[k]=v):out[k]="object"==typeof v?v:String(v))};if("string"==typeof raw&&raw)try{add(JSON.parse(raw))}catch{return{}}else add(raw);return out},exports.filtersToQS=function(filters){const out={};for(const[k,v]of Object.entries(filters??{}))null!=v&&(Array.isArray(v)?v.length&&(out[k]=v):"object"!=typeof v?""!==String(v).trim()&&(out[k]=String(v).trim()):Object.keys(v).length&&(out[k]=v));return Object.keys(out).length?"f="+encodeURIComponent(JSON.stringify(out)):""},exports.isInternalTable=function(name){return name.startsWith("_")},exports.encodePk=function(values){return values.map(v=>encodeURIComponent(null==v?"":String(v))).join(",")},exports.decodePk=function(encoded){return String(encoded).split(",").map(s=>{try{return decodeURIComponent(s)}catch{return s}})},exports.normalizeCell=normalizeCell,exports.normalizeRow=function(row){const out={};for(const[k,v]of Object.entries(row??{}))out[k]=normalizeCell(v);return out},exports.coerceFormValue=function(raw,columnType,dialect="sqlite"){const type=(columnType||"").toUpperCase();if(null==raw)return null;if("BOOLEAN"===type||"BOOL"===type){const s=String(raw).trim().toLowerCase();if(""===s)return null;const boolVal="true"===s||"1"===s||"on"===s||"yes"===s||"checked"===s;return"postgres"===dialect?boolVal:boolVal?1:0}if(type.startsWith("INT")||"REAL"===type||"NUMERIC"===type||type.startsWith("DECIMAL")||"FLOAT"===type||"DOUBLE"===type||type.startsWith("BIGINT")||type.startsWith("SMALLINT")||type.startsWith("SERIAL")){const s=String(raw).trim();if(""===s)return null;const n=Number(s);return Number.isFinite(n)?n:s}if("BLOB"===type||"BYTEA"===type){const s=String(raw);return/^0x[0-9a-f]*$/i.test(s)||/^\\x[0-9a-f]*$/i.test(s)?Buffer.from(s.slice(2),"hex"):Buffer.from(s,"utf8")}if("JSON"===type||"JSONB"===type){const s=String(raw).trim();return""===s?null:s}if(type.endsWith("[]")||type.startsWith("_")||type.includes("ARRAY")){if(Array.isArray(raw))return raw;const s=String(raw).trim();return""===s?null:s}const s=String(raw);return""===s?null:s},exports.formatBytes=function(bytes){if(0===bytes)return"0 B";const i=Math.floor(Math.log(bytes)/Math.log(1024));return`${parseFloat((bytes/Math.pow(1024,i)).toFixed(1))} ${["B","KB","MB","GB","TB"][i]}`},exports.truncate=function(str,maxLength){return!str||str.length<=maxLength?str:`${str.slice(0,maxLength)}…`};const node_fs_1=require("node:fs"),node_path_1=__importDefault(require("node:path"));function normalizeCell(value){return value instanceof Uint8Array||Buffer.isBuffer(value)?`0x${Buffer.from(value).toString("hex")}`:value instanceof Date?value.toISOString():"object"==typeof value&&null!==value?JSON.stringify(value):void 0===value?null:value}
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.errorMessage = errorMessage;
7
+ exports.isPostgresConnectionString = isPostgresConnectionString;
8
+ exports.sanitizeConnectionString = sanitizeConnectionString;
9
+ exports.isPathWithinRoot = isPathWithinRoot;
10
+ exports.parseFilters = parseFilters;
11
+ exports.filtersToQS = filtersToQS;
12
+ exports.isInternalTable = isInternalTable;
13
+ exports.encodePk = encodePk;
14
+ exports.decodePk = decodePk;
15
+ exports.normalizeCell = normalizeCell;
16
+ exports.normalizeRow = normalizeRow;
17
+ exports.coerceFormValue = coerceFormValue;
18
+ exports.formatBytes = formatBytes;
19
+ exports.truncate = truncate;
20
+ const node_fs_1 = require("node:fs");
21
+ const node_path_1 = __importDefault(require("node:path"));
22
+ function errorMessage(err) {
23
+ if (err instanceof Error)
24
+ return err.message;
25
+ return String(err);
26
+ }
27
+ function isPostgresConnectionString(target) {
28
+ return (typeof target === 'string' &&
29
+ (target.startsWith('postgres://') || target.startsWith('postgresql://')));
30
+ }
31
+ function sanitizeConnectionString(conn) {
32
+ if (!conn || typeof conn !== 'string')
33
+ return '';
34
+ try {
35
+ const u = new URL(conn);
36
+ if (u.password) {
37
+ u.password = '****';
38
+ return u.toString();
39
+ }
40
+ }
41
+ catch { }
42
+ return conn.replace(/:([^:@]+)@/, ':****@');
43
+ }
44
+ function isPathWithinRoot(root, p) {
45
+ if (!root || !p || typeof root !== 'string' || typeof p !== 'string')
46
+ return false;
47
+ if (p.includes('\0') || root.includes('\0'))
48
+ return false;
49
+ const absRoot = node_path_1.default.resolve(root);
50
+ const absPath = node_path_1.default.resolve(p);
51
+ let realRoot = absRoot;
52
+ let realPath = absPath;
53
+ try {
54
+ if ((0, node_fs_1.existsSync)(absRoot))
55
+ realRoot = (0, node_fs_1.realpathSync)(absRoot);
56
+ }
57
+ catch { }
58
+ try {
59
+ if ((0, node_fs_1.existsSync)(absPath))
60
+ realPath = (0, node_fs_1.realpathSync)(absPath);
61
+ }
62
+ catch { }
63
+ const rel = node_path_1.default.relative(realRoot, realPath);
64
+ return rel === '' || (!rel.startsWith('..') && !node_path_1.default.isAbsolute(rel));
65
+ }
66
+ function parseFilters(raw) {
67
+ const out = {};
68
+ const add = (obj) => {
69
+ if (obj && typeof obj === 'object') {
70
+ for (const [k, v] of Object.entries(obj)) {
71
+ if (v === undefined || v === null || v === '')
72
+ continue;
73
+ if (Array.isArray(v)) {
74
+ if (v.length)
75
+ out[k] = v;
76
+ }
77
+ else if (typeof v === 'object') {
78
+ out[k] = v;
79
+ }
80
+ else {
81
+ out[k] = String(v);
82
+ }
83
+ }
84
+ }
85
+ };
86
+ if (typeof raw === 'string' && raw) {
87
+ try {
88
+ add(JSON.parse(raw));
89
+ }
90
+ catch {
91
+ return {};
92
+ }
93
+ }
94
+ else {
95
+ add(raw);
96
+ }
97
+ return out;
98
+ }
99
+ function filtersToQS(filters) {
100
+ const out = {};
101
+ for (const [k, v] of Object.entries(filters ?? {})) {
102
+ if (v === undefined || v === null)
103
+ continue;
104
+ if (Array.isArray(v)) {
105
+ if (v.length)
106
+ out[k] = v;
107
+ continue;
108
+ }
109
+ if (typeof v === 'object') {
110
+ if (Object.keys(v).length)
111
+ out[k] = v;
112
+ continue;
113
+ }
114
+ if (String(v).trim() !== '')
115
+ out[k] = String(v).trim();
116
+ }
117
+ const keys = Object.keys(out);
118
+ if (!keys.length)
119
+ return '';
120
+ return 'f=' + encodeURIComponent(JSON.stringify(out));
121
+ }
122
+ function isInternalTable(name) {
123
+ return name.startsWith('_');
124
+ }
125
+ function encodePk(values) {
126
+ return values.map((v) => encodeURIComponent(v == null ? '' : String(v))).join(',');
127
+ }
128
+ function decodePk(encoded) {
129
+ return String(encoded)
130
+ .split(',')
131
+ .map((s) => {
132
+ try {
133
+ return decodeURIComponent(s);
134
+ }
135
+ catch {
136
+ return s;
137
+ }
138
+ });
139
+ }
140
+ function normalizeCell(value) {
141
+ if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
142
+ return `0x${Buffer.from(value).toString('hex')}`;
143
+ }
144
+ if (value instanceof Date) {
145
+ return value.toISOString();
146
+ }
147
+ if (typeof value === 'object' && value !== null) {
148
+ return JSON.stringify(value);
149
+ }
150
+ if (value === undefined)
151
+ return null;
152
+ return value;
153
+ }
154
+ function normalizeRow(row) {
155
+ const out = {};
156
+ for (const [k, v] of Object.entries(row ?? {}))
157
+ out[k] = normalizeCell(v);
158
+ return out;
159
+ }
160
+ function coerceFormValue(raw, columnType, dialect = 'sqlite') {
161
+ const type = (columnType || '').toUpperCase();
162
+ if (raw === undefined || raw === null)
163
+ return null;
164
+ if (type === 'BOOLEAN' || type === 'BOOL') {
165
+ const s = String(raw).trim().toLowerCase();
166
+ if (s === '')
167
+ return null;
168
+ const boolVal = s === 'true' || s === '1' || s === 'on' || s === 'yes' || s === 'checked';
169
+ return dialect === 'postgres' ? boolVal : (boolVal ? 1 : 0);
170
+ }
171
+ if (type.startsWith('INT') ||
172
+ type === 'REAL' ||
173
+ type === 'NUMERIC' ||
174
+ type.startsWith('DECIMAL') ||
175
+ type === 'FLOAT' ||
176
+ type === 'DOUBLE' ||
177
+ type.startsWith('BIGINT') ||
178
+ type.startsWith('SMALLINT') ||
179
+ type.startsWith('SERIAL')) {
180
+ const s = String(raw).trim();
181
+ if (s === '')
182
+ return null;
183
+ const n = Number(s);
184
+ return Number.isFinite(n) ? n : s;
185
+ }
186
+ if (type === 'BLOB' || type === 'BYTEA') {
187
+ const s = String(raw);
188
+ if (/^0x[0-9a-f]*$/i.test(s))
189
+ return Buffer.from(s.slice(2), 'hex');
190
+ if (/^\\x[0-9a-f]*$/i.test(s))
191
+ return Buffer.from(s.slice(2), 'hex');
192
+ return Buffer.from(s, 'utf8');
193
+ }
194
+ if (type === 'JSON' || type === 'JSONB') {
195
+ const s = String(raw).trim();
196
+ if (s === '')
197
+ return null;
198
+ return s;
199
+ }
200
+ if (type.endsWith('[]') || type.startsWith('_') || type.includes('ARRAY')) {
201
+ if (Array.isArray(raw))
202
+ return raw;
203
+ const s = String(raw).trim();
204
+ if (s === '')
205
+ return null;
206
+ return s;
207
+ }
208
+ const s = String(raw);
209
+ if (s === '')
210
+ return null;
211
+ return s;
212
+ }
213
+ function formatBytes(bytes) {
214
+ if (bytes === 0)
215
+ return '0 B';
216
+ const k = 1024;
217
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
218
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
219
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
220
+ }
221
+ function truncate(str, maxLength) {
222
+ if (!str || str.length <= maxLength)
223
+ return str;
224
+ return `${str.slice(0, maxLength)}…`;
225
+ }