diff --git a/src/lib/services/logger.ts b/src/lib/services/logger.ts index 1b14781..a1da830 100644 --- a/src/lib/services/logger.ts +++ b/src/lib/services/logger.ts @@ -4,21 +4,23 @@ * Browser-safe: falls back to console in browser environments */ -function createConsoleLogger() { +import type { Logger } from '../types/logger.js'; + +function createConsoleLogger(): Logger { return { - info: (...args: any[]) => console.log('[INFO]', ...args), - error: (...args: any[]) => console.error('[ERROR]', ...args), - warn: (...args: any[]) => console.warn('[WARN]', ...args), - debug: (...args: any[]) => console.debug('[DEBUG]', ...args), - trace: (...args: any[]) => console.trace('[TRACE]', ...args), - fatal: (...args: any[]) => console.error('[FATAL]', ...args) + info: (...args: unknown[]) => console.log('[INFO]', ...args), + error: (...args: unknown[]) => console.error('[ERROR]', ...args), + warn: (...args: unknown[]) => console.warn('[WARN]', ...args), + debug: (...args: unknown[]) => console.debug('[DEBUG]', ...args), + trace: (...args: unknown[]) => console.trace('[TRACE]', ...args), + fatal: (...args: unknown[]) => console.error('[FATAL]', ...args) }; } // Check if we're in a Node.js environment const isNode = typeof process !== 'undefined' && process.versions?.node; -let logger: any; +let logger: Logger; if (isNode) { // Server-side: use pino diff --git a/src/lib/services/nostr/nip19-utils.ts b/src/lib/services/nostr/nip19-utils.ts index ce78ed9..eadf046 100644 --- a/src/lib/services/nostr/nip19-utils.ts +++ b/src/lib/services/nostr/nip19-utils.ts @@ -3,6 +3,7 @@ */ import { nip19 } from 'nostr-tools'; +import type { DecodedNevent, DecodedNaddr, DecodedNote } from '../../types/nip19.js'; export interface DecodedEvent { type: 'nevent' | 'naddr' | 'note'; @@ -27,7 +28,7 @@ export function decodeNostrAddress(input: string): DecodedEvent | null { const decoded = nip19.decode(trimmed); if (decoded.type === 'nevent') { - const data = decoded.data as { id: string; pubkey?: string; relays?: string[] }; + const data = decoded.data as DecodedNevent['data']; return { type: 'nevent', id: data.id, @@ -35,7 +36,7 @@ export function decodeNostrAddress(input: string): DecodedEvent | null { relays: data.relays }; } else if (decoded.type === 'naddr') { - const data = decoded.data as { pubkey: string; kind: number; identifier: string; relays?: string[] }; + const data = decoded.data as DecodedNaddr['data']; return { type: 'naddr', pubkey: data.pubkey, @@ -44,9 +45,10 @@ export function decodeNostrAddress(input: string): DecodedEvent | null { relays: data.relays }; } else if (decoded.type === 'note') { + const data = decoded.data as DecodedNote['data']; return { type: 'note', - id: decoded.data as string + id: data }; } } catch (e) { diff --git a/src/lib/types/highlight-js.d.ts b/src/lib/types/highlight-js.d.ts new file mode 100644 index 0000000..eecbe00 --- /dev/null +++ b/src/lib/types/highlight-js.d.ts @@ -0,0 +1,39 @@ +/** + * Type definitions for highlight.js + * These are minimal types for the parts we use + */ + +declare module 'highlight.js' { + export interface HighlightResult { + value: string; + language?: string; + relevance?: number; + } + + export interface HighlightOptions { + language?: string; + ignoreIllegals?: boolean; + } + + export interface AutoHighlightResult extends HighlightResult { + secondBest?: HighlightResult; + } + + export interface Language { + name?: string; + aliases?: string[]; + keywords?: Record; + contains?: any[]; + } + + export interface HLJSApi { + highlight(code: string, options: HighlightOptions): HighlightResult; + highlightAuto(code: string, options?: { languageSubset?: string[] }): AutoHighlightResult; + getLanguage(name: string): Language | undefined; + registerLanguage(name: string, language: (hljs: HLJSApi) => Language): void; + listLanguages(): string[]; + } + + const hljs: HLJSApi; + export default hljs; +} diff --git a/src/lib/types/logger.ts b/src/lib/types/logger.ts new file mode 100644 index 0000000..18f8dc9 --- /dev/null +++ b/src/lib/types/logger.ts @@ -0,0 +1,13 @@ +/** + * Logger interface for consistent logging across the application + * Compatible with both pino (server-side) and console (browser-side) + */ + +export interface Logger { + info(...args: unknown[]): void; + error(...args: unknown[]): void; + warn(...args: unknown[]): void; + debug(...args: unknown[]): void; + trace(...args: unknown[]): void; + fatal(...args: unknown[]): void; +} diff --git a/src/lib/types/nip19.ts b/src/lib/types/nip19.ts new file mode 100644 index 0000000..147f626 --- /dev/null +++ b/src/lib/types/nip19.ts @@ -0,0 +1,80 @@ +/** + * Type definitions for NIP-19 bech32 encoded entities + * These types help with proper typing of nip19.decode() return values + */ + +/** + * Decoded npub (public key) + */ +export interface DecodedNpub { + type: 'npub'; + data: string; // hex pubkey +} + +/** + * Decoded nsec (private key) + */ +export interface DecodedNsec { + type: 'nsec'; + data: Uint8Array; // private key bytes +} + +/** + * Decoded note (event ID) + */ +export interface DecodedNote { + type: 'note'; + data: string; // hex event ID +} + +/** + * Decoded nevent (event reference) + */ +export interface DecodedNevent { + type: 'nevent'; + data: { + id: string; // hex event ID + pubkey?: string; // hex pubkey + relays?: string[]; // relay hints + kind?: number; // event kind + }; +} + +/** + * Decoded naddr (parameterized replaceable event) + */ +export interface DecodedNaddr { + type: 'naddr'; + data: { + pubkey: string; // hex pubkey + kind: number; // event kind + identifier: string; // d-tag value + relays?: string[]; // relay hints + }; +} + +/** + * Union type for all decoded NIP-19 entities + */ +export type DecodedNip19 = DecodedNpub | DecodedNsec | DecodedNote | DecodedNevent | DecodedNaddr; + +/** + * Type guard to check if decoded value is an npub + */ +export function isDecodedNpub(decoded: DecodedNip19): decoded is DecodedNpub { + return decoded.type === 'npub'; +} + +/** + * Type guard to check if decoded value is a nevent + */ +export function isDecodedNevent(decoded: DecodedNip19): decoded is DecodedNevent { + return decoded.type === 'nevent'; +} + +/** + * Type guard to check if decoded value is an naddr + */ +export function isDecodedNaddr(decoded: DecodedNip19): decoded is DecodedNaddr { + return decoded.type === 'naddr'; +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index b15eafa..f8f80fc 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -311,8 +311,13 @@ let queryHex = ''; try { const decoded = nip19.decode(query); - if (decoded.type === 'naddr' || decoded.type === 'nevent') { - queryHex = (decoded.data as any).id || ''; + if (decoded.type === 'nevent') { + const data = decoded.data as { id: string }; + queryHex = data.id || ''; + } else if (decoded.type === 'naddr') { + // For naddr, we can't extract an event ID directly, skip + } else if (decoded.type === 'note') { + queryHex = decoded.data as string; } } catch { // Not a bech32 encoded value diff --git a/src/routes/docs/+page.svelte b/src/routes/docs/+page.svelte index 354014a..29ea25b 100644 --- a/src/routes/docs/+page.svelte +++ b/src/routes/docs/+page.svelte @@ -14,7 +14,7 @@ const hljsModule = await import('highlight.js'); const hljs = hljsModule.default || hljsModule; - const md: any = new MarkdownIt({ + const md = new MarkdownIt({ highlight: function (str: string, lang: string): string { if (lang && hljs.getLanguage(lang)) { try { diff --git a/src/routes/docs/nip34/+page.svelte b/src/routes/docs/nip34/+page.svelte index aa0e7cf..baebff7 100644 --- a/src/routes/docs/nip34/+page.svelte +++ b/src/routes/docs/nip34/+page.svelte @@ -14,7 +14,7 @@ const hljsModule = await import('highlight.js'); const hljs = hljsModule.default || hljsModule; - const md: any = new MarkdownIt({ + const md = new MarkdownIt({ highlight: function (str: string, lang: string): string { if (lang && hljs.getLanguage(lang)) { try { diff --git a/src/routes/docs/nip34/spec/+page.svelte b/src/routes/docs/nip34/spec/+page.svelte index 9c51287..23c360a 100644 --- a/src/routes/docs/nip34/spec/+page.svelte +++ b/src/routes/docs/nip34/spec/+page.svelte @@ -14,7 +14,7 @@ const hljsModule = await import('highlight.js'); const hljs = hljsModule.default || hljsModule; - const md: any = new MarkdownIt({ + const md = new MarkdownIt({ highlight: function (str: string, lang: string): string { if (lang && hljs.getLanguage(lang)) { try { diff --git a/src/routes/repos/[npub]/[repo]/+page.svelte b/src/routes/repos/[npub]/[repo]/+page.svelte index fda2560..8d59154 100644 --- a/src/routes/repos/[npub]/[repo]/+page.svelte +++ b/src/routes/repos/[npub]/[repo]/+page.svelte @@ -128,7 +128,7 @@ const hljsModule = await import('highlight.js'); const hljs = hljsModule.default || hljsModule; - const md: any = new MarkdownIt({ + const md = new MarkdownIt({ highlight: function (str: string, lang: string): string { if (lang && hljs.getLanguage(lang)) { try { @@ -212,7 +212,7 @@ // Register AsciiDoc language if needed (not in highlight.js by default) if (lang === 'asciidoc' && !hljs.getLanguage('asciidoc')) { - hljs.registerLanguage('asciidoc', function(hljs: any) { + hljs.registerLanguage('asciidoc', function(hljs) { return { name: 'AsciiDoc', aliases: ['adoc', 'asciidoc', 'ad'],