From 124507d074d5607da3887554230894b3c98b7d82 Mon Sep 17 00:00:00 2001 From: yourfriendoss Date: Mon, 15 Dec 2025 22:46:49 +0200 Subject: [PATCH] give out .json and .csv, not only .ndjson --- index.ts | 14 +++++++++++++- lib.ts | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 641e13e..06d246b 100644 --- a/index.ts +++ b/index.ts @@ -1,5 +1,5 @@ import { parseHTML } from "linkedom" -import { ndjsonToJson, prettyStringify, requireBasicAuth, tripleBool, type Change, type Entry } from "./lib"; +import { jsonToCsv, ndjsonToJson, prettyStringify, requireBasicAuth, tripleBool, type Change, type Entry } from "./lib"; import * as fs from "fs/promises" import { existsSync } from "fs"; import { $ } from "bun" @@ -193,6 +193,18 @@ export class ClientResponse extends Response { Bun.serve({ routes: { "/": () => new ClientResponse("Sheets v2"), + "/artists.json": async () => ClientResponse.json( + ndjsonToJson((await fs.readFile("artists.ndjson")).toString("utf8")) + ), + "/artists.csv": async () => new ClientResponse( + jsonToCsv( + ndjsonToJson((await fs.readFile("artists.ndjson")).toString("utf8") + ) + ), { + headers: { + "Content-Type": "text/csv" + } + }), "/artists.ndjson": async () => new ClientResponse(await fs.readFile("artists.ndjson")), "/th_artists.ndjson": async () => new ClientResponse(await fs.readFile("th_artists.ndjson")), "/ignore-th/:id": async (req) => { diff --git a/lib.ts b/lib.ts index 066af3e..b4380ee 100644 --- a/lib.ts +++ b/lib.ts @@ -17,6 +17,20 @@ export const thIgnore = [ "bpmkeytracker", ] +export function jsonToCsv(data: unknown|unknown[]) { + const arr = Array.isArray(data) ? data : [data]; + const headers = [...new Set(arr.flatMap(o => Object.keys(o)))]; + + const escape = (v: string )=> + `"${String(v ?? "").replace(/"/g, '""')}"`; + + const rows = arr.map(o => + headers.map(h => escape(o[h])).join(",") + ); + + return [headers.join(","), ...rows].join("\n"); +} + export enum TripleBool { MOSTLY = 2, YES = 1,