edited notes: recognize not valid dates/keywords, return 0 limit to client

This commit is contained in:
contributor 2025-11-16 17:56:34 +02:00
parent 366a8bd841
commit e1170b2666
2 changed files with 65 additions and 14 deletions

View File

@ -25,6 +25,14 @@ function keywordResolvesToDate(dateStrOrKeyword: string, expectedDate: string) {
}); });
} }
function keywordDoesNotResolve(dateStrOrKeyword: string) {
cls.init(() => {
cls.set("localNowDateTime", clientDate);
const dateFilter = dateNoteLabelKeywordToDateFilter(dateStrOrKeyword);
expect(dateFilter.date).toBe(null);
});
}
describe("edited-notes::dateNoteLabelKeywordToDateFilter", () => { describe("edited-notes::dateNoteLabelKeywordToDateFilter", () => {
beforeEach(() => { beforeEach(() => {
vi.stubEnv('TZ', 'UTC'); vi.stubEnv('TZ', 'UTC');
@ -70,16 +78,32 @@ describe("edited-notes::dateNoteLabelKeywordToDateFilter", () => {
keywordResolvesToDate("2020-12", "2020-12"); keywordResolvesToDate("2020-12", "2020-12");
}); });
it("returns original string for partial month", () => {
keywordResolvesToDate("2020-1", "2020-1");
});
it("returns original string for partial month with trailing dash", () => {
keywordResolvesToDate("2020-", "2020-");
});
it("returns original string for year", () => { it("returns original string for year", () => {
keywordResolvesToDate("2020", "2020"); keywordResolvesToDate("2020", "2020");
}); });
it("returns original string for unrecognized keyword", () => { it("returns original string for potentially partial day", () => {
keywordResolvesToDate("FOO", "FOO"); keywordResolvesToDate("2020-12-1", "2020-12-1");
}); });
it("returns original string for partially recognized keyword", () => { it("returns null for partial year", () => {
keywordResolvesToDate("TODAY-", "TODAY-"); keywordDoesNotResolve("202");
});
it("returns null for arbitrary string", () => {
keywordDoesNotResolve("FOO");
});
it("returns null for missing delta", () => {
keywordDoesNotResolve("TODAY-");
}); });
it("resolves 'today' (lowercase) to today's date", () => { it("resolves 'today' (lowercase) to today's date", () => {

View File

@ -24,6 +24,13 @@ interface NotePojoWithNotePath extends NotePojo {
function getEditedNotesOnDate(req: Request) { function getEditedNotesOnDate(req: Request) {
const dateFilter = dateNoteLabelKeywordToDateFilter(req.params.date); const dateFilter = dateNoteLabelKeywordToDateFilter(req.params.date);
if (!dateFilter.date) {
return {
notes: [],
limit: 0,
} satisfies EditedNotesResponse;
}
const sqlParams = { date: dateFilter.date + "%" }; const sqlParams = { date: dateFilter.date + "%" };
const limit = 50; const limit = 50;
const sqlQuery = /*sql*/`\ const sqlQuery = /*sql*/`\
@ -117,7 +124,7 @@ function formatDateFromKeywordAndDelta(
interface DateValue { interface DateValue {
// kind: "date", // kind: "date",
date: string, date: string | null,
} }
type DateFilter = DateValue; type DateFilter = DateValue;
@ -146,22 +153,42 @@ type DateFilter = DateValue;
* @returns A `DateFilter` object containing the resolved date string. * @returns A `DateFilter` object containing the resolved date string.
*/ */
export function dateNoteLabelKeywordToDateFilter(dateStr: string): DateFilter { export function dateNoteLabelKeywordToDateFilter(dateStr: string): DateFilter {
const match = dateStr.match(/^(today|month|year)([+-]\d+)?$/i); const keywordAndDelta = dateStr.match(/^(today|month|year)([+-]\d+)?$/i);
if (!match) { if (keywordAndDelta) {
return { const keyword = keywordAndDelta[1].toLowerCase();
date: dateStr const delta = keywordAndDelta[2] ? parseInt(keywordAndDelta[2]) : 0;
}
}
const keyword = match[1].toLowerCase();
const delta = match[2] ? parseInt(match[2]) : 0;
const clientDate = dayjs(dateUtils.localNowDate()); const clientDate = dayjs(dateUtils.localNowDate());
const date = formatDateFromKeywordAndDelta(clientDate, keyword, delta); const date = formatDateFromKeywordAndDelta(clientDate, keyword, delta);
return { return {
date: date date: date
};
} }
// Check if it's a valid date format (YYYY-MM-DD, YYYY-MM, or YYYY)
const isDatePrefix = isValidDatePrefix(dateStr);
if (isDatePrefix) {
return {
date: dateStr
};
} else {
// Not a keyword and not a valid date prefix
return {
date: null
}
}
}
function isValidDatePrefix(dateStr: string): boolean {
// Check if it starts with YYYY format
if (/^\d{4}/.test(dateStr)) {
const year = parseInt(dateStr.substring(0, 4));
return !isNaN(year) && year > 0 && year < 10000;
}
return false;
} }
export default { export default {