Skip to content

Commit a4113c8

Browse files
committed
fix(publisher): news mapper critical and test issues
CRITICAL: Removed ai_generated from news_articles select string — column doesn't exist on news_articles, only on blog_articles. Kept mapper guard for future-proofing when the column is eventually added. Added comment explaining the pattern. IMPORTANT: Enhanced happy-path test with real Markdown assertion (HTML→MD transform) and verified all t tags present (both 'news' and 'stadt'). Added dedicated test for ai_generated guard with synthetic row to pin intent when column is later added.
1 parent c9d7834 commit a4113c8

3 files changed

Lines changed: 21 additions & 2 deletions

File tree

packages/publisher/src/mappers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ export function newsToSpec(row: Row, htmlToMd: (html: string) => string): Publis
322322
if (publishedAt) tags.push(["published_at", String(Math.floor(Date.parse(publishedAt) / 1000))]);
323323
const category = str(row, "category");
324324
if (category && category !== "news") tags.push(["t", category]);
325+
// ai_generated does not yet exist on news_articles (only on blog_articles). The guard
326+
// is harmless when the field is absent and future-proofs the mapper if the column is
327+
// later added, following the pattern of blog_articles migration.
325328
if (row["ai_generated"] === true) tags.push(["ai_generated", "true"]);
326329

327330
return {

packages/publisher/src/sync.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export async function buildSpecs(
168168
if (deps.datasets.includes("news")) {
169169
const rows = await deps.fetchRows(
170170
"news_articles",
171-
"select=id,slug,title,excerpt,content,cover_image_url,category,published_at,ai_generated,status,updated_at,created_at&status=eq.published",
171+
"select=id,slug,title,excerpt,content,cover_image_url,category,published_at,status,updated_at,created_at&status=eq.published",
172172
);
173173
for (const row of rows) {
174174
const spec = newsToSpec(row, htmlToMarkdown);

packages/publisher/test/mappers.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,13 @@ describe("town news mapping (NIP-23)", () => {
206206
const tag = (n: string) => spec.tags.find((t) => t[0] === n)?.[1];
207207
assert.equal(tag("title"), "Stadtfest");
208208
assert.equal(tag("slug"), "stadtfest-2026");
209-
assert.equal(tag("t"), "news");
209+
// Verify HTML→Markdown: no HTML tags remain, real Markdown produced (bold as **)
210+
assert.match(spec.content, /Hallo \*\*Röbel\*\*/);
211+
assert.doesNotMatch(spec.content, /<[a-z]+>/i);
212+
// Collect ALL t tags (not just the first) — should have both "news" and category "stadt"
213+
const allTags = spec.tags.filter((t) => t[0] === "t").map((t) => t[1]);
214+
assert.ok(allTags.includes("news"));
215+
assert.ok(allTags.includes("stadt"));
210216
assert.equal(tag("ai_generated"), "true");
211217
});
212218

@@ -232,6 +238,16 @@ describe("town news mapping (NIP-23)", () => {
232238
assert.ok(!json.includes("leak@example.com"));
233239
assert.ok(!json.includes("0xDEADBEEF"));
234240
});
241+
242+
it("newsToSpec: ai_generated flag is future-proofed (column does not exist on news_articles yet)", () => {
243+
// ai_generated exists only on blog_articles; when the schema adds it to news_articles,
244+
// the mapper already has the guard ready. Test with synthetic row to pin the intent.
245+
const spec = newsToSpec(
246+
{ id: "n4", slug: "s", title: "T", content: "ok", status: "published", updated_at: "2026-07-02T10:00:00Z", ai_generated: true },
247+
htmlToMarkdown,
248+
)!;
249+
assert.deepEqual(spec.tags.find((t) => t[0] === "ai_generated"), ["ai_generated", "true"]);
250+
});
235251
});
236252

237253
describe("marketplace mapping (NIP-15) — withdrawal FIRST", () => {

0 commit comments

Comments
 (0)