feat: Centralize configuration management for Nostr and API settings

- Introduce a new config module to manage Nostr relays, admin pubkeys, and API settings.
- Update components to utilize the centralized config instead of environment variables directly.
- Refactor relevant files to improve maintainability and reduce reliance on environment variables.
This commit is contained in:
padreug 2025-07-02 19:47:55 +02:00
parent 17a1504771
commit 0324cf8ec5
6 changed files with 83 additions and 13 deletions

View file

@ -8,8 +8,9 @@ import { Toaster } from 'vue-sonner'
import { useNostr } from '@/composables/useNostr' import { useNostr } from '@/composables/useNostr'
import { identity } from '@/composables/useIdentity' import { identity } from '@/composables/useIdentity'
import { toast } from 'vue-sonner' import { toast } from 'vue-sonner'
import { config } from '@/lib/config'
const relays = JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string) const relays = config.nostr.relays
const { isConnected, isConnecting, error, connect, disconnect } = useNostr({ relays }) const { isConnected, isConnecting, error, connect, disconnect } = useNostr({ relays })
const showPasswordDialog = ref(false) const showPasswordDialog = ref(false)

View file

@ -6,6 +6,7 @@ import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
import QRCode from 'qrcode' import QRCode from 'qrcode'
import { config } from '@/lib/config'
interface Props { interface Props {
event: { event: {
@ -49,14 +50,14 @@ async function handleSubmit() {
isLoading.value = true isLoading.value = true
error.value = '' error.value = ''
const apiUrl = `${import.meta.env.VITE_API_BASE_URL}/events/api/v1/tickets/${props.event.id}/${encodeURIComponent(name.value)}/${encodeURIComponent(email.value)}` const apiUrl = `${config.api.baseUrl}/events/api/v1/tickets/${props.event.id}/${encodeURIComponent(name.value)}/${encodeURIComponent(email.value)}`
console.log('Calling API:', apiUrl) console.log('Calling API:', apiUrl)
try { try {
const response = await fetch(apiUrl, { const response = await fetch(apiUrl, {
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
'X-API-KEY': import.meta.env.VITE_API_KEY 'X-API-KEY': config.api.key
} }
}) })

View file

@ -7,6 +7,7 @@ import { ScrollArea } from '@/components/ui/scroll-area'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { formatDistanceToNow } from 'date-fns' import { formatDistanceToNow } from 'date-fns'
import { Megaphone } from 'lucide-vue-next' import { Megaphone } from 'lucide-vue-next'
import { config, configUtils } from '@/lib/config'
const props = defineProps<{ const props = defineProps<{
relays?: string[] relays?: string[]
@ -17,14 +18,11 @@ const notes = ref<NostrNote[]>([])
const isLoading = ref(true) const isLoading = ref(true)
const error = ref<Error | null>(null) const error = ref<Error | null>(null)
const relayUrls = props.relays || JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string) const relayUrls = props.relays || config.nostr.relays
const { disconnect } = useNostr({ relays: relayUrls }) const { disconnect } = useNostr({ relays: relayUrls })
// Get admin/moderator pubkeys from environment // Get admin/moderator pubkeys from centralized config
// These should be hex pubkeys of trusted moderators/admins const adminPubkeys = config.nostr.adminPubkeys
const adminPubkeys = import.meta.env.VITE_ADMIN_PUBKEYS
? JSON.parse(import.meta.env.VITE_ADMIN_PUBKEYS as string)
: []
async function loadNotes() { async function loadNotes() {
try { try {

View file

@ -152,5 +152,5 @@ export function useSocial(relayUrls: string[]) {
} }
// Export singleton instance for global use // Export singleton instance for global use
const relayUrls = JSON.parse(import.meta.env.VITE_NOSTR_RELAYS as string) import { config } from '@/lib/config'
export const social = useSocial(relayUrls) export const social = useSocial(config.nostr.relays)

View file

@ -1,7 +1,8 @@
import type { Event, EventsApiError } from '../types/event' import type { Event, EventsApiError } from '../types/event'
import { config } from '@/lib/config'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://lnbits' const API_BASE_URL = config.api.baseUrl || 'http://lnbits'
const API_KEY = import.meta.env.VITE_API_KEY const API_KEY = config.api.key
export async function fetchEvents(allWallets = true): Promise<Event[]> { export async function fetchEvents(allWallets = true): Promise<Event[]> {
try { try {

69
src/lib/config/index.ts Normal file
View file

@ -0,0 +1,69 @@
// Centralized configuration management
// Handles all environment variables and app configuration
interface NostrConfig {
relays: string[]
adminPubkeys: string[]
}
interface ApiConfig {
baseUrl: string
key: string
}
interface AppConfig {
nostr: NostrConfig
api: ApiConfig
support: {
npub: string
}
}
// Parse JSON environment variables safely
function parseJsonEnv(envVar: string | undefined, fallback: any = []): any {
if (!envVar) return fallback
try {
return JSON.parse(envVar)
} catch (error) {
console.warn(`Failed to parse environment variable: ${envVar}`)
return fallback
}
}
// Create the configuration object
export const config: AppConfig = {
nostr: {
relays: parseJsonEnv(import.meta.env.VITE_NOSTR_RELAYS, []),
adminPubkeys: parseJsonEnv(import.meta.env.VITE_ADMIN_PUBKEYS, [])
},
api: {
baseUrl: import.meta.env.VITE_API_BASE_URL || '',
key: import.meta.env.VITE_API_KEY || ''
},
support: {
npub: import.meta.env.VITE_SUPPORT_NPUB || ''
}
} as const
// Utility functions for common config operations
export const configUtils = {
isAdminPubkey: (pubkey: string): boolean => {
return config.nostr.adminPubkeys.includes(pubkey)
},
hasNostrConfig: (): boolean => {
return config.nostr.relays.length > 0
},
hasApiConfig: (): boolean => {
return Boolean(config.api.baseUrl && config.api.key)
},
getDefaultRelays: (): string[] => {
return config.nostr.relays
}
}
// Export individual config sections for convenience
export const { nostr: nostrConfig, api: apiConfig } = config