From 075549893758ba41d628f073706a862e863e689f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lohrer?= Date: Tue, 28 Apr 2026 08:12:01 +0200 Subject: [PATCH] feat(snapshot): output-writer (index.json + posts/.json) Co-Authored-By: Claude Opus 4.7 (1M context) --- snapshot/src/core/output.ts | 41 +++++++++++++++++++++++++++++++++++ snapshot/tests/output.test.ts | 36 ++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 snapshot/src/core/output.ts create mode 100644 snapshot/tests/output.test.ts diff --git a/snapshot/src/core/output.ts b/snapshot/src/core/output.ts new file mode 100644 index 0000000..77b68c3 --- /dev/null +++ b/snapshot/src/core/output.ts @@ -0,0 +1,41 @@ +import { ensureDir } from '@std/fs' +import { join } from '@std/path' +import type { PostJson } from './post-json.ts' + +export interface OutputInput { + generatedAt: string + authorPubkey: string + relaysQueried: string[] + relaysResponded: string[] + posts: PostJson[] +} + +export async function writeOutput(outDir: string, input: OutputInput): Promise { + await ensureDir(outDir) + await ensureDir(join(outDir, 'posts')) + + const index = { + generated_at: input.generatedAt, + author_pubkey: input.authorPubkey, + relays_queried: input.relaysQueried, + relays_responded: input.relaysResponded, + post_count: input.posts.length, + posts: input.posts.map((p) => ({ + slug: p.slug, + lang: p.lang, + created_at: p.created_at, + title: p.title, + })), + } + await Deno.writeTextFile( + join(outDir, 'index.json'), + JSON.stringify(index, null, 2) + '\n', + ) + + for (const post of input.posts) { + await Deno.writeTextFile( + join(outDir, 'posts', `${post.slug}.json`), + JSON.stringify(post, null, 2) + '\n', + ) + } +} diff --git a/snapshot/tests/output.test.ts b/snapshot/tests/output.test.ts new file mode 100644 index 0000000..862b7ee --- /dev/null +++ b/snapshot/tests/output.test.ts @@ -0,0 +1,36 @@ +import { assertEquals } from '@std/assert' +import { join } from '@std/path' +import { writeOutput } from '../src/core/output.ts' +import type { PostJson } from '../src/core/post-json.ts' + +const samplePost: PostJson = { + slug: 'a', event_id: 'e1', created_at: 1, published_at: 1, + title: 'A', summary: 's', lang: 'de', cover_image: null, + content_markdown: '# A', tags: [], naddr: 'naddr1', habla_url: 'https://habla.news/a/naddr1', + translations: [], +} + +Deno.test('writeOutput schreibt index.json + posts/.json', async () => { + const dir = await Deno.makeTempDir() + await writeOutput(dir, { + generatedAt: '2026-04-28T10:00:00Z', + authorPubkey: 'P', + relaysQueried: ['wss://r1', 'wss://r2'], + relaysResponded: ['wss://r1'], + posts: [samplePost], + }) + + const indexText = await Deno.readTextFile(join(dir, 'index.json')) + const index = JSON.parse(indexText) + assertEquals(index.author_pubkey, 'P') + assertEquals(index.post_count, 1) + assertEquals(index.posts.length, 1) + assertEquals(index.posts[0].slug, 'a') + assertEquals(index.posts[0].title, 'A') + assertEquals(index.posts[0].lang, 'de') + + const postText = await Deno.readTextFile(join(dir, 'posts', 'a.json')) + const post = JSON.parse(postText) + assertEquals(post.slug, 'a') + assertEquals(post.content_markdown, '# A') +})