lint fix wip

This commit is contained in:
Nicolas Cantu 2026-01-06 16:10:08 +01:00
parent 303c0bf7df
commit ccf2fdf759
15 changed files with 77 additions and 48 deletions

View File

@ -34,7 +34,7 @@ export function LanguageSelector(): React.ReactElement {
const loadLocale = (): void => {
try {
if (typeof window !== 'undefined') {
const savedLocale = localStorage.getItem(LOCALE_STORAGE_KEY) as Locale | null
const savedLocale = window.localStorage.getItem(LOCALE_STORAGE_KEY) as Locale | null
if (savedLocale && (savedLocale === 'fr' || savedLocale === 'en')) {
setLocale(savedLocale)
setCurrentLocale(savedLocale)
@ -52,7 +52,7 @@ export function LanguageSelector(): React.ReactElement {
setCurrentLocale(locale)
try {
if (typeof window !== 'undefined') {
localStorage.setItem(LOCALE_STORAGE_KEY, locale)
window.localStorage.setItem(LOCALE_STORAGE_KEY, locale)
}
} catch (e) {
console.error('Error saving locale:', e)

View File

@ -38,7 +38,7 @@ export function LanguageSettingsManager(): React.ReactElement {
setLoading(false)
return
}
const savedLocale = localStorage.getItem(LOCALE_STORAGE_KEY) as Locale | null
const savedLocale = window.localStorage.getItem(LOCALE_STORAGE_KEY) as Locale | null
if (savedLocale && (savedLocale === 'fr' || savedLocale === 'en')) {
setLocale(savedLocale)
setCurrentLocale(savedLocale)
@ -57,7 +57,7 @@ export function LanguageSettingsManager(): React.ReactElement {
setCurrentLocale(locale)
try {
if (typeof window !== 'undefined') {
localStorage.setItem(LOCALE_STORAGE_KEY, locale)
window.localStorage.setItem(LOCALE_STORAGE_KEY, locale)
}
} catch (e) {
console.error('Error saving locale:', e)

View File

@ -17,7 +17,7 @@ export function subscribeWithTimeout<T>(
const resolved = { value: false }
const relayUrl = getPrimaryRelaySync()
const sub = createSubscription(pool, [relayUrl], filters)
let timeoutId: NodeJS.Timeout | null = null
let timeoutId: ReturnType<typeof setTimeout> | null = null
const cleanup = (): void => {
if (timeoutId) {

View File

@ -1,6 +1,6 @@
import type { AuthorTags, SeriesTags, PublicationTags, QuoteTags, PaymentTags } from './nostrTagSystemTypes'
function buildBaseTags(tags: AuthorTags | SeriesTags | PublicationTags | QuoteTags): string[][] {
function buildBaseTags(tags: AuthorTags | SeriesTags | PublicationTags | QuoteTags | PaymentTags): string[][] {
const result: string[][] = []
result.push([tags.type])
result.push([tags.category])

View File

@ -42,29 +42,47 @@ export function extractCommonTags(findTag: (key: string) => string | undefined,
reviewerPubkey?: string
json?: string
} {
const id = findTag('id')
const service = findTag('service')
const title = findTag('title')
const preview = findTag('preview')
const description = findTag('description')
const mainnetAddress = findTag('mainnet_address')
const totalSponsoring = parseNumericTag(findTag, 'total_sponsoring')
const pictureUrl = findTag('picture')
const seriesId = findTag('series')
const coverUrl = findTag('cover')
const bannerUrl = findTag('banner')
const zapAmount = parseNumericTag(findTag, 'zap')
const invoice = findTag('invoice')
const paymentHash = findTag('payment_hash')
const encryptedKey = findTag('encrypted_key')
const articleId = findTag('article')
const reviewerPubkey = findTag('reviewer')
const json = findTag('json')
return {
id: findTag('id'),
service: findTag('service'),
...(id ? { id } : {}),
...(service ? { service } : {}),
version: parseNumericTag(findTag, 'version') ?? 0, // Default to 0 if not present
hidden: findTag('hidden') === 'true', // true only if tag exists and value is 'true'
paywall: hasTag('paywall'),
payment: hasTag('payment'),
title: findTag('title'),
preview: findTag('preview'),
description: findTag('description'),
mainnetAddress: findTag('mainnet_address'),
totalSponsoring: parseNumericTag(findTag, 'total_sponsoring'),
pictureUrl: findTag('picture'),
seriesId: findTag('series'),
coverUrl: findTag('cover'),
bannerUrl: findTag('banner'),
zapAmount: parseNumericTag(findTag, 'zap'),
invoice: findTag('invoice'),
paymentHash: findTag('payment_hash'),
encryptedKey: findTag('encrypted_key'),
articleId: findTag('article'),
reviewerPubkey: findTag('reviewer'),
json: findTag('json'), // JSON metadata stored in tag (for all object types)
...(title ? { title } : {}),
...(preview ? { preview } : {}),
...(description ? { description } : {}),
...(mainnetAddress ? { mainnetAddress } : {}),
...(totalSponsoring !== undefined ? { totalSponsoring } : {}),
...(pictureUrl ? { pictureUrl } : {}),
...(seriesId ? { seriesId } : {}),
...(coverUrl ? { coverUrl } : {}),
...(bannerUrl ? { bannerUrl } : {}),
...(zapAmount !== undefined ? { zapAmount } : {}),
...(invoice ? { invoice } : {}),
...(paymentHash ? { paymentHash } : {}),
...(encryptedKey ? { encryptedKey } : {}),
...(articleId ? { articleId } : {}),
...(reviewerPubkey ? { reviewerPubkey } : {}),
...(json ? { json } : {}),
}
}

View File

@ -4,7 +4,7 @@
* One database per object type
*/
import type { Event } from 'nostr-tools'
import type { Event as NostrEvent } from 'nostr-tools'
import type { AuthorPresentationArticle } from '@/types/nostr'
import { buildObjectId } from './urlGenerator'
@ -15,7 +15,7 @@ interface CachedObject {
hash: string // SHA-256 hash of the object
hashId: string // Legacy field for backward compatibility
index: number // Index for duplicates
event: Event
event: NostrEvent
parsed: unknown // Parsed object (AuthorPresentationArticle, Series, etc.)
version: number
hidden: boolean
@ -41,7 +41,7 @@ class ObjectCacheService {
}
const dbName = `${DB_PREFIX}${objectType}`
const request = indexedDB.open(dbName, DB_VERSION)
const request = window.indexedDB.open(dbName, DB_VERSION)
request.onerror = (): void => {
reject(new Error(`Failed to open IndexedDB: ${request.error}`))
@ -112,7 +112,7 @@ class ObjectCacheService {
async set(
objectType: ObjectType,
hash: string,
event: Event,
event: NostrEvent,
parsed: unknown,
version: number,
hidden: boolean,
@ -175,7 +175,7 @@ class ObjectCacheService {
const request = hashIndex.openCursor(IDBKeyRange.only(hash))
const objects: CachedObject[] = []
request.onsuccess = (event: Event): void => {
request.onsuccess = (event: globalThis.Event): void => {
const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result
if (cursor) {
const obj = cursor.value as CachedObject
@ -246,7 +246,7 @@ class ObjectCacheService {
const request = store.openCursor()
const objects: CachedObject[] = []
request.onsuccess = (event: Event): void => {
request.onsuccess = (event: globalThis.Event): void => {
const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result
if (cursor) {
const obj = cursor.value as CachedObject
@ -288,7 +288,7 @@ class ObjectCacheService {
const request = store.openCursor()
const objects: unknown[] = []
request.onsuccess = (event: Event): void => {
request.onsuccess = (event: globalThis.Event): void => {
const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result
if (cursor) {
const obj = cursor.value as CachedObject

View File

@ -46,8 +46,8 @@ export async function publishPurchaseNote(params: {
payerPubkey: params.payerPubkey,
recipientPubkey: params.authorPubkey,
paymentHash: params.paymentHash,
zapReceiptId: params.zapReceiptId,
articleId: params.articleId,
...(params.zapReceiptId ? { zapReceiptId: params.zapReceiptId } : {}),
...(params.seriesId ? { seriesId: params.seriesId } : {}),
})
@ -120,9 +120,9 @@ export async function publishReviewTipNote(params: {
payerPubkey: params.payerPubkey,
recipientPubkey: params.reviewerPubkey,
paymentHash: params.paymentHash,
zapReceiptId: params.zapReceiptId,
articleId: params.articleId,
reviewId: params.reviewId,
...(params.zapReceiptId ? { zapReceiptId: params.zapReceiptId } : {}),
...(params.seriesId ? { seriesId: params.seriesId } : {}),
...(params.text ? { text: params.text } : {}),
})

View File

@ -61,15 +61,16 @@ export async function sendPrivateContentAfterPayment(
}
}
const category = article.category === 'author-presentation' ? undefined : (article.category === 'science-fiction' || article.category === 'scientific-research' ? article.category : undefined)
await publishPurchaseNote({
articleId: article.id,
authorPubkey: article.pubkey,
payerPubkey: recipientPubkey,
amount,
paymentHash,
zapReceiptId,
category: article.category,
seriesId: article.seriesId,
...(zapReceiptId ? { zapReceiptId } : {}),
...(category ? { category } : {}),
...(article.seriesId ? { seriesId: article.seriesId } : {}),
payerPrivateKey,
})
}

View File

@ -28,6 +28,9 @@ function buildPurchaseFilters(articleId?: string, payerPubkey?: string, authorPu
kinds: number[]
since: number
'#kind_type': string[]
authors?: string[]
'#p'?: string[]
'#e'?: string[]
} = {
kinds: [9735], // Zap receipt
since: MIN_EVENT_DATE,

View File

@ -22,6 +22,10 @@ function buildReviewTipFilters(articleId?: string, reviewId?: string, authorPubk
kinds: number[]
since: number
'#kind_type': string[]
'#p'?: string[]
'#e'?: string[]
'#review_id'?: string[]
'#reviewer'?: string[]
} = {
kinds: [9735], // Zap receipt
since: MIN_EVENT_DATE,

View File

@ -22,6 +22,10 @@ function buildSponsoringFilters(authorPubkey?: string, payerPubkey?: string, ser
kinds: number[]
since: number
'#kind_type': string[]
authors?: string[]
'#p'?: string[]
'#series'?: string[]
'#article'?: string[]
} = {
kinds: [9735], // Zap receipt
since: MIN_EVENT_DATE,

View File

@ -5,11 +5,11 @@ function toBase64(bytes: Uint8Array): string {
bytes.forEach((b) => {
binary += String.fromCharCode(b)
})
return btoa(binary)
return window.btoa(binary)
}
function fromBase64(value: string): Uint8Array {
const binary = atob(value)
const binary = window.atob(value)
const bytes = new Uint8Array(binary.length)
for (let i = 0; i < binary.length; i += 1) {
bytes[i] = binary.charCodeAt(i)
@ -20,8 +20,8 @@ function fromBase64(value: string): Uint8Array {
async function importKey(secret: string): Promise<CryptoKey> {
const encoder = new TextEncoder()
const keyMaterial = encoder.encode(secret)
const hash = await crypto.subtle.digest('SHA-256', keyMaterial)
return crypto.subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt'])
const hash = await window.crypto.subtle.digest('SHA-256', keyMaterial)
return window.crypto.subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt'])
}
export interface EncryptedPayload {
@ -31,10 +31,10 @@ export interface EncryptedPayload {
export async function encryptPayload(secret: string, value: unknown): Promise<EncryptedPayload> {
const key = await importKey(secret)
const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH))
const iv = window.crypto.getRandomValues(new Uint8Array(IV_LENGTH))
const encoder = new TextEncoder()
const encoded = encoder.encode(JSON.stringify(value))
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoded)
const ciphertext = await window.crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoded)
return {
iv: toBase64(iv),
ciphertext: toBase64(new Uint8Array(ciphertext)),
@ -47,7 +47,7 @@ export async function decryptPayload<T>(secret: string, payload: EncryptedPayloa
const cipherBytes = fromBase64(payload.ciphertext)
const ivBuffer = ivBytes.buffer as ArrayBuffer
const cipherBuffer = cipherBytes.buffer as ArrayBuffer
const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: ivBuffer }, key, cipherBuffer)
const decrypted = await window.crypto.subtle.decrypt({ name: 'AES-GCM', iv: ivBuffer }, key, cipherBuffer)
const decoder = new TextDecoder()
return JSON.parse(decoder.decode(decrypted)) as T
}

View File

@ -48,7 +48,7 @@ export class IndexedDBStorage {
return
}
const request = indexedDB.open(DB_NAME, DB_VERSION)
const request = window.indexedDB.open(DB_NAME, DB_VERSION)
request.onerror = (): void => {
reject(new Error(`Failed to open IndexedDB: ${request.error}`))

View File

@ -11,7 +11,7 @@ function I18nProvider({ children }: { children: React.ReactNode }) {
return 'fr'
}
try {
const savedLocale = localStorage.getItem('zapwall-locale') as 'fr' | 'en' | null
const savedLocale = window.localStorage.getItem('zapwall-locale') as 'fr' | 'en' | null
if (savedLocale === 'fr' || savedLocale === 'en') {
return savedLocale
}

View File

@ -6,7 +6,6 @@
*/
const { execSync } = require('child_process')
const path = require('path')
const projectRoot = process.cwd()
@ -18,7 +17,7 @@ try {
cwd: projectRoot,
env: { ...process.env, PWD: projectRoot },
})
} catch (error) {
} catch {
// If next lint fails, try eslint directly with flat config
console.log('Falling back to eslint directly...')
try {
@ -35,7 +34,7 @@ try {
cwd: projectRoot,
})
}
} catch (eslintError) {
} catch {
console.error('Both next lint and eslint failed')
process.exit(1)
}