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.
Files changed (119) hide show
  1. package/README.md +368 -335
  2. package/dist/app.js +227 -1
  3. package/dist/auth/config.d.ts +1 -1
  4. package/dist/auth/config.js +109 -1
  5. package/dist/auth/crypto.js +98 -1
  6. package/dist/auth/index.js +21 -1
  7. package/dist/auth/middleware.js +78 -1
  8. package/dist/auth/routes.js +64 -1
  9. package/dist/auth/types.js +7 -1
  10. package/dist/cli/args.d.ts +1 -1
  11. package/dist/cli/args.js +309 -1
  12. package/dist/cli/config.js +118 -1
  13. package/dist/cli/index.js +20 -1
  14. package/dist/cli/runner.js +208 -1
  15. package/dist/cli.js +4 -1
  16. package/dist/data/chain.d.ts +1 -0
  17. package/dist/data/chain.js +130 -0
  18. package/dist/data/datasets.d.ts +1 -1
  19. package/dist/data/datasets.js +171 -1
  20. package/dist/data/detector.d.ts +1 -1
  21. package/dist/data/detector.js +535 -1
  22. package/dist/data/engine.d.ts +1 -1
  23. package/dist/data/engine.js +586 -1
  24. package/dist/data/index.d.ts +1 -1
  25. package/dist/data/index.js +30 -1
  26. package/dist/data/prng.d.ts +1 -0
  27. package/dist/data/prng.js +73 -0
  28. package/dist/data/registry.d.ts +1 -0
  29. package/dist/data/registry.js +805 -0
  30. package/dist/data/schema-graph.d.ts +1 -0
  31. package/dist/data/schema-graph.js +210 -0
  32. package/dist/data/strategies.d.ts +1 -1
  33. package/dist/data/strategies.js +100 -1
  34. package/dist/data/templates.d.ts +1 -0
  35. package/dist/data/templates.js +134 -0
  36. package/dist/data/types.d.ts +1 -1
  37. package/dist/data/types.js +5 -1
  38. package/dist/data/validator.d.ts +1 -0
  39. package/dist/data/validator.js +160 -0
  40. package/dist/db/database.d.ts +1 -1
  41. package/dist/db/database.js +472 -1
  42. package/dist/db/export.d.ts +1 -1
  43. package/dist/db/export.js +67 -1
  44. package/dist/db/filters.d.ts +1 -1
  45. package/dist/db/filters.js +119 -1
  46. package/dist/db/index.js +24 -1
  47. package/dist/db/introspection.js +164 -1
  48. package/dist/db/manager.js +327 -1
  49. package/dist/db/migrations.js +100 -1
  50. package/dist/db/postgres.d.ts +1 -1
  51. package/dist/db/postgres.js +687 -1
  52. package/dist/db/types.d.ts +1 -1
  53. package/dist/db/types.js +6 -1
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.js +52 -1
  56. package/dist/public/css/app.css +1 -1
  57. package/dist/public/js/api.js +1 -1
  58. package/dist/public/js/browse.js +1 -1
  59. package/dist/public/js/common.js +1 -0
  60. package/dist/public/js/databases.js +1 -1
  61. package/dist/public/js/designer.js +1 -1
  62. package/dist/public/js/forms.js +1 -1
  63. package/dist/public/js/home.js +1 -0
  64. package/dist/public/js/inspector.js +1 -1
  65. package/dist/public/js/query.js +1 -1
  66. package/dist/public/js/schema.js +1 -1
  67. package/dist/public/js/seed.js +1 -1
  68. package/dist/routes/api/erd.d.ts +1 -0
  69. package/dist/routes/api/erd.js +45 -0
  70. package/dist/routes/api/helpers.d.ts +1 -1
  71. package/dist/routes/api/helpers.js +213 -1
  72. package/dist/routes/api/import-export.js +82 -1
  73. package/dist/routes/api/index.js +48 -1
  74. package/dist/routes/api/query.js +74 -1
  75. package/dist/routes/api/rows.js +358 -1
  76. package/dist/routes/api/seed.js +167 -1
  77. package/dist/routes/api/tables.js +216 -1
  78. package/dist/routes/databases.js +210 -1
  79. package/dist/routes/index.js +19 -1
  80. package/dist/routes/pages.js +446 -1
  81. package/dist/serverless.js +149 -1
  82. package/dist/sql/classifier.js +24 -1
  83. package/dist/sql/error-analyzer.d.ts +1 -0
  84. package/dist/sql/error-analyzer.js +550 -0
  85. package/dist/sql/generator.d.ts +1 -1
  86. package/dist/sql/generator.js +245 -1
  87. package/dist/sql/index.js +18 -1
  88. package/dist/types/api.d.ts +1 -1
  89. package/dist/types/api.js +2 -1
  90. package/dist/utils/colors.js +54 -1
  91. package/dist/utils/common.d.ts +1 -1
  92. package/dist/utils/common.js +185 -1
  93. package/dist/utils/csv.d.ts +1 -1
  94. package/dist/utils/csv.js +61 -1
  95. package/dist/utils/datatype.js +167 -1
  96. package/dist/utils/icons.js +81 -1
  97. package/dist/utils/index.js +20 -1
  98. package/dist/utils/logger.js +36 -1
  99. package/dist/views/layouts/main.hbs +1 -74
  100. package/dist/views/pages/databases.hbs +1 -233
  101. package/dist/views/pages/designer.hbs +1 -89
  102. package/dist/views/pages/erd.hbs +1 -0
  103. package/dist/views/pages/error.hbs +1 -10
  104. package/dist/views/pages/form.hbs +1 -59
  105. package/dist/views/pages/home.hbs +1 -124
  106. package/dist/views/pages/info.hbs +1 -0
  107. package/dist/views/pages/login.hbs +1 -98
  108. package/dist/views/pages/query.hbs +1 -87
  109. package/dist/views/pages/schema.hbs +1 -298
  110. package/dist/views/pages/seed-select.hbs +251 -0
  111. package/dist/views/pages/seed.hbs +273 -167
  112. package/dist/views/pages/table.hbs +1 -327
  113. package/dist/views/partials/navbar.hbs +1 -83
  114. package/dist/views/partials/sidebar.hbs +1 -117
  115. package/docs/API.md +149 -144
  116. package/docs/EXAMPLES.md +579 -576
  117. package/docs/SECURITY.md +265 -265
  118. package/package.json +79 -78
  119. package/dist/public/js/icons.js +0 -1
@@ -1 +1,245 @@
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.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
- 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);
@@ -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,};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>;
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
- 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 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;
@@ -1 +1,185 @@
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.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;
@@ -1 +1 @@
1
- export declare function csvEscape(value:unknown):string;export declare function toCsv(rows:Record<string,unknown>[],columns:string[]):string;export declare function toJson(rows:Record<string,unknown>[]):string;export declare function parseCsv(text:string):string[][];
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[][];