feat: Add presence heartbeat for Matrix online status
- matrix-gateway: POST /internal/matrix/presence/online endpoint - usePresenceHeartbeat hook with activity tracking - Auto away after 5 min inactivity - Offline on page close/visibility change - Integrated in MatrixChatRoom component
This commit is contained in:
21
backend/infra/config/env.ts
Normal file
21
backend/infra/config/env.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Environment Configuration
|
||||
* Load and validate environment variables
|
||||
*/
|
||||
|
||||
export const config = {
|
||||
port: parseInt(process.env.PORT || '3000', 10),
|
||||
nodeEnv: process.env.NODE_ENV || 'development',
|
||||
apiBaseUrl: process.env.API_BASE_URL || 'http://localhost:3000',
|
||||
|
||||
// Database
|
||||
dbUrl: process.env.DATABASE_URL || 'postgresql://localhost:5432/microdao',
|
||||
|
||||
// Auth
|
||||
jwtSecret: process.env.JWT_SECRET || 'change-me-in-production',
|
||||
|
||||
// Wallet/Chain (future)
|
||||
chainRpcUrl: process.env.CHAIN_RPC_URL || '',
|
||||
};
|
||||
|
||||
|
||||
20
backend/infra/db/client.ts
Normal file
20
backend/infra/db/client.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Database Client
|
||||
* MVP: Placeholder for future DB connection
|
||||
* TODO: Replace with actual DB client (PostgreSQL, etc.)
|
||||
*/
|
||||
|
||||
// MVP: No-op
|
||||
export const dbClient = {
|
||||
connect: async () => {
|
||||
// TODO: Implement actual DB connection
|
||||
console.log('[DB] Connected (stub)');
|
||||
},
|
||||
|
||||
disconnect: async () => {
|
||||
// TODO: Implement actual DB disconnection
|
||||
console.log('[DB] Disconnected (stub)');
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
44
backend/infra/db/dao.repository.ts
Normal file
44
backend/infra/db/dao.repository.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* DAO Repository
|
||||
* Database access layer for DAO records
|
||||
* MVP: In-memory storage, replace with actual DB later
|
||||
*/
|
||||
|
||||
import type { DaoRecord } from '../../domain/dao/types';
|
||||
|
||||
// MVP: In-memory storage
|
||||
const daoStore: Map<string, DaoRecord> = new Map();
|
||||
|
||||
export const daoRepository = {
|
||||
async save(record: DaoRecord): Promise<void> {
|
||||
daoStore.set(record.daoId, record);
|
||||
},
|
||||
|
||||
async findById(daoId: string): Promise<DaoRecord | null> {
|
||||
return daoStore.get(daoId) || null;
|
||||
},
|
||||
|
||||
async findAll(filter?: { level?: string; type?: string }): Promise<DaoRecord[]> {
|
||||
const all = Array.from(daoStore.values());
|
||||
|
||||
if (!filter) {
|
||||
return all;
|
||||
}
|
||||
|
||||
return all.filter(dao => {
|
||||
if (filter.level && dao.level !== filter.level) {
|
||||
return false;
|
||||
}
|
||||
if (filter.type && dao.type !== filter.type) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
async delete(daoId: string): Promise<void> {
|
||||
daoStore.delete(daoId);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
27
backend/infra/logger/logger.ts
Normal file
27
backend/infra/logger/logger.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Logger
|
||||
* MVP: Simple console logger
|
||||
* Future: Replace with proper logging library (Winston, Pino, etc.)
|
||||
*/
|
||||
|
||||
type LogLevel = 'info' | 'warn' | 'error' | 'debug';
|
||||
|
||||
export const logger = {
|
||||
info: (message: string, ...args: unknown[]) => {
|
||||
console.log(`[INFO] ${message}`, ...args);
|
||||
},
|
||||
|
||||
warn: (message: string, ...args: unknown[]) => {
|
||||
console.warn(`[WARN] ${message}`, ...args);
|
||||
},
|
||||
|
||||
error: (message: string, ...args: unknown[]) => {
|
||||
console.error(`[ERROR] ${message}`, ...args);
|
||||
},
|
||||
|
||||
debug: (message: string, ...args: unknown[]) => {
|
||||
console.debug(`[DEBUG] ${message}`, ...args);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user