poll.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { Request as ExpressRequest, Response as ExpressResponse } from "express";
  2. import { Option, tryDo } from "@shared/common/async_utils";
  3. import { rpcClient } from "src/utils/rpc";
  4. import { eventLogger } from "src/utils/logging";
  5. import { QueryOptions } from "winston";
  6. export interface LogEvent {
  7. _id: string;
  8. label: string;
  9. level: string;
  10. message: string;
  11. timestamp: string;
  12. }
  13. export interface PollOptions {
  14. limit?: string;
  15. }
  16. function zip(obj: Record<string, unknown[]>): unknown[] {
  17. return Object.values(obj).reduce((prev, cur) => [...prev, ...cur], []);
  18. }
  19. function isNumber(val: unknown): val is number {
  20. return !Number.isNaN(Number.parseInt(val as string, 10));
  21. }
  22. function queryEvents(opts?: QueryOptions | { includeIds?: boolean }):
  23. Promise<Record<string, unknown[]>> {
  24. return new Promise((resolve, reject) => {
  25. eventLogger.query(opts as QueryOptions, (error, results) => {
  26. if (error) {
  27. reject(error);
  28. } else {
  29. resolve(results);
  30. }
  31. });
  32. });
  33. }
  34. export type PollResult = Option<{ events: LogEvent[] }, { error: string }>;
  35. type GetResult = Promise<ExpressResponse<PollResult>>;
  36. export const get = async (req: ExpressRequest, res: ExpressResponse): GetResult => {
  37. const params = req.query as PollOptions;
  38. if (!req.session?.userId) {
  39. return res.json({
  40. ok: false,
  41. error: "Not logged in, please log in",
  42. });
  43. }
  44. const { authorised } = await rpcClient.userAuthorised({ userId: req.session.userId });
  45. if (!authorised) {
  46. return res.json({
  47. ok: false,
  48. error: "Not authorised, please log in",
  49. });
  50. }
  51. const DEFAULT_LIMIT = 50;
  52. const result = await tryDo(queryEvents({
  53. fields: ["level", "message", "label", "timestamp"],
  54. limit: isNumber(params.limit) ? +params.limit : DEFAULT_LIMIT,
  55. includeIds: true,
  56. }));
  57. if (!result.ok) {
  58. return res.json({
  59. ok: false,
  60. error: `Failed to query events. Error: ${result.error}`,
  61. });
  62. }
  63. return res.json({ ok: true, events: zip(result.result) });
  64. };