story-research-zapwall/lib/articleStorage.ts
Nicolas Cantu 3000872dbc refactoring
- **Motivations :** Assurer passage du lint strict et clarifier la logique paiements/publications.

- **Root causes :** Fonctions trop longues, promesses non gérées et typages WebLN/Nostr incomplets.

- **Correctifs :** Refactor PaymentModal (handlers void), extraction helpers articlePublisher, simplification polling sponsoring/zap, corrections curly et awaits.

- **Evolutions :** Nouveau module articlePublisherHelpers pour présentation/aiguillage contenu privé.

- **Page affectées :** components/PaymentModal.tsx, lib/articlePublisher.ts, lib/articlePublisherHelpers.ts, lib/paymentPolling.ts, lib/sponsoring.ts, lib/nostrZapVerification.ts et dépendances liées.
2025-12-22 17:56:00 +01:00

110 lines
2.7 KiB
TypeScript

import type { AlbyInvoice } from '@/types/alby'
import { storageService } from './storage/indexedDB'
interface StoredArticleData {
content: string
authorPubkey: string
articleId: string
invoice: {
invoice: string
paymentHash: string
amount: number
expiresAt: number
} | null
createdAt: number
}
// Default expiration: 30 days in milliseconds
const DEFAULT_EXPIRATION = 30 * 24 * 60 * 60 * 1000
/**
* Store private content temporarily until payment is confirmed
* Also stores the invoice if provided
* Uses IndexedDB exclusively
* Content expires after 30 days by default
*/
export async function storePrivateContent(
articleId: string,
content: string,
authorPubkey: string,
invoice?: AlbyInvoice
): Promise<void> {
try {
const key = `article_private_content_${articleId}`
const data: StoredArticleData = {
content,
authorPubkey,
articleId,
invoice: invoice
? {
invoice: invoice.invoice,
paymentHash: invoice.paymentHash,
amount: invoice.amount,
expiresAt: invoice.expiresAt,
}
: null,
createdAt: Date.now(),
}
// Store with expiration (30 days)
await storageService.set(key, data, DEFAULT_EXPIRATION)
} catch (error) {
console.error('Error storing private content:', error)
}
}
/**
* Get stored private content for an article
* Returns null if not found or expired
*/
export async function getStoredPrivateContent(articleId: string): Promise<{
content: string
authorPubkey: string
invoice?: AlbyInvoice
} | null> {
try {
const key = `article_private_content_${articleId}`
const data = await storageService.get<StoredArticleData>(key)
if (!data) {
return null
}
return {
content: data.content,
authorPubkey: data.authorPubkey,
invoice: data.invoice
? {
invoice: data.invoice.invoice,
paymentHash: data.invoice.paymentHash,
amount: data.invoice.amount,
expiresAt: data.invoice.expiresAt,
}
: undefined,
}
} catch (error) {
console.error('Error retrieving private content:', error)
return null
}
}
/**
* Get stored invoice for an article
*/
export async function getStoredInvoice(articleId: string): Promise<AlbyInvoice | null> {
const stored = await getStoredPrivateContent(articleId)
return stored?.invoice ?? null
}
/**
* Remove stored private content (after successful send or expiry)
*/
export async function removeStoredPrivateContent(articleId: string): Promise<void> {
try {
const key = `article_private_content_${articleId}`
await storageService.delete(key)
} catch (error) {
console.error('Error removing private content:', error)
}
}