mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-22 23:31:12 +02:00
feat: Integrate Electric SQL for real-time notifications and enhance PostgreSQL configuration
- Added Electric SQL service to docker-compose for real-time data synchronization. - Introduced PostgreSQL configuration for logical replication and performance tuning. - Created scripts for initializing Electric SQL user and electrifying tables. - Implemented notification model and service in the backend. - Developed ElectricProvider and useNotifications hook in the frontend for managing notifications. - Updated environment variables and package dependencies for Electric SQL integration.
This commit is contained in:
parent
383592ce63
commit
82c6dd0221
18 changed files with 1844 additions and 6 deletions
21
surfsense_web/lib/electric/auth.ts
Normal file
21
surfsense_web/lib/electric/auth.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Get auth token for Electric SQL
|
||||
* In production, this should get the token from your auth system
|
||||
*/
|
||||
|
||||
export async function getElectricAuthToken(): Promise<string> {
|
||||
// For insecure mode (development), return empty string
|
||||
if (process.env.NEXT_PUBLIC_ELECTRIC_AUTH_MODE === 'insecure') {
|
||||
return ''
|
||||
}
|
||||
|
||||
// In production, get token from your auth system
|
||||
// This should match your backend auth token
|
||||
if (typeof window !== 'undefined') {
|
||||
const token = localStorage.getItem('surfsense_bearer_token')
|
||||
return token || ''
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
86
surfsense_web/lib/electric/client.ts
Normal file
86
surfsense_web/lib/electric/client.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Electric SQL client setup
|
||||
* This initializes the Electric SQL client with local PGlite database (PostgreSQL in browser)
|
||||
*/
|
||||
|
||||
import { PGlite } from '@electric-sql/pglite'
|
||||
import { electrify } from 'electric-sql/pglite'
|
||||
import { getElectricAuthToken } from './auth'
|
||||
|
||||
// We'll generate the schema after running electric:generate
|
||||
// For now, we'll use a placeholder type
|
||||
type Electric = any
|
||||
type Schema = any
|
||||
|
||||
let electric: Electric | null = null
|
||||
let isInitializing = false
|
||||
let initPromise: Promise<Electric> | null = null
|
||||
|
||||
export async function initElectric(): Promise<Electric> {
|
||||
if (electric) {
|
||||
return electric
|
||||
}
|
||||
|
||||
if (isInitializing && initPromise) {
|
||||
return initPromise
|
||||
}
|
||||
|
||||
isInitializing = true
|
||||
initPromise = (async () => {
|
||||
try {
|
||||
const config = {
|
||||
auth: {
|
||||
token: await getElectricAuthToken(),
|
||||
},
|
||||
url: process.env.NEXT_PUBLIC_ELECTRIC_URL || 'http://localhost:5133',
|
||||
}
|
||||
|
||||
// Initialize PGlite database (PostgreSQL in browser)
|
||||
// Use idb:// prefix for IndexedDB storage in browser
|
||||
// relaxedDurability improves responsiveness by scheduling flush after query returns
|
||||
const conn = new PGlite('idb://surfsense.db', {
|
||||
relaxedDurability: true,
|
||||
})
|
||||
|
||||
// Import schema (will be generated by electric:generate)
|
||||
// For now, we'll use a dynamic import that will work after schema generation
|
||||
let schema: Schema
|
||||
try {
|
||||
const schemaModule = await import('./generated/schema')
|
||||
schema = schemaModule.schema
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Electric SQL schema not found. Run "pnpm electric:generate" to generate it.',
|
||||
error
|
||||
)
|
||||
// Return a mock electric client for now
|
||||
return null as any
|
||||
}
|
||||
|
||||
// Electrify the PGlite database connection
|
||||
electric = await electrify(conn, schema, config)
|
||||
|
||||
console.log('Electric SQL initialized successfully with PGlite')
|
||||
return electric
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize Electric SQL:', error)
|
||||
throw error
|
||||
} finally {
|
||||
isInitializing = false
|
||||
}
|
||||
})()
|
||||
|
||||
return initPromise
|
||||
}
|
||||
|
||||
export function getElectric(): Electric {
|
||||
if (!electric) {
|
||||
throw new Error('Electric not initialized. Call initElectric() first.')
|
||||
}
|
||||
return electric
|
||||
}
|
||||
|
||||
export function isElectricInitialized(): boolean {
|
||||
return electric !== null
|
||||
}
|
||||
|
||||
19
surfsense_web/lib/electric/config.ts
Normal file
19
surfsense_web/lib/electric/config.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Electric SQL configuration
|
||||
* This file will be used by @electric-sql/cli to generate the schema
|
||||
*/
|
||||
|
||||
export const electricConfig = {
|
||||
connection: {
|
||||
host: process.env.ELECTRIC_HOST || 'localhost',
|
||||
port: parseInt(process.env.ELECTRIC_PORT || '5133', 10),
|
||||
database: process.env.POSTGRES_DB || 'surfsense',
|
||||
user: process.env.ELECTRIC_USER || 'electric',
|
||||
password: process.env.ELECTRIC_PASSWORD || 'electric_password',
|
||||
},
|
||||
service: {
|
||||
host: process.env.ELECTRIC_HOST || 'localhost',
|
||||
port: parseInt(process.env.ELECTRIC_PORT || '5133', 10),
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue