admindb 1.0.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.
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/app.d.ts +36 -0
- package/dist/app.js +186 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/csv.d.ts +15 -0
- package/dist/csv.js +80 -0
- package/dist/csv.js.map +1 -0
- package/dist/db/database.d.ts +225 -0
- package/dist/db/database.js +497 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/export.d.ts +12 -0
- package/dist/db/export.js +37 -0
- package/dist/db/export.js.map +1 -0
- package/dist/db/manager.d.ts +62 -0
- package/dist/db/manager.js +206 -0
- package/dist/db/manager.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.js +25 -0
- package/dist/logger.js.map +1 -0
- package/dist/public/css/app.css +1 -0
- package/dist/public/css/input.css +179 -0
- package/dist/public/js/api.js +47 -0
- package/dist/public/js/app.js +120 -0
- package/dist/public/js/browse.js +123 -0
- package/dist/public/js/databases.js +45 -0
- package/dist/public/js/designer.js +205 -0
- package/dist/public/js/forms.js +244 -0
- package/dist/public/js/query.js +232 -0
- package/dist/public/js/schema.js +314 -0
- package/dist/public/js/triggers.js +155 -0
- package/dist/public/js/views.js +176 -0
- package/dist/routes/api.d.ts +9 -0
- package/dist/routes/api.js +622 -0
- package/dist/routes/api.js.map +1 -0
- package/dist/routes/databases.d.ts +19 -0
- package/dist/routes/databases.js +99 -0
- package/dist/routes/databases.js.map +1 -0
- package/dist/routes/pages.d.ts +9 -0
- package/dist/routes/pages.js +253 -0
- package/dist/routes/pages.js.map +1 -0
- package/dist/sql/classifier.d.ts +19 -0
- package/dist/sql/classifier.js +37 -0
- package/dist/sql/classifier.js.map +1 -0
- package/dist/sql/generator.d.ts +99 -0
- package/dist/sql/generator.js +259 -0
- package/dist/sql/generator.js.map +1 -0
- package/dist/test/classifier.test.d.ts +1 -0
- package/dist/test/classifier.test.js +44 -0
- package/dist/test/classifier.test.js.map +1 -0
- package/dist/test/csv.test.d.ts +1 -0
- package/dist/test/csv.test.js +64 -0
- package/dist/test/csv.test.js.map +1 -0
- package/dist/test/database.test.d.ts +1 -0
- package/dist/test/database.test.js +224 -0
- package/dist/test/database.test.js.map +1 -0
- package/dist/test/generator.test.d.ts +1 -0
- package/dist/test/generator.test.js +164 -0
- package/dist/test/generator.test.js.map +1 -0
- package/dist/test/manager.test.d.ts +1 -0
- package/dist/test/manager.test.js +146 -0
- package/dist/test/manager.test.js.map +1 -0
- package/dist/util.d.ts +29 -0
- package/dist/util.js +127 -0
- package/dist/util.js.map +1 -0
- package/dist/views/layouts/main.hbs +49 -0
- package/dist/views/pages/databases.hbs +102 -0
- package/dist/views/pages/designer.hbs +81 -0
- package/dist/views/pages/error.hbs +12 -0
- package/dist/views/pages/form.hbs +62 -0
- package/dist/views/pages/home.hbs +123 -0
- package/dist/views/pages/query.hbs +94 -0
- package/dist/views/pages/schema.hbs +290 -0
- package/dist/views/pages/table.hbs +203 -0
- package/dist/views/pages/triggers.hbs +162 -0
- package/dist/views/pages/views.hbs +134 -0
- package/dist/views/partials/navbar.hbs +50 -0
- package/dist/views/partials/sidebar.hbs +128 -0
- package/package.json +62 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure SQL generators. Kept completely free of any I/O so they are easy to
|
|
3
|
+
* unit-test. Both the "run" and the "generate" (get-query) variants of every
|
|
4
|
+
* mutating operation share these functions.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DESIGNER_TYPES: readonly ["TEXT", "INTEGER", "REAL", "BLOB", "BOOLEAN", "DATE", "DATETIME"];
|
|
7
|
+
export type DesignerColumnType = (typeof DESIGNER_TYPES)[number];
|
|
8
|
+
export interface ColumnDef {
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
primaryKey?: boolean;
|
|
12
|
+
notNull?: boolean;
|
|
13
|
+
unique?: boolean;
|
|
14
|
+
/** Raw SQL expression used after DEFAULT (e.g. `0`, `'x'`, `CURRENT_TIMESTAMP`). */
|
|
15
|
+
defaultValue?: string | null;
|
|
16
|
+
foreignKey?: {
|
|
17
|
+
table: string;
|
|
18
|
+
column: string;
|
|
19
|
+
} | null;
|
|
20
|
+
}
|
|
21
|
+
export interface FieldValue {
|
|
22
|
+
column: string;
|
|
23
|
+
value: unknown;
|
|
24
|
+
}
|
|
25
|
+
/** Quote an SQL identifier (table/column name), escaping embedded double quotes. */
|
|
26
|
+
export declare function quoteIdentifier(identifier: string): string;
|
|
27
|
+
/** Escape a string for use inside a single-quoted SQL literal. */
|
|
28
|
+
export declare function escapeString(value: string): string;
|
|
29
|
+
/** Render a JS value as a safe SQL literal. */
|
|
30
|
+
export declare function sqlValue(value: unknown): string;
|
|
31
|
+
export interface MappedType {
|
|
32
|
+
sqlType: string;
|
|
33
|
+
/** Auto default applied when the user provides none (used for DATE). */
|
|
34
|
+
defaultAuto?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Map a designer-friendly type to a real SQLite column type.
|
|
38
|
+
* DATE-style types map to a datetime column with a current-timestamp default.
|
|
39
|
+
* Throws for unsupported types.
|
|
40
|
+
*/
|
|
41
|
+
export declare function mapColumnType(type: string): MappedType;
|
|
42
|
+
export interface RenderOptions {
|
|
43
|
+
/** Constrain DDL to what `ALTER TABLE ADD COLUMN` supports. */
|
|
44
|
+
forAddColumn?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Render a single column definition.
|
|
48
|
+
* When `forAddColumn` is set, enforces SQLite's ADD COLUMN restrictions
|
|
49
|
+
* (no PRIMARY KEY / UNIQUE, NOT NULL requires a default, FK requires NULL default).
|
|
50
|
+
*/
|
|
51
|
+
export declare function renderColumnDef(col: ColumnDef, opts?: RenderOptions): string;
|
|
52
|
+
/** Build a `CREATE TABLE` statement from structured column definitions. */
|
|
53
|
+
export declare function generateCreateTable(tableName: string, columns: ColumnDef[]): string;
|
|
54
|
+
/** Build an `ALTER TABLE … ADD COLUMN` statement. */
|
|
55
|
+
export declare function generateAddColumn(tableName: string, col: ColumnDef): string;
|
|
56
|
+
/** Build an `ALTER TABLE … RENAME TO …` statement. */
|
|
57
|
+
export declare function generateRenameTable(tableName: string, newName: string): string;
|
|
58
|
+
/** Build an `ALTER TABLE … RENAME COLUMN … TO …` statement. */
|
|
59
|
+
export declare function generateRenameColumn(tableName: string, oldName: string, newName: string): string;
|
|
60
|
+
/** Build an `ALTER TABLE … DROP COLUMN …` statement. */
|
|
61
|
+
export declare function generateDropColumn(tableName: string, column: string): string;
|
|
62
|
+
/** Build a `DROP TABLE …` statement. */
|
|
63
|
+
export declare function generateDropTable(tableName: string): string;
|
|
64
|
+
export interface IndexDef {
|
|
65
|
+
/** Optional explicit index name; a default `idx_<table>_<cols>` is generated when omitted. */
|
|
66
|
+
name?: string;
|
|
67
|
+
columns: string[];
|
|
68
|
+
unique?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** Build a `CREATE INDEX` (or `CREATE UNIQUE INDEX`) statement. */
|
|
71
|
+
export declare function generateCreateIndex(tableName: string, index: IndexDef): string;
|
|
72
|
+
/** Build a `DROP INDEX …` statement. */
|
|
73
|
+
export declare function generateDropIndex(indexName: string): string;
|
|
74
|
+
/** Build a `CREATE VIEW … AS <select>` statement. */
|
|
75
|
+
export declare function generateCreateView(viewName: string, selectSql: string): string;
|
|
76
|
+
/** Build a `DROP VIEW …` statement. */
|
|
77
|
+
export declare function generateDropView(viewName: string): string;
|
|
78
|
+
export type TriggerTiming = 'BEFORE' | 'AFTER' | 'INSTEAD OF';
|
|
79
|
+
export type TriggerEvent = 'INSERT' | 'UPDATE' | 'DELETE';
|
|
80
|
+
export interface TriggerDef {
|
|
81
|
+
name: string;
|
|
82
|
+
/** Table or view the trigger fires on. */
|
|
83
|
+
table: string;
|
|
84
|
+
timing: TriggerTiming;
|
|
85
|
+
/** The single event that fires the trigger (SQLite allows one per trigger). */
|
|
86
|
+
event: TriggerEvent;
|
|
87
|
+
/** Optional `WHEN` expression (without the `WHEN` keyword). */
|
|
88
|
+
when?: string;
|
|
89
|
+
/** Body statements (may contain multiple statements separated by `;`). */
|
|
90
|
+
body: string;
|
|
91
|
+
}
|
|
92
|
+
/** Build a `CREATE TRIGGER …` statement from structured parts. */
|
|
93
|
+
export declare function generateCreateTrigger(def: TriggerDef): string;
|
|
94
|
+
/** Build a `DROP TRIGGER …` statement. */
|
|
95
|
+
export declare function generateDropTrigger(triggerName: string): string;
|
|
96
|
+
/** Build an `INSERT` statement from column/value pairs. */
|
|
97
|
+
export declare function generateInsert(table: string, fields: FieldValue[]): string;
|
|
98
|
+
/** Build an `UPDATE` statement from SET fields and a WHERE clause. */
|
|
99
|
+
export declare function generateUpdate(table: string, fields: FieldValue[], where: FieldValue[]): string;
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure SQL generators. Kept completely free of any I/O so they are easy to
|
|
4
|
+
* unit-test. Both the "run" and the "generate" (get-query) variants of every
|
|
5
|
+
* mutating operation share these functions.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DESIGNER_TYPES = void 0;
|
|
9
|
+
exports.quoteIdentifier = quoteIdentifier;
|
|
10
|
+
exports.escapeString = escapeString;
|
|
11
|
+
exports.sqlValue = sqlValue;
|
|
12
|
+
exports.mapColumnType = mapColumnType;
|
|
13
|
+
exports.renderColumnDef = renderColumnDef;
|
|
14
|
+
exports.generateCreateTable = generateCreateTable;
|
|
15
|
+
exports.generateAddColumn = generateAddColumn;
|
|
16
|
+
exports.generateRenameTable = generateRenameTable;
|
|
17
|
+
exports.generateRenameColumn = generateRenameColumn;
|
|
18
|
+
exports.generateDropColumn = generateDropColumn;
|
|
19
|
+
exports.generateDropTable = generateDropTable;
|
|
20
|
+
exports.generateCreateIndex = generateCreateIndex;
|
|
21
|
+
exports.generateDropIndex = generateDropIndex;
|
|
22
|
+
exports.generateCreateView = generateCreateView;
|
|
23
|
+
exports.generateDropView = generateDropView;
|
|
24
|
+
exports.generateCreateTrigger = generateCreateTrigger;
|
|
25
|
+
exports.generateDropTrigger = generateDropTrigger;
|
|
26
|
+
exports.generateInsert = generateInsert;
|
|
27
|
+
exports.generateUpdate = generateUpdate;
|
|
28
|
+
exports.DESIGNER_TYPES = ['TEXT', 'INTEGER', 'REAL', 'BLOB', 'BOOLEAN', 'DATE', 'DATETIME'];
|
|
29
|
+
const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
30
|
+
/** Quote an SQL identifier (table/column name), escaping embedded double quotes. */
|
|
31
|
+
function quoteIdentifier(identifier) {
|
|
32
|
+
return `"${String(identifier).replace(/"/g, '""')}"`;
|
|
33
|
+
}
|
|
34
|
+
/** Escape a string for use inside a single-quoted SQL literal. */
|
|
35
|
+
function escapeString(value) {
|
|
36
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
37
|
+
}
|
|
38
|
+
/** Render a JS value as a safe SQL literal. */
|
|
39
|
+
function sqlValue(value) {
|
|
40
|
+
if (value === null || value === undefined)
|
|
41
|
+
return 'NULL';
|
|
42
|
+
if (typeof value === 'number')
|
|
43
|
+
return Number.isFinite(value) ? String(value) : 'NULL';
|
|
44
|
+
if (typeof value === 'bigint')
|
|
45
|
+
return String(value);
|
|
46
|
+
if (typeof value === 'boolean')
|
|
47
|
+
return value ? '1' : '0';
|
|
48
|
+
if (value instanceof Uint8Array)
|
|
49
|
+
return `X'${Buffer.from(value).toString('hex')}'`;
|
|
50
|
+
if (value instanceof Date)
|
|
51
|
+
return escapeString(value.toISOString());
|
|
52
|
+
return escapeString(String(value));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Map a designer-friendly type to a real SQLite column type.
|
|
56
|
+
* DATE-style types map to a datetime column with a current-timestamp default.
|
|
57
|
+
* Throws for unsupported types.
|
|
58
|
+
*/
|
|
59
|
+
function mapColumnType(type) {
|
|
60
|
+
const t = String(type).trim().toUpperCase();
|
|
61
|
+
switch (t) {
|
|
62
|
+
case 'INTEGER':
|
|
63
|
+
return { sqlType: 'INTEGER' };
|
|
64
|
+
case 'TEXT':
|
|
65
|
+
return { sqlType: 'TEXT' };
|
|
66
|
+
case 'REAL':
|
|
67
|
+
return { sqlType: 'REAL' };
|
|
68
|
+
case 'BLOB':
|
|
69
|
+
return { sqlType: 'BLOB' };
|
|
70
|
+
case 'BOOLEAN':
|
|
71
|
+
return { sqlType: 'INTEGER' };
|
|
72
|
+
case 'DATE':
|
|
73
|
+
return { sqlType: 'DATETIME', defaultAuto: 'CURRENT_TIMESTAMP' };
|
|
74
|
+
case 'DATETIME':
|
|
75
|
+
return { sqlType: 'DATETIME' };
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Unsupported column type: "${type}". Supported types: ${exports.DESIGNER_TYPES.join(', ')}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function validateIdentifier(kind, name) {
|
|
81
|
+
const label = kind.charAt(0).toUpperCase() + kind.slice(1);
|
|
82
|
+
const trimmed = String(name ?? '').trim();
|
|
83
|
+
if (!trimmed)
|
|
84
|
+
throw new Error(`${label} name is required.`);
|
|
85
|
+
if (!IDENTIFIER_RE.test(trimmed)) {
|
|
86
|
+
throw new Error(`Invalid ${label.toLowerCase()} name: "${trimmed}". Use letters, digits and underscores.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Render a single column definition.
|
|
91
|
+
* When `forAddColumn` is set, enforces SQLite's ADD COLUMN restrictions
|
|
92
|
+
* (no PRIMARY KEY / UNIQUE, NOT NULL requires a default, FK requires NULL default).
|
|
93
|
+
*/
|
|
94
|
+
function renderColumnDef(col, opts = {}) {
|
|
95
|
+
const colName = String(col?.name ?? '').trim();
|
|
96
|
+
validateIdentifier('column', colName);
|
|
97
|
+
const mapped = mapColumnType(col.type);
|
|
98
|
+
if (opts.forAddColumn) {
|
|
99
|
+
if (col.primaryKey) {
|
|
100
|
+
throw new Error(`Cannot add "${colName}" as PRIMARY KEY: ALTER TABLE ADD COLUMN does not support primary keys.`);
|
|
101
|
+
}
|
|
102
|
+
if (col.unique) {
|
|
103
|
+
throw new Error(`Cannot add "${colName}" with UNIQUE: ALTER TABLE ADD COLUMN does not support UNIQUE constraints.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
let def = `${quoteIdentifier(colName)} ${mapped.sqlType}`;
|
|
107
|
+
if (!opts.forAddColumn && col.primaryKey)
|
|
108
|
+
def += ' PRIMARY KEY';
|
|
109
|
+
if (col.notNull)
|
|
110
|
+
def += ' NOT NULL';
|
|
111
|
+
if (!opts.forAddColumn && col.unique)
|
|
112
|
+
def += ' UNIQUE';
|
|
113
|
+
const rawDefault = String(col.defaultValue ?? '').trim().replace(/;/g, '');
|
|
114
|
+
const dflt = rawDefault || mapped.defaultAuto || '';
|
|
115
|
+
if (dflt)
|
|
116
|
+
def += ` DEFAULT ${dflt}`;
|
|
117
|
+
else if (opts.forAddColumn && col.notNull) {
|
|
118
|
+
throw new Error(`Cannot add "${colName}" as NOT NULL without a default value.`);
|
|
119
|
+
}
|
|
120
|
+
if (col.foreignKey?.table && col.foreignKey.column) {
|
|
121
|
+
if (opts.forAddColumn && (col.notNull || dflt)) {
|
|
122
|
+
throw new Error(`Cannot add "${colName}" as a foreign key with NOT NULL or a non-NULL default.`);
|
|
123
|
+
}
|
|
124
|
+
def += ` REFERENCES ${quoteIdentifier(col.foreignKey.table)}(${quoteIdentifier(col.foreignKey.column)})`;
|
|
125
|
+
}
|
|
126
|
+
return def;
|
|
127
|
+
}
|
|
128
|
+
/** Build a `CREATE TABLE` statement from structured column definitions. */
|
|
129
|
+
function generateCreateTable(tableName, columns) {
|
|
130
|
+
const table = String(tableName ?? '').trim();
|
|
131
|
+
validateIdentifier('table', table);
|
|
132
|
+
if (!Array.isArray(columns) || columns.length === 0) {
|
|
133
|
+
throw new Error('At least one column is required.');
|
|
134
|
+
}
|
|
135
|
+
const seen = new Set();
|
|
136
|
+
let pkCount = 0;
|
|
137
|
+
const parts = [];
|
|
138
|
+
for (const col of columns) {
|
|
139
|
+
const colName = String(col?.name ?? '').trim();
|
|
140
|
+
validateIdentifier('column', colName);
|
|
141
|
+
if (seen.has(colName))
|
|
142
|
+
throw new Error(`Duplicate column name: "${colName}".`);
|
|
143
|
+
seen.add(colName);
|
|
144
|
+
if (col.primaryKey)
|
|
145
|
+
pkCount += 1;
|
|
146
|
+
parts.push(renderColumnDef(col));
|
|
147
|
+
}
|
|
148
|
+
if (pkCount > 1)
|
|
149
|
+
throw new Error('At most one primary key column is allowed.');
|
|
150
|
+
return `CREATE TABLE ${quoteIdentifier(table)} (\n ${parts.join(',\n ')}\n);`;
|
|
151
|
+
}
|
|
152
|
+
/** Build an `ALTER TABLE … ADD COLUMN` statement. */
|
|
153
|
+
function generateAddColumn(tableName, col) {
|
|
154
|
+
const table = String(tableName ?? '').trim();
|
|
155
|
+
validateIdentifier('table', table);
|
|
156
|
+
const def = renderColumnDef(col, { forAddColumn: true });
|
|
157
|
+
return `ALTER TABLE ${quoteIdentifier(table)} ADD COLUMN ${def};`;
|
|
158
|
+
}
|
|
159
|
+
/** Build an `ALTER TABLE … RENAME TO …` statement. */
|
|
160
|
+
function generateRenameTable(tableName, newName) {
|
|
161
|
+
validateIdentifier('table', tableName);
|
|
162
|
+
validateIdentifier('table', newName);
|
|
163
|
+
return `ALTER TABLE ${quoteIdentifier(tableName)} RENAME TO ${quoteIdentifier(newName)};`;
|
|
164
|
+
}
|
|
165
|
+
/** Build an `ALTER TABLE … RENAME COLUMN … TO …` statement. */
|
|
166
|
+
function generateRenameColumn(tableName, oldName, newName) {
|
|
167
|
+
validateIdentifier('table', tableName);
|
|
168
|
+
validateIdentifier('column', oldName);
|
|
169
|
+
validateIdentifier('column', newName);
|
|
170
|
+
return `ALTER TABLE ${quoteIdentifier(tableName)} RENAME COLUMN ${quoteIdentifier(oldName)} TO ${quoteIdentifier(newName)};`;
|
|
171
|
+
}
|
|
172
|
+
/** Build an `ALTER TABLE … DROP COLUMN …` statement. */
|
|
173
|
+
function generateDropColumn(tableName, column) {
|
|
174
|
+
validateIdentifier('table', tableName);
|
|
175
|
+
validateIdentifier('column', column);
|
|
176
|
+
return `ALTER TABLE ${quoteIdentifier(tableName)} DROP COLUMN ${quoteIdentifier(column)};`;
|
|
177
|
+
}
|
|
178
|
+
/** Build a `DROP TABLE …` statement. */
|
|
179
|
+
function generateDropTable(tableName) {
|
|
180
|
+
validateIdentifier('table', tableName);
|
|
181
|
+
return `DROP TABLE ${quoteIdentifier(tableName)};`;
|
|
182
|
+
}
|
|
183
|
+
/** Build a `CREATE INDEX` (or `CREATE UNIQUE INDEX`) statement. */
|
|
184
|
+
function generateCreateIndex(tableName, index) {
|
|
185
|
+
validateIdentifier('table', tableName);
|
|
186
|
+
const cols = Array.isArray(index?.columns) ? index.columns : [];
|
|
187
|
+
if (!cols.length)
|
|
188
|
+
throw new Error('At least one column is required for an index.');
|
|
189
|
+
for (const c of cols)
|
|
190
|
+
validateIdentifier('column', c);
|
|
191
|
+
const unique = index.unique ? 'UNIQUE ' : '';
|
|
192
|
+
let name = String(index?.name ?? '').trim();
|
|
193
|
+
if (!name)
|
|
194
|
+
name = `idx_${tableName}_${cols.join('_')}`;
|
|
195
|
+
validateIdentifier('index', name);
|
|
196
|
+
return `CREATE ${unique}INDEX ${quoteIdentifier(name)} ON ${quoteIdentifier(tableName)} (${cols.map(quoteIdentifier).join(', ')});`;
|
|
197
|
+
}
|
|
198
|
+
/** Build a `DROP INDEX …` statement. */
|
|
199
|
+
function generateDropIndex(indexName) {
|
|
200
|
+
validateIdentifier('index', indexName);
|
|
201
|
+
return `DROP INDEX ${quoteIdentifier(indexName)};`;
|
|
202
|
+
}
|
|
203
|
+
/** Build a `CREATE VIEW … AS <select>` statement. */
|
|
204
|
+
function generateCreateView(viewName, selectSql) {
|
|
205
|
+
validateIdentifier('view', viewName);
|
|
206
|
+
const select = String(selectSql ?? '').trim().replace(/;+\s*$/, '');
|
|
207
|
+
if (!select)
|
|
208
|
+
throw new Error('A SELECT statement is required to create a view.');
|
|
209
|
+
return `CREATE VIEW ${quoteIdentifier(viewName)} AS\n${select};`;
|
|
210
|
+
}
|
|
211
|
+
/** Build a `DROP VIEW …` statement. */
|
|
212
|
+
function generateDropView(viewName) {
|
|
213
|
+
validateIdentifier('view', viewName);
|
|
214
|
+
return `DROP VIEW ${quoteIdentifier(viewName)};`;
|
|
215
|
+
}
|
|
216
|
+
const TRIGGER_TIMINGS = ['BEFORE', 'AFTER', 'INSTEAD OF'];
|
|
217
|
+
const TRIGGER_EVENTS = ['INSERT', 'UPDATE', 'DELETE'];
|
|
218
|
+
/** Build a `CREATE TRIGGER …` statement from structured parts. */
|
|
219
|
+
function generateCreateTrigger(def) {
|
|
220
|
+
const name = String(def?.name ?? '').trim();
|
|
221
|
+
validateIdentifier('trigger', name);
|
|
222
|
+
const table = String(def?.table ?? '').trim();
|
|
223
|
+
validateIdentifier('table', table);
|
|
224
|
+
const timing = String(def?.timing ?? '').trim().toUpperCase();
|
|
225
|
+
if (!TRIGGER_TIMINGS.includes(timing)) {
|
|
226
|
+
throw new Error(`Invalid trigger timing: "${def?.timing}". Use ${TRIGGER_TIMINGS.join(', ')}.`);
|
|
227
|
+
}
|
|
228
|
+
const event = String(def?.event ?? '').trim().toUpperCase();
|
|
229
|
+
if (!TRIGGER_EVENTS.includes(event)) {
|
|
230
|
+
throw new Error(`Invalid trigger event: "${def?.event}". Use ${TRIGGER_EVENTS.join(', ')}.`);
|
|
231
|
+
}
|
|
232
|
+
const body = String(def?.body ?? '').trim().replace(/;+\s*$/, '');
|
|
233
|
+
if (!body)
|
|
234
|
+
throw new Error('Trigger body is required.');
|
|
235
|
+
const when = String(def?.when ?? '').trim();
|
|
236
|
+
let sql = `CREATE TRIGGER ${quoteIdentifier(name)} ${timing} ${event} ON ${quoteIdentifier(table)}`;
|
|
237
|
+
if (when)
|
|
238
|
+
sql += ` WHEN ${when}`;
|
|
239
|
+
sql += `\nBEGIN\n${body};\nEND;`;
|
|
240
|
+
return sql;
|
|
241
|
+
}
|
|
242
|
+
/** Build a `DROP TRIGGER …` statement. */
|
|
243
|
+
function generateDropTrigger(triggerName) {
|
|
244
|
+
validateIdentifier('trigger', triggerName);
|
|
245
|
+
return `DROP TRIGGER ${quoteIdentifier(triggerName)};`;
|
|
246
|
+
}
|
|
247
|
+
/** Build an `INSERT` statement from column/value pairs. */
|
|
248
|
+
function generateInsert(table, fields) {
|
|
249
|
+
const cols = fields.map((f) => quoteIdentifier(f.column));
|
|
250
|
+
const vals = fields.map((f) => sqlValue(f.value));
|
|
251
|
+
return `INSERT INTO ${quoteIdentifier(table)} (${cols.join(', ')}) VALUES (${vals.join(', ')});`;
|
|
252
|
+
}
|
|
253
|
+
/** Build an `UPDATE` statement from SET fields and a WHERE clause. */
|
|
254
|
+
function generateUpdate(table, fields, where) {
|
|
255
|
+
const sets = fields.map((f) => `${quoteIdentifier(f.column)} = ${sqlValue(f.value)}`);
|
|
256
|
+
const conds = where.map((w) => `${quoteIdentifier(w.column)} = ${sqlValue(w.value)}`);
|
|
257
|
+
return `UPDATE ${quoteIdentifier(table)} SET ${sets.join(', ')} WHERE ${conds.join(' AND ')};`;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/sql/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const classifier_1 = require("../sql/classifier");
|
|
9
|
+
(0, node_test_1.test)('classifies SELECT statements as select', () => {
|
|
10
|
+
strict_1.default.equal((0, classifier_1.classifySql)('SELECT * FROM users').kind, 'select');
|
|
11
|
+
strict_1.default.equal((0, classifier_1.classifySql)(' select id, name from users;').kind, 'select');
|
|
12
|
+
strict_1.default.equal((0, classifier_1.classifySql)('WITH c AS (SELECT 1) SELECT * FROM c').kind, 'select');
|
|
13
|
+
});
|
|
14
|
+
(0, node_test_1.test)('classifies pure count queries as count', () => {
|
|
15
|
+
strict_1.default.equal((0, classifier_1.classifySql)('SELECT count(*) FROM users').kind, 'count');
|
|
16
|
+
strict_1.default.equal((0, classifier_1.classifySql)('select COUNT(id) from orders').kind, 'count');
|
|
17
|
+
});
|
|
18
|
+
(0, node_test_1.test)('does not classify grouped or unioned selects as count', () => {
|
|
19
|
+
strict_1.default.equal((0, classifier_1.classifySql)('SELECT type, count(*) FROM items GROUP BY type').kind, 'select');
|
|
20
|
+
strict_1.default.equal((0, classifier_1.classifySql)('SELECT count(*) FROM a UNION SELECT count(*) FROM b').kind, 'select');
|
|
21
|
+
});
|
|
22
|
+
(0, node_test_1.test)('classifies write statements as write', () => {
|
|
23
|
+
const writes = [
|
|
24
|
+
'INSERT INTO t (a) VALUES (1)',
|
|
25
|
+
'UPDATE t SET a = 1',
|
|
26
|
+
'DELETE FROM t',
|
|
27
|
+
'CREATE TABLE t (a TEXT)',
|
|
28
|
+
'ALTER TABLE t ADD COLUMN b TEXT',
|
|
29
|
+
'DROP TABLE t',
|
|
30
|
+
'REPLACE INTO t (a) VALUES (1)',
|
|
31
|
+
];
|
|
32
|
+
for (const sql of writes) {
|
|
33
|
+
strict_1.default.equal((0, classifier_1.classifySql)(sql).kind, 'write', sql);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
(0, node_test_1.test)('classifies PRAGMA and EXPLAIN as read', () => {
|
|
37
|
+
strict_1.default.equal((0, classifier_1.classifySql)('PRAGMA table_info(users)').kind, 'read');
|
|
38
|
+
strict_1.default.equal((0, classifier_1.classifySql)('EXPLAIN QUERY PLAN SELECT * FROM t').kind, 'read');
|
|
39
|
+
});
|
|
40
|
+
(0, node_test_1.test)('ignores leading comments and whitespace', () => {
|
|
41
|
+
strict_1.default.equal((0, classifier_1.classifySql)('-- hello\nSELECT * FROM t').kind, 'select');
|
|
42
|
+
strict_1.default.equal((0, classifier_1.classifySql)('/* block */\n INSERT INTO t (a) VALUES (1)').kind, 'write');
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=classifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.test.js","sourceRoot":"","sources":["../../src/test/classifier.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAiC;AACjC,gEAAwC;AACxC,kDAAgD;AAEhD,IAAA,gBAAI,EAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChE,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,+BAA+B,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1E,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,sCAAsC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnF,CAAC,CAAC,CAAC;AAEH,IAAA,gBAAI,EAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,4BAA4B,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtE,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,8BAA8B,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC,CAAC,CAAC;AAEH,IAAA,gBAAI,EAAC,uDAAuD,EAAE,GAAG,EAAE;IACjE,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,gDAAgD,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3F,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,qDAAqD,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAClG,CAAC,CAAC,CAAC;AAEH,IAAA,gBAAI,EAAC,sCAAsC,EAAE,GAAG,EAAE;IAChD,MAAM,MAAM,GAAG;QACb,8BAA8B;QAC9B,oBAAoB;QACpB,eAAe;QACf,yBAAyB;QACzB,iCAAiC;QACjC,cAAc;QACd,+BAA+B;KAChC,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAA,gBAAI,EAAC,uCAAuC,EAAE,GAAG,EAAE;IACjD,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,0BAA0B,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnE,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,oCAAoC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/E,CAAC,CAAC,CAAC;AAEH,IAAA,gBAAI,EAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,2BAA2B,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtE,gBAAM,CAAC,KAAK,CAAC,IAAA,wBAAW,EAAC,4CAA4C,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACxF,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const csv_1 = require("../csv");
|
|
9
|
+
(0, node_test_1.test)('csvEscape quotes fields with commas, quotes or newlines', () => {
|
|
10
|
+
strict_1.default.equal((0, csv_1.csvEscape)('plain'), 'plain');
|
|
11
|
+
strict_1.default.equal((0, csv_1.csvEscape)('a,b'), '"a,b"');
|
|
12
|
+
strict_1.default.equal((0, csv_1.csvEscape)('say "hi"'), '"say ""hi"""');
|
|
13
|
+
strict_1.default.equal((0, csv_1.csvEscape)('line1\nline2'), '"line1\nline2"');
|
|
14
|
+
strict_1.default.equal((0, csv_1.csvEscape)(null), '');
|
|
15
|
+
strict_1.default.equal((0, csv_1.csvEscape)(0), '0');
|
|
16
|
+
strict_1.default.equal((0, csv_1.csvEscape)(false), 'false');
|
|
17
|
+
});
|
|
18
|
+
(0, node_test_1.test)('toCsv writes a header and quotes tricky cells', () => {
|
|
19
|
+
const csv = (0, csv_1.toCsv)([
|
|
20
|
+
{ id: 1, name: 'Ada', note: 'a, b "c"' },
|
|
21
|
+
{ id: 2, name: null, note: 'x' },
|
|
22
|
+
], ['id', 'name', 'note']);
|
|
23
|
+
strict_1.default.equal(csv, 'id,name,note\r\n1,Ada,"a, b ""c"""\r\n2,,x');
|
|
24
|
+
});
|
|
25
|
+
(0, node_test_1.test)('toJson pretty-prints an array of objects', () => {
|
|
26
|
+
const json = (0, csv_1.toJson)([{ a: 1, b: null }]);
|
|
27
|
+
strict_1.default.equal(json, '[\n {\n "a": 1,\n "b": null\n }\n]');
|
|
28
|
+
});
|
|
29
|
+
(0, node_test_1.test)('parseCsv handles quoted fields, embedded commas and newlines', () => {
|
|
30
|
+
const rows = (0, csv_1.parseCsv)('a,b,c\r\n1,"two, words","line1\nline2"\r\n');
|
|
31
|
+
strict_1.default.deepEqual(rows, [
|
|
32
|
+
['a', 'b', 'c'],
|
|
33
|
+
['1', 'two, words', 'line1\nline2'],
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
(0, node_test_1.test)('parseCsv handles escaped quotes and skips blank lines', () => {
|
|
37
|
+
const rows = (0, csv_1.parseCsv)('x,y\n"say ""hi""",2\n\n3,4\n');
|
|
38
|
+
strict_1.default.deepEqual(rows, [
|
|
39
|
+
['x', 'y'],
|
|
40
|
+
['say "hi"', '2'],
|
|
41
|
+
['3', '4'],
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
(0, node_test_1.test)('parseCsv handles a file without a trailing newline', () => {
|
|
45
|
+
const rows = (0, csv_1.parseCsv)('a,b\n1,2');
|
|
46
|
+
strict_1.default.deepEqual(rows, [
|
|
47
|
+
['a', 'b'],
|
|
48
|
+
['1', '2'],
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
(0, node_test_1.test)('toCsv → parseCsv round-trips typical data', () => {
|
|
52
|
+
const rows = [
|
|
53
|
+
{ name: 'O\'Reilly, John', age: 42, note: 'line1\nline2' },
|
|
54
|
+
{ name: 'x', age: null, note: 'plain' },
|
|
55
|
+
];
|
|
56
|
+
const columns = ['name', 'age', 'note'];
|
|
57
|
+
const parsed = (0, csv_1.parseCsv)((0, csv_1.toCsv)(rows, columns));
|
|
58
|
+
strict_1.default.deepEqual(parsed, [
|
|
59
|
+
['name', 'age', 'note'],
|
|
60
|
+
["O'Reilly, John", '42', 'line1\nline2'],
|
|
61
|
+
['x', '', 'plain'],
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=csv.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv.test.js","sourceRoot":"","sources":["../../src/test/csv.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|