useGithubContents.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { useQuery } from "@tanstack/react-query";
  2. import _ from "lodash";
  3. import { useEffect, useState } from "react";
  4. import api from "shared/api";
  5. import { z } from "zod";
  6. type UseGithubContentsOptions = {
  7. repoId: number;
  8. repoOwner: string;
  9. repoName: string;
  10. branch: string;
  11. path: string;
  12. projectId: number;
  13. };
  14. const githubContentsValidator = z.discriminatedUnion("type", [
  15. z.object({
  16. path: z.string(),
  17. type: z.literal("file"),
  18. }),
  19. z.object({
  20. path: z.string(),
  21. type: z.literal("dir"),
  22. }),
  23. z.object({
  24. path: z.string(),
  25. type: z.literal("symlink"),
  26. }),
  27. ]);
  28. type GithubContents = z.infer<typeof githubContentsValidator>;
  29. export const useGithubContents = ({
  30. repoId,
  31. repoOwner,
  32. repoName,
  33. branch,
  34. path,
  35. projectId,
  36. }: UseGithubContentsOptions) => {
  37. const [contents, setContents] = useState<GithubContents[]>([]);
  38. const result = useQuery(
  39. ["getGithubContentsAtPath", repoOwner, repoName, branch, path],
  40. async () => {
  41. const res = await api.getBranchContents(
  42. "<token>",
  43. {
  44. dir: path,
  45. },
  46. {
  47. kind: "github",
  48. project_id: projectId,
  49. git_repo_id: repoId,
  50. owner: repoOwner,
  51. name: repoName,
  52. branch,
  53. }
  54. );
  55. const parsed = await z.array(githubContentsValidator).parseAsync(res.data);
  56. return parsed;
  57. }
  58. );
  59. useEffect(() => {
  60. if (result.isSuccess) {
  61. const folders = result.data.filter((c) => c.type === "dir").sort((a, b) => a.path.localeCompare(b.path));
  62. const files = result.data.filter((c) => c.type === "file").sort((a, b) => a.path.localeCompare(b.path));
  63. const updatedContents = [...folders, ...files];
  64. if (!_.isEqual(updatedContents, contents)) {
  65. setContents(updatedContents);
  66. }
  67. }
  68. }, [result, contents]);
  69. return {
  70. contents,
  71. isLoading: result.isLoading,
  72. }
  73. };