feat: add listed field to note for public listing visibility

Notes with listed=false are filtered out from all GET /notes queries.
The field defaults to true so existing and new notes without it remain visible.
Migration handles existing databases with ALTER TABLE ADD COLUMN.
This commit is contained in:
Julien Calixte
2026-02-25 23:03:00 +01:00
parent 62f981dd93
commit f39f62f1c7
4 changed files with 24 additions and 7 deletions

View File

@@ -46,6 +46,10 @@
"type": "string",
"description": "Display theme for the note.",
"knownValues": ["light", "dark"]
},
"listed": {
"type": "boolean",
"description": "Whether the note appears in public listings. Defaults to true."
}
}
}

View File

@@ -22,10 +22,10 @@ type NoteRow = {
export const getNotes = (cursor?: string, limit = 20) => {
const notes = cursor
? db.prepare(
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE rkey < ? ORDER BY rkey DESC LIMIT ?",
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE listed = 1 AND rkey < ? ORDER BY rkey DESC LIMIT ?",
).all<NoteRow>(cursor, limit)
: db.prepare(
"SELECT did, rkey, title, publishedAt, createdAt FROM note ORDER BY rkey DESC LIMIT ?",
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE listed = 1 ORDER BY rkey DESC LIMIT ?",
).all<NoteRow>(limit);
return {
@@ -37,10 +37,10 @@ export const getNotes = (cursor?: string, limit = 20) => {
export const getNotesByDid = (did: string, cursor?: string, limit = 20) => {
const notes = cursor
? db.prepare(
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE did = ? AND rkey < ? ORDER BY rkey DESC LIMIT ?",
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE listed = 1 AND did = ? AND rkey < ? ORDER BY rkey DESC LIMIT ?",
).all<NoteRow>(did, cursor, limit)
: db.prepare(
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE did = ? ORDER BY rkey DESC LIMIT ?",
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE listed = 1 AND did = ? ORDER BY rkey DESC LIMIT ?",
).all<NoteRow>(did, limit);
return {
@@ -107,18 +107,21 @@ export const upsertNote = (note: Note) => {
publishedAt,
createdAt,
did,
rkey
rkey,
listed
)
VALUES (?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(did, rkey)
DO UPDATE SET
title = excluded.title,
publishedAt = excluded.publishedAt
publishedAt = excluded.publishedAt,
listed = excluded.listed
`,
note.title,
note.publishedAt ? new Date(note.publishedAt).toISOString() : now,
note.createdAt ? new Date(note.createdAt).toISOString() : now,
note.did,
note.rkey,
note.listed !== false ? 1 : 0,
);
};

View File

@@ -4,4 +4,5 @@ export type Note = {
title: string;
publishedAt: string;
createdAt: string;
listed?: boolean;
};

View File

@@ -7,10 +7,19 @@ db.exec(`
createdAt DATETIME NOT NULL,
did TEXT NOT NULL,
rkey TEXT NOT NULL,
listed INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY (did, rkey)
);
`);
try {
db.exec(
`ALTER TABLE note ADD COLUMN listed INTEGER NOT NULL DEFAULT 1;`,
);
} catch {
// Column already exists — no-op
}
db.exec(`
CREATE TABLE IF NOT EXISTS state (
key TEXT PRIMARY KEY,