fix: SQLite boolean binding, CSS brace, race condition, 0 npm vulns, code-splitting
This commit is contained in:
@@ -9,6 +9,7 @@ import { randomUUID } from 'crypto';
|
||||
import type {
|
||||
DatabaseInterface, DBProject, DBDrawing, DBLayer,
|
||||
DBElement, DBBlock, DBSetting, DBUser, DBSession,
|
||||
DBNotification, DBProjectShare,
|
||||
} from './DatabaseInterface.js';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@@ -146,7 +147,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const id = data.id ?? `layer-${Date.now()}`;
|
||||
this.db.prepare(
|
||||
'INSERT INTO layers (id, drawing_id, name, visible, locked, color, line_type, transparency, sort_order, parent_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.drawing_id!, data.name ?? 'Layer', data.visible ?? 1, data.locked ?? 0,
|
||||
).run(id, data.drawing_id!, data.name ?? 'Layer', data.visible !== undefined ? (data.visible ? 1 : 0) : 1, data.locked !== undefined ? (data.locked ? 1 : 0) : 0,
|
||||
data.color ?? '#ffffff', data.line_type ?? 'solid', data.transparency ?? 0,
|
||||
data.sort_order ?? 0, data.parent_id ?? null);
|
||||
return this.db.prepare('SELECT * FROM layers WHERE id = ?').get(id) as DBLayer;
|
||||
@@ -157,7 +158,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const vals: any[] = [];
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
if (['name','visible','locked','color','line_type','transparency','sort_order','parent_id'].includes(k)) {
|
||||
sets.push(`${k} = ?`); vals.push(v);
|
||||
sets.push(`${k} = ?`); vals.push(k === 'visible' || k === 'locked' ? (v ? 1 : 0) : v);
|
||||
}
|
||||
}
|
||||
if (sets.length > 0) {
|
||||
@@ -189,7 +190,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const vals: any[] = [];
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
if (['layer_id','type','x','y','width','height','properties_json'].includes(k)) {
|
||||
sets.push(`${k} = ?`); vals.push(v);
|
||||
sets.push(`${k} = ?`); vals.push(k === 'visible' || k === 'locked' ? (v ? 1 : 0) : v);
|
||||
}
|
||||
}
|
||||
if (sets.length > 0) {
|
||||
@@ -221,7 +222,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const vals: any[] = [];
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
if (['name','description','category','elements_json','thumbnail'].includes(k)) {
|
||||
sets.push(`${k} = ?`); vals.push(v);
|
||||
sets.push(`${k} = ?`); vals.push(k === 'visible' || k === 'locked' ? (v ? 1 : 0) : v);
|
||||
}
|
||||
}
|
||||
if (sets.length > 0) {
|
||||
@@ -265,4 +266,51 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
deleteExpiredSessions(): void {
|
||||
this.db.prepare('DELETE FROM sessions WHERE expires_at < ?').run(Date.now());
|
||||
}
|
||||
|
||||
// ─── Notifications ──────────────────────────────────
|
||||
listNotifications(userId: string): DBNotification[] {
|
||||
return this.db.prepare('SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC').all(userId) as DBNotification[];
|
||||
}
|
||||
|
||||
getNotification(id: string): DBNotification | null {
|
||||
return this.db.prepare('SELECT * FROM notifications WHERE id = ?').get(id) as DBNotification | null;
|
||||
}
|
||||
|
||||
createNotification(data: Partial<DBNotification>): DBNotification {
|
||||
const id = data.id ?? `notif-${Date.now()}`;
|
||||
this.db.prepare(
|
||||
'INSERT INTO notifications (id, user_id, type, title, message, read) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.user_id!, data.type ?? 'info', data.title!, data.message!, data.read ?? 0);
|
||||
return this.db.prepare('SELECT * FROM notifications WHERE id = ?').get(id) as DBNotification;
|
||||
}
|
||||
|
||||
markNotificationRead(id: string): boolean {
|
||||
return this.db.prepare('UPDATE notifications SET read = 1 WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
|
||||
deleteNotification(id: string): boolean {
|
||||
return this.db.prepare('DELETE FROM notifications WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
|
||||
// ─── Project Shares ─────────────────────────────────
|
||||
listProjectShares(projectId: string): DBProjectShare[] {
|
||||
return this.db.prepare('SELECT * FROM project_shares WHERE project_id = ? ORDER BY created_at DESC').all(projectId) as DBProjectShare[];
|
||||
}
|
||||
|
||||
getProjectShare(id: string): DBProjectShare | null {
|
||||
return this.db.prepare('SELECT * FROM project_shares WHERE id = ?').get(id) as DBProjectShare | null;
|
||||
}
|
||||
|
||||
createProjectShare(data: Partial<DBProjectShare>): DBProjectShare {
|
||||
const id = data.id ?? `share-${Date.now()}`;
|
||||
const shareToken = data.share_token ?? randomUUID();
|
||||
this.db.prepare(
|
||||
'INSERT INTO project_shares (id, project_id, shared_with_email, shared_by, permission, share_token) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.project_id!, data.shared_with_email!, data.shared_by!, data.permission ?? 'view', shareToken);
|
||||
return this.db.prepare('SELECT * FROM project_shares WHERE id = ?').get(id) as DBProjectShare;
|
||||
}
|
||||
|
||||
deleteProjectShare(id: string): boolean {
|
||||
return this.db.prepare('DELETE FROM project_shares WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user