mirror of
https://github.com/DocNR/POWR.git
synced 2025-04-23 01:01:27 +00:00
181 lines
4.8 KiB
TypeScript
181 lines
4.8 KiB
TypeScript
// lib/db/services/EventCache.ts
|
|
import { SQLiteDatabase } from 'expo-sqlite';
|
|
import { NostrEvent } from '@/types/nostr';
|
|
import { DbService } from '../db-service';
|
|
|
|
export class EventCache {
|
|
private db: DbService;
|
|
|
|
constructor(database: SQLiteDatabase) {
|
|
this.db = new DbService(database);
|
|
}
|
|
|
|
/**
|
|
* Store a Nostr event in the cache
|
|
*/
|
|
async setEvent(event: NostrEvent, skipExisting: boolean = false): Promise<void> {
|
|
if (!event.id) return;
|
|
|
|
try {
|
|
// Check if event already exists
|
|
if (skipExisting) {
|
|
const exists = await this.db.getFirstAsync<{ id: string }>(
|
|
'SELECT id FROM nostr_events WHERE id = ?',
|
|
[event.id]
|
|
);
|
|
|
|
if (exists) return;
|
|
}
|
|
|
|
// Store the event
|
|
await this.db.withTransactionAsync(async () => {
|
|
await this.db.runAsync(
|
|
`INSERT OR REPLACE INTO nostr_events
|
|
(id, pubkey, kind, created_at, content, sig, raw_event, received_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
event.id,
|
|
event.pubkey || '',
|
|
event.kind,
|
|
event.created_at,
|
|
event.content,
|
|
event.sig || '',
|
|
JSON.stringify(event),
|
|
Date.now()
|
|
]
|
|
);
|
|
|
|
// Store event tags
|
|
if (event.tags && event.tags.length > 0) {
|
|
// Delete existing tags first
|
|
await this.db.runAsync(
|
|
'DELETE FROM event_tags WHERE event_id = ?',
|
|
[event.id]
|
|
);
|
|
|
|
// Insert new tags
|
|
for (let i = 0; i < event.tags.length; i++) {
|
|
const tag = event.tags[i];
|
|
if (tag.length >= 2) {
|
|
await this.db.runAsync(
|
|
'INSERT INTO event_tags (event_id, name, value, index_num) VALUES (?, ?, ?, ?)',
|
|
[event.id, tag[0], tag[1], i]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Error caching event:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store a Nostr event in the cache without using a transaction
|
|
* This is used when the caller is already managing a transaction
|
|
*/
|
|
async setEventWithoutTransaction(event: NostrEvent, skipExisting: boolean = false): Promise<void> {
|
|
if (!event.id) return;
|
|
|
|
try {
|
|
// Check if event already exists
|
|
if (skipExisting) {
|
|
const exists = await this.db.getFirstAsync<{ id: string }>(
|
|
'SELECT id FROM nostr_events WHERE id = ?',
|
|
[event.id]
|
|
);
|
|
|
|
if (exists) return;
|
|
}
|
|
|
|
// Store the event without a transaction
|
|
await this.db.runAsync(
|
|
`INSERT OR REPLACE INTO nostr_events
|
|
(id, pubkey, kind, created_at, content, sig, raw_event, received_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
event.id,
|
|
event.pubkey || '',
|
|
event.kind,
|
|
event.created_at,
|
|
event.content,
|
|
event.sig || '',
|
|
JSON.stringify(event),
|
|
Date.now()
|
|
]
|
|
);
|
|
|
|
// Delete existing tags
|
|
await this.db.runAsync(
|
|
'DELETE FROM event_tags WHERE event_id = ?',
|
|
[event.id]
|
|
);
|
|
|
|
// Insert new tags
|
|
if (event.tags && event.tags.length > 0) {
|
|
for (let i = 0; i < event.tags.length; i++) {
|
|
const tag = event.tags[i];
|
|
if (tag.length >= 2) {
|
|
await this.db.runAsync(
|
|
'INSERT INTO event_tags (event_id, name, value, index_num) VALUES (?, ?, ?, ?)',
|
|
[event.id, tag[0], tag[1], i]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Error caching event without transaction:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get an event from the cache by ID
|
|
*/
|
|
async getEvent(id: string): Promise<NostrEvent | null> {
|
|
try {
|
|
const event = await this.db.getFirstAsync<{
|
|
id: string;
|
|
pubkey: string;
|
|
kind: number;
|
|
created_at: number;
|
|
content: string;
|
|
sig: string;
|
|
raw_event: string;
|
|
}>(
|
|
'SELECT * FROM nostr_events WHERE id = ?',
|
|
[id]
|
|
);
|
|
|
|
if (!event) return null;
|
|
|
|
// Get tags
|
|
const tags = await this.db.getAllAsync<{
|
|
name: string;
|
|
value: string;
|
|
index_num: number;
|
|
}>(
|
|
'SELECT name, value, index_num FROM event_tags WHERE event_id = ? ORDER BY index_num',
|
|
[id]
|
|
);
|
|
|
|
// Build the event object
|
|
const nostrEvent: NostrEvent = {
|
|
id: event.id,
|
|
pubkey: event.pubkey,
|
|
kind: event.kind,
|
|
created_at: event.created_at,
|
|
content: event.content,
|
|
sig: event.sig,
|
|
tags: tags.map(tag => [tag.name, tag.value])
|
|
};
|
|
|
|
return nostrEvent;
|
|
} catch (error) {
|
|
console.error('Error retrieving event:', error);
|
|
return null;
|
|
}
|
|
}
|
|
}
|