diff --git a/packages/ditto/storages/DittoAPIStore.test.ts b/packages/ditto/storages/DittoAPIStore.test.ts new file mode 100644 index 00000000..1d51061f --- /dev/null +++ b/packages/ditto/storages/DittoAPIStore.test.ts @@ -0,0 +1,71 @@ +import { DittoPolyPg } from '@ditto/db'; +import { DittoConf } from '@ditto/conf'; +import { genEvent, MockRelay } from '@nostrify/nostrify/test'; +import { assertEquals } from '@std/assert'; +import { generateSecretKey, getPublicKey } from 'nostr-tools'; + +import { DittoAPIStore } from './DittoAPIStore.ts'; + +import type { NostrMetadata } from '@nostrify/types'; + +Deno.test('updateAuthorData sets nip05', async () => { + const alex = generateSecretKey(); + + await using test = setupTest((req) => { + switch (req.url) { + case 'https://gleasonator.dev/.well-known/nostr.json?name=alex': + return jsonResponse({ names: { alex: getPublicKey(alex) } }); + default: + return new Response('Not found', { status: 404 }); + } + }); + + const { db, store } = test; + + const metadata: NostrMetadata = { nip05: 'alex@gleasonator.dev' }; + const event = genEvent({ kind: 0, content: JSON.stringify(metadata) }, alex); + + await store.updateAuthorData(event); + + const row = await db.kysely + .selectFrom('author_stats') + .select(['nip05', 'nip05_domain', 'nip05_hostname']) + .where('pubkey', '=', getPublicKey(alex)) + .executeTakeFirstOrThrow(); + + assertEquals(row.nip05, 'alex@gleasonator.dev'); + assertEquals(row.nip05_domain, 'gleasonator.dev'); + assertEquals(row.nip05_hostname, 'gleasonator.dev'); +}); + +function setupTest(cb: (req: Request) => Response | Promise) { + const conf = new DittoConf(Deno.env); + const db = new DittoPolyPg(conf.databaseUrl); + + const pool = new MockRelay(); + const relay = new MockRelay(); + + const mockFetch: typeof fetch = async (input, init) => { + const req = new Request(input, init); + return await cb(req); + }; + + const store = new DittoAPIStore({ conf, db, relay, pool, fetch: mockFetch }); + + return { + db, + store, + [Symbol.asyncDispose]: async () => { + await store[Symbol.asyncDispose](); + await db[Symbol.asyncDispose](); + }, + }; +} + +function jsonResponse(body: unknown): Response { + return new Response(JSON.stringify(body), { + headers: { + 'Content-Type': 'application/json', + }, + }); +} diff --git a/packages/ditto/storages/DittoAPIStore.ts b/packages/ditto/storages/DittoAPIStore.ts index ad7c6028..f423eae4 100644 --- a/packages/ditto/storages/DittoAPIStore.ts +++ b/packages/ditto/storages/DittoAPIStore.ts @@ -48,6 +48,7 @@ interface DittoAPIStoreOpts { conf: DittoConf; pool: NRelay; relay: NRelay; + fetch?: typeof fetch; } export class DittoAPIStore implements NRelay { diff --git a/packages/ditto/utils/nip05.ts b/packages/ditto/utils/nip05.ts index 60eb8c32..83ddc863 100644 --- a/packages/ditto/utils/nip05.ts +++ b/packages/ditto/utils/nip05.ts @@ -11,6 +11,7 @@ interface GetNip05Opts { conf: DittoConf; relay: NStore; signal?: AbortSignal; + fetch?: typeof fetch; } export async function lookupNip05(nip05: string, opts: GetNip05Opts): Promise { @@ -35,7 +36,7 @@ export async function lookupNip05(nip05: string, opts: GetNip05Opts): Promise