network/src/orbit/orbitDBService.ts
2025-04-01 10:44:20 +03:00

121 lines
3.1 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import { createOrbitDB, IPFSAccessController } from '@orbitdb/core';
import { registerFeed } from '@orbitdb/feed-db';
import { config } from '../config';
import { createServiceLogger } from '../utils/logger';
import { getHelia } from '../ipfs/ipfsService';
const logger = createServiceLogger('ORBITDB');
let orbitdb: any;
// Create a node-specific directory based on fingerprint to avoid lock conflicts
export const getOrbitDBDir = (): string => {
const baseDir = config.orbitdb.directory;
const fingerprint = config.env.fingerprint;
return `${baseDir}-${fingerprint}`;
};
const ORBITDB_DIR = getOrbitDBDir();
export const getDBAddress = (name: string): string | null => {
const addressFile = path.join(ORBITDB_DIR, `${name}.address`);
if (fs.existsSync(addressFile)) {
return fs.readFileSync(addressFile, 'utf-8').trim();
}
return null;
};
export const saveDBAddress = (name: string, address: string) => {
const addressFile = path.join(ORBITDB_DIR, `${name}.address`);
fs.writeFileSync(addressFile, address);
};
export const init = async () => {
try {
// Create directory if it doesn't exist
if (!fs.existsSync(ORBITDB_DIR)) {
fs.mkdirSync(ORBITDB_DIR, { recursive: true });
logger.info(`Created OrbitDB directory: ${ORBITDB_DIR}`);
}
registerFeed();
const ipfs = getHelia();
if (!ipfs) {
throw new Error('IPFS instance is not initialized.');
}
logger.info(`Initializing OrbitDB with directory: ${ORBITDB_DIR}`);
orbitdb = await createOrbitDB({
ipfs,
directory: ORBITDB_DIR,
});
logger.info('OrbitDB initialized successfully.');
return orbitdb;
} catch (e) {
logger.error('Failed to initialize OrbitDB:', e);
throw e;
}
};
export const openDB = async (name: string, type: string) => {
if (!orbitdb) {
throw new Error('OrbitDB not initialized. Call init() first.');
}
const existingAddress = getDBAddress(name);
let db;
try {
const dbOptions = {
type,
overwrite: false,
AccessController: IPFSAccessController({ write: ['*'], storage: getHelia() }),
};
if (existingAddress) {
logger.info(`Loading existing database with address: ${existingAddress}`);
db = await orbitdb.open(existingAddress, dbOptions);
} else {
logger.info(`Creating new database: ${name}`);
db = await orbitdb.open(name, dbOptions);
saveDBAddress(name, db.address.toString());
}
// Log the access controller type to verify
logger.info('Access Controller Type:', db.access.type);
return db;
} catch (error) {
logger.error(`Error opening database '${name}':`, error);
throw error;
}
};
export const getOrbitDB = () => {
return orbitdb;
};
export const db = async (dbName: string, type: string) => {
try {
if (!orbitdb) {
throw new Error('OrbitDB not initialized. Call init() first.');
}
return await openDB(dbName, type);
} catch (error: any) {
logger.error(`Error accessing database '${dbName}':`, error);
throw new Error(`Database error: ${error.message}`);
}
};
export default {
init,
openDB,
getOrbitDB,
db,
};