useGithubContents.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { useEffect, useState } from "react";
  2. import { useQuery } from "@tanstack/react-query";
  3. import _ from "lodash";
  4. import { z } from "zod";
  5. import api from "shared/api";
  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
  56. .array(githubContentsValidator)
  57. .parseAsync(res.data);
  58. return parsed;
  59. }
  60. );
  61. useEffect(() => {
  62. if (result.isSuccess) {
  63. const folders = result.data
  64. .filter((c) => c.type === "dir")
  65. .sort((a, b) => a.path.localeCompare(b.path));
  66. const files = result.data
  67. .filter((c) => c.type === "file")
  68. .sort((a, b) => a.path.localeCompare(b.path));
  69. const updatedContents = [...folders, ...files];
  70. if (!_.isEqual(updatedContents, contents)) {
  71. setContents(updatedContents);
  72. }
  73. }
  74. }, [result, contents]);
  75. return {
  76. contents,
  77. isLoading: result.isLoading,
  78. };
  79. };