From eb7bdb6a85876583e830a50a76f7e24247845e72 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Wed, 23 Oct 2024 14:01:04 -0400 Subject: [PATCH] feat(api): sort notifications file listing by date (latest first) --- .../notifications/notifications.service.ts | 20 +++++++++++++++---- api/src/unraid-api/types/util.ts | 3 +++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 api/src/unraid-api/types/util.ts diff --git a/api/src/unraid-api/graph/resolvers/notifications/notifications.service.ts b/api/src/unraid-api/graph/resolvers/notifications/notifications.service.ts index a1dd604e7..020a6eea6 100644 --- a/api/src/unraid-api/graph/resolvers/notifications/notifications.service.ts +++ b/api/src/unraid-api/graph/resolvers/notifications/notifications.service.ts @@ -22,9 +22,11 @@ import { fileExists } from '@app/core/utils/files/file-exists'; import { encode as encodeIni } from 'ini'; import { v7 as uuidv7 } from 'uuid'; import { CHOKIDAR_USEPOLLING } from '@app/environment'; -import { emptyDir } from 'fs-extra'; +import { emptyDir, statSync } from 'fs-extra'; import { execa } from 'execa'; import { AppError } from '@app/core/errors/app-error'; +import { SortFn } from '@app/unraid-api/types/util'; +import type { Stats } from 'fs'; @Injectable() export class NotificationsService { @@ -539,13 +541,23 @@ export class NotificationsService { /** * Given a path to a folder, returns the full (absolute) paths of the folder's top-level contents. + * Sorted latest-first by default. + * * @param folderPath The path of the folder to read. + * @param sortFn An optional function to sort folder contents. Defaults to descending birth time. * @returns A list of absolute paths of all the files and contents in the folder. */ - private async listFilesInFolder(folderPath: string): Promise { + private async listFilesInFolder(folderPath: string, sortFn?: SortFn): Promise { + sortFn ??= (fileA, fileB) => fileB.birthtimeMs - fileA.birthtimeMs; // latest first const contents = await readdir(folderPath); - - return contents.map((content) => join(folderPath, content)); + // pre-map each file's stats to avoid excess calls during sorting + return contents + .map((content) => { + const path = join(folderPath, content); + return { path, stats: statSync(path) }; + }) + .sort((fileA, fileB) => sortFn(fileA.stats, fileB.stats)) + .map(({ path }) => path); } /** diff --git a/api/src/unraid-api/types/util.ts b/api/src/unraid-api/types/util.ts new file mode 100644 index 000000000..5c414fa9f --- /dev/null +++ b/api/src/unraid-api/types/util.ts @@ -0,0 +1,3 @@ +// custom utility & helper types + +export type SortFn = (a: T, b: T) => number; \ No newline at end of file