refactor: migrate from node-sqlite3-wasm to better-sqlite3
Replace all db.run(sql, [params]) calls with db.prepare(sql).run(...params) across all source modules and test files. Also remove the node-sqlite3-wasm import from tests/db.test.ts and update the type annotation accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,10 +44,9 @@ router.get('/:id', (req: Request, res: Response): void => {
|
||||
}
|
||||
|
||||
// Update last_seen
|
||||
db.run(
|
||||
`UPDATE displays SET last_seen = datetime('now') WHERE id = ?`,
|
||||
[displayId]
|
||||
);
|
||||
db.prepare(
|
||||
`UPDATE displays SET last_seen = datetime('now') WHERE id = ?`
|
||||
).run(displayId);
|
||||
|
||||
const json = buildDisplayJson(displayId);
|
||||
if (!json) {
|
||||
|
||||
@@ -43,11 +43,10 @@ router.post('/', (req, res): void => {
|
||||
const { name, description, layout_id, api_token, refresh_sec } = req.body;
|
||||
if (!name) { res.status(400).json({ error: 'name is required' }); return; }
|
||||
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO displays (name, description, layout_id, api_token, refresh_sec)
|
||||
VALUES (?, ?, ?, ?, ?)`,
|
||||
[name, description ?? null, layout_id ?? null, api_token ?? null, refresh_sec ?? 300]
|
||||
);
|
||||
VALUES (?, ?, ?, ?, ?)`
|
||||
).run(name, description ?? null, layout_id ?? null, api_token ?? null, refresh_sec ?? 300);
|
||||
const id = result.lastInsertRowid as number;
|
||||
res.status(201).json(db.prepare('SELECT * FROM displays WHERE id = ?').get(id));
|
||||
} catch (err) {
|
||||
@@ -78,7 +77,7 @@ router.put('/:id', (req, res): void => {
|
||||
}
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE displays SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE displays SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
const display = db.prepare('SELECT * FROM displays WHERE id = ?').get(id);
|
||||
if (!display) { res.status(404).json({ error: 'Display not found' }); return; }
|
||||
res.json(display);
|
||||
@@ -91,7 +90,7 @@ router.put('/:id', (req, res): void => {
|
||||
router.delete('/:id', (req, res): void => {
|
||||
try {
|
||||
const db = getDb();
|
||||
const result = db.run('DELETE FROM displays WHERE id = ?', [parseInt(req.params.id)]);
|
||||
const result = db.prepare('DELETE FROM displays WHERE id = ?').run(parseInt(req.params.id));
|
||||
if ((result.changes as number) === 0) { res.status(404).json({ error: 'Display not found' }); return; }
|
||||
res.status(204).send();
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { Database } from 'node-sqlite3-wasm';
|
||||
import Database from 'better-sqlite3';
|
||||
import { migrate001 } from './migrations/001-initial';
|
||||
|
||||
let dbInstance: Database | null = null;
|
||||
let dbInstance: Database.Database | null = null;
|
||||
|
||||
export function initDb(path: string): Database {
|
||||
// node-sqlite3-wasm: pass undefined for in-memory DB
|
||||
const db = new Database(path === ':memory:' ? undefined : path);
|
||||
export function initDb(path: string): Database.Database {
|
||||
const db = new Database(path === ':memory:' ? ':memory:' : path);
|
||||
|
||||
// Enable WAL mode (file-based databases only, :memory: uses 'memory' mode)
|
||||
db.exec('PRAGMA journal_mode = WAL');
|
||||
// Enable foreign key constraints
|
||||
db.exec('PRAGMA foreign_keys = ON');
|
||||
db.pragma('journal_mode = WAL');
|
||||
db.pragma('foreign_keys = ON');
|
||||
|
||||
// Run migrations
|
||||
migrate001(db);
|
||||
@@ -19,7 +16,7 @@ export function initDb(path: string): Database {
|
||||
return db;
|
||||
}
|
||||
|
||||
export function getDb(): Database {
|
||||
export function getDb(): Database.Database {
|
||||
if (!dbInstance) {
|
||||
throw new Error('Database not initialized. Call initDb() first.');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Database } from 'node-sqlite3-wasm';
|
||||
import Database from 'better-sqlite3';
|
||||
|
||||
export function migrate001(db: Database): void {
|
||||
db.exec(`
|
||||
|
||||
@@ -19,10 +19,9 @@ async function main(): Promise<void> {
|
||||
|
||||
if (userCount.count === 0) {
|
||||
const hash = bcrypt.hashSync('admin', 10);
|
||||
db.run(
|
||||
`INSERT INTO users (username, password_hash) VALUES (?, ?)`,
|
||||
['admin', hash]
|
||||
);
|
||||
db.prepare(
|
||||
`INSERT INTO users (username, password_hash) VALUES (?, ?)`
|
||||
).run('admin', hash);
|
||||
console.log('Created default admin user (admin/admin)');
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,9 @@ export function updateDatapointValue(id: number, rawValue: string): Datapoint |
|
||||
|
||||
const transformed = applyTransform(rawValue, config);
|
||||
|
||||
db.run(
|
||||
`UPDATE datapoints SET value = ?, status = 'ok', updated_at = datetime('now') WHERE id = ?`,
|
||||
[transformed, id]
|
||||
);
|
||||
db.prepare(
|
||||
`UPDATE datapoints SET value = ?, status = 'ok', updated_at = datetime('now') WHERE id = ?`
|
||||
).run(transformed, id);
|
||||
|
||||
return db.prepare('SELECT * FROM datapoints WHERE id = ?').get(id) as Datapoint | undefined;
|
||||
}
|
||||
@@ -87,7 +86,7 @@ export function updateDatapoint(id: number, data: DatapointUpdate): Datapoint |
|
||||
if (fields.length === 0) return getDatapointById(id);
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE datapoints SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE datapoints SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return getDatapointById(id);
|
||||
}
|
||||
|
||||
@@ -97,11 +96,10 @@ export function createDatapointFromMqtt(
|
||||
topicPath: string
|
||||
): Datapoint {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO datapoints (name, label, source_type, source_id, topic_id, enabled)
|
||||
VALUES (?, ?, 'mqtt', ?, ?, 1)`,
|
||||
[topicPath, topicPath, brokerId, topicId]
|
||||
);
|
||||
VALUES (?, ?, 'mqtt', ?, ?, 1)`
|
||||
).run(topicPath, topicPath, brokerId, topicId);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM datapoints WHERE id = ?').get(id) as Datapoint;
|
||||
}
|
||||
@@ -112,11 +110,10 @@ export function createDatapointFromPg(
|
||||
queryName: string
|
||||
): Datapoint {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO datapoints (name, label, source_type, source_id, query_id, enabled)
|
||||
VALUES (?, ?, 'postgresql', ?, ?, 1)`,
|
||||
[queryName, queryName, sourceId, queryId]
|
||||
);
|
||||
VALUES (?, ?, 'postgresql', ?, ?, 1)`
|
||||
).run(queryName, queryName, sourceId, queryId);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM datapoints WHERE id = ?').get(id) as Datapoint;
|
||||
}
|
||||
|
||||
@@ -92,17 +92,16 @@ export function getLayoutById(id: number): LayoutWithElements | undefined {
|
||||
|
||||
export function createLayout(data: CreateLayoutData): Layout {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO layouts (name, type, width, height, grid_cols, grid_rows)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
data.name,
|
||||
data.type ?? 'free',
|
||||
data.width ?? 800,
|
||||
data.height ?? 480,
|
||||
data.grid_cols ?? null,
|
||||
data.grid_rows ?? null,
|
||||
]
|
||||
VALUES (?, ?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
data.name,
|
||||
data.type ?? 'free',
|
||||
data.width ?? 800,
|
||||
data.height ?? 480,
|
||||
data.grid_cols ?? null,
|
||||
data.grid_rows ?? null,
|
||||
);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM layouts WHERE id = ?').get(id) as Layout;
|
||||
@@ -125,41 +124,40 @@ export function updateLayout(id: number, data: UpdateLayoutData): Layout | undef
|
||||
}
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE layouts SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE layouts SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return db.prepare('SELECT * FROM layouts WHERE id = ?').get(id) as Layout | undefined;
|
||||
}
|
||||
|
||||
export function deleteLayout(id: number): boolean {
|
||||
const db = getDb();
|
||||
const result = db.run('DELETE FROM layouts WHERE id = ?', [id]);
|
||||
const result = db.prepare('DELETE FROM layouts WHERE id = ?').run(id);
|
||||
return (result.changes as number) > 0;
|
||||
}
|
||||
|
||||
export function addElement(layoutId: number, data: CreateElementData): LayoutElement {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO layout_elements
|
||||
(layout_id, datapoint_id, type, x, y, width, height, font_size, font_weight,
|
||||
text_align, icon, style, static_text, grid_col, grid_row, sort_order)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
layoutId,
|
||||
data.datapoint_id ?? null,
|
||||
data.type,
|
||||
data.x ?? 0,
|
||||
data.y ?? 0,
|
||||
data.width ?? null,
|
||||
data.height ?? null,
|
||||
data.font_size ?? 24,
|
||||
data.font_weight ?? 'normal',
|
||||
data.text_align ?? 'left',
|
||||
data.icon ?? null,
|
||||
data.style ?? 'plain',
|
||||
data.static_text ?? null,
|
||||
data.grid_col ?? null,
|
||||
data.grid_row ?? null,
|
||||
data.sort_order ?? 0,
|
||||
]
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
layoutId,
|
||||
data.datapoint_id ?? null,
|
||||
data.type,
|
||||
data.x ?? 0,
|
||||
data.y ?? 0,
|
||||
data.width ?? null,
|
||||
data.height ?? null,
|
||||
data.font_size ?? 24,
|
||||
data.font_weight ?? 'normal',
|
||||
data.text_align ?? 'left',
|
||||
data.icon ?? null,
|
||||
data.style ?? 'plain',
|
||||
data.static_text ?? null,
|
||||
data.grid_col ?? null,
|
||||
data.grid_row ?? null,
|
||||
data.sort_order ?? 0,
|
||||
);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM layout_elements WHERE id = ?').get(id) as LayoutElement;
|
||||
@@ -200,12 +198,12 @@ export function updateElement(id: number, data: UpdateElementData): LayoutElemen
|
||||
}
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE layout_elements SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE layout_elements SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return db.prepare('SELECT * FROM layout_elements WHERE id = ?').get(id) as LayoutElement | undefined;
|
||||
}
|
||||
|
||||
export function deleteElement(id: number): boolean {
|
||||
const db = getDb();
|
||||
const result = db.run('DELETE FROM layout_elements WHERE id = ?', [id]);
|
||||
const result = db.prepare('DELETE FROM layout_elements WHERE id = ?').run(id);
|
||||
return (result.changes as number) > 0;
|
||||
}
|
||||
|
||||
@@ -55,18 +55,17 @@ export function getBrokerById(id: number): MqttBroker | undefined {
|
||||
|
||||
export function createBroker(data: CreateBrokerData): MqttBroker {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO mqtt_brokers (name, host, port, username, password, use_tls, enabled)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
data.name,
|
||||
data.host,
|
||||
data.port ?? 1883,
|
||||
data.username ?? null,
|
||||
data.password ?? null,
|
||||
data.use_tls ?? 0,
|
||||
data.enabled ?? 1,
|
||||
]
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
data.name,
|
||||
data.host,
|
||||
data.port ?? 1883,
|
||||
data.username ?? null,
|
||||
data.password ?? null,
|
||||
data.use_tls ?? 0,
|
||||
data.enabled ?? 1,
|
||||
);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM mqtt_brokers WHERE id = ?').get(id) as MqttBroker;
|
||||
@@ -89,14 +88,14 @@ export function updateBroker(id: number, data: UpdateBrokerData): MqttBroker | u
|
||||
|
||||
fields.push("updated_at = datetime('now')");
|
||||
values.push(id);
|
||||
db.run(`UPDATE mqtt_brokers SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE mqtt_brokers SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return getBrokerById(id);
|
||||
}
|
||||
|
||||
export function deleteBroker(id: number): boolean {
|
||||
const db = getDb();
|
||||
disconnectBroker(id);
|
||||
const result = db.run('DELETE FROM mqtt_brokers WHERE id = ?', [id]);
|
||||
const result = db.prepare('DELETE FROM mqtt_brokers WHERE id = ?').run(id);
|
||||
return (result.changes as number) > 0;
|
||||
}
|
||||
|
||||
@@ -107,10 +106,9 @@ function buildConnectUrl(broker: MqttBroker): string {
|
||||
|
||||
function setStatus(id: number, status: string): void {
|
||||
const db = getDb();
|
||||
db.run(
|
||||
`UPDATE mqtt_brokers SET status = ?, updated_at = datetime('now') WHERE id = ?`,
|
||||
[status, id]
|
||||
);
|
||||
db.prepare(
|
||||
`UPDATE mqtt_brokers SET status = ?, updated_at = datetime('now') WHERE id = ?`
|
||||
).run(status, id);
|
||||
}
|
||||
|
||||
export function connectBroker(id: number): Promise<mqtt.MqttClient> {
|
||||
@@ -172,7 +170,7 @@ export function connectBroker(id: number): Promise<mqtt.MqttClient> {
|
||||
.get(id, t) as MqttTopic | undefined;
|
||||
if (!topicRecord) continue;
|
||||
|
||||
db.run('UPDATE mqtt_topics SET last_payload = ? WHERE id = ?', [p, topicRecord.id]);
|
||||
db.prepare('UPDATE mqtt_topics SET last_payload = ? WHERE id = ?').run(p, topicRecord.id);
|
||||
|
||||
const extracted = extractValue(p, topicRecord.json_path);
|
||||
if (extracted === null) continue;
|
||||
|
||||
@@ -40,7 +40,7 @@ export function updateTopic(id: number, data: UpdateTopicData): MqttTopic | unde
|
||||
}
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE mqtt_topics SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE mqtt_topics SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return db.prepare('SELECT * FROM mqtt_topics WHERE id = ?').get(id) as MqttTopic | undefined;
|
||||
}
|
||||
|
||||
@@ -51,11 +51,10 @@ function ensureTopicExists(brokerId: number, topic: string): void {
|
||||
.get(brokerId, topic);
|
||||
|
||||
if (!existing) {
|
||||
db.run(
|
||||
db.prepare(
|
||||
`INSERT INTO mqtt_topics (broker_id, topic, selected, ignored)
|
||||
VALUES (?, ?, 0, 0)`,
|
||||
[brokerId, topic]
|
||||
);
|
||||
VALUES (?, ?, 0, 0)`
|
||||
).run(brokerId, topic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,10 +104,9 @@ export function startDiscovery(brokerId: number, prefix?: string): Promise<MqttT
|
||||
discoveredTopics.add(t);
|
||||
ensureTopicExists(brokerId, t);
|
||||
}
|
||||
db.run(
|
||||
'UPDATE mqtt_topics SET last_payload = ? WHERE broker_id = ? AND topic = ?',
|
||||
[p, brokerId, t]
|
||||
);
|
||||
db.prepare(
|
||||
'UPDATE mqtt_topics SET last_payload = ? WHERE broker_id = ? AND topic = ?'
|
||||
).run(p, brokerId, t);
|
||||
}
|
||||
payloadCache.clear();
|
||||
};
|
||||
@@ -179,11 +177,10 @@ export function addManualTopic(brokerId: number, topic: string): MqttTopic {
|
||||
|
||||
if (existing) return existing;
|
||||
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO mqtt_topics (broker_id, topic, selected, ignored)
|
||||
VALUES (?, ?, 0, 0)`,
|
||||
[brokerId, topic]
|
||||
);
|
||||
VALUES (?, ?, 0, 0)`
|
||||
).run(brokerId, topic);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM mqtt_topics WHERE id = ?').get(id) as MqttTopic;
|
||||
}
|
||||
|
||||
@@ -39,16 +39,15 @@ export function getQueryById(id: number): PgQuery | undefined {
|
||||
|
||||
export function createQuery(data: CreateQueryData): PgQuery {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO pg_queries (source_id, name, query, interval_sec, result_column)
|
||||
VALUES (?, ?, ?, ?, ?)`,
|
||||
[
|
||||
data.source_id,
|
||||
data.name,
|
||||
data.query,
|
||||
data.interval_sec ?? 60,
|
||||
data.result_column,
|
||||
]
|
||||
VALUES (?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
data.source_id,
|
||||
data.name,
|
||||
data.query,
|
||||
data.interval_sec ?? 60,
|
||||
data.result_column,
|
||||
);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM pg_queries WHERE id = ?').get(id) as PgQuery;
|
||||
@@ -67,14 +66,14 @@ export function updateQuery(id: number, data: UpdateQueryData): PgQuery | undefi
|
||||
if (fields.length === 0) return getQueryById(id);
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE pg_queries SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE pg_queries SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return getQueryById(id);
|
||||
}
|
||||
|
||||
export function deleteQuery(id: number): boolean {
|
||||
const db = getDb();
|
||||
stopQueryTimer(id);
|
||||
const result = db.run('DELETE FROM pg_queries WHERE id = ?', [id]);
|
||||
const result = db.prepare('DELETE FROM pg_queries WHERE id = ?').run(id);
|
||||
return (result.changes as number) > 0;
|
||||
}
|
||||
|
||||
@@ -99,10 +98,9 @@ async function executeQuery(queryId: number): Promise<void> {
|
||||
const valueStr = String(rawValue);
|
||||
|
||||
const db = getDb();
|
||||
db.run(
|
||||
`UPDATE pg_queries SET last_result = ?, last_run_at = datetime('now') WHERE id = ?`,
|
||||
[valueStr, queryId]
|
||||
);
|
||||
db.prepare(
|
||||
`UPDATE pg_queries SET last_result = ?, last_run_at = datetime('now') WHERE id = ?`
|
||||
).run(valueStr, queryId);
|
||||
|
||||
const dp = getDatapointByQueryId(queryId);
|
||||
if (dp) {
|
||||
|
||||
@@ -42,19 +42,18 @@ export function getSourceById(id: number): PgSource | undefined {
|
||||
|
||||
export function createSource(data: CreateSourceData): PgSource {
|
||||
const db = getDb();
|
||||
const result = db.run(
|
||||
const result = db.prepare(
|
||||
`INSERT INTO pg_sources (name, host, port, database_name, username, password, use_tls, enabled)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
data.name,
|
||||
data.host,
|
||||
data.port ?? 5432,
|
||||
data.database_name,
|
||||
data.username,
|
||||
data.password,
|
||||
data.use_tls ?? 0,
|
||||
data.enabled ?? 1,
|
||||
]
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
data.name,
|
||||
data.host,
|
||||
data.port ?? 5432,
|
||||
data.database_name,
|
||||
data.username,
|
||||
data.password,
|
||||
data.use_tls ?? 0,
|
||||
data.enabled ?? 1,
|
||||
);
|
||||
const id = result.lastInsertRowid as number;
|
||||
return db.prepare('SELECT * FROM pg_sources WHERE id = ?').get(id) as PgSource;
|
||||
@@ -77,20 +76,20 @@ export function updateSource(id: number, data: UpdateSourceData): PgSource | und
|
||||
if (fields.length === 0) return getSourceById(id);
|
||||
|
||||
values.push(id);
|
||||
db.run(`UPDATE pg_sources SET ${fields.join(', ')} WHERE id = ?`, values);
|
||||
db.prepare(`UPDATE pg_sources SET ${fields.join(', ')} WHERE id = ?`).run(...values);
|
||||
return getSourceById(id);
|
||||
}
|
||||
|
||||
export function deleteSource(id: number): boolean {
|
||||
const db = getDb();
|
||||
disconnectSource(id);
|
||||
const result = db.run('DELETE FROM pg_sources WHERE id = ?', [id]);
|
||||
const result = db.prepare('DELETE FROM pg_sources WHERE id = ?').run(id);
|
||||
return (result.changes as number) > 0;
|
||||
}
|
||||
|
||||
function setStatus(id: number, status: string): void {
|
||||
const db = getDb();
|
||||
db.run('UPDATE pg_sources SET status = ? WHERE id = ?', [status, id]);
|
||||
db.prepare('UPDATE pg_sources SET status = ? WHERE id = ?').run(status, id);
|
||||
}
|
||||
|
||||
export async function connectSource(id: number): Promise<Pool> {
|
||||
|
||||
Reference in New Issue
Block a user