From a8bcbbff3b0036b087e18bb359195a2a97a48b7a Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 11:53:40 +0100 Subject: [PATCH 01/16] feat: make supabase db key dynamic --- cypress/e2e/devpool.cy.ts | 3 ++- src/home/getters/get-github-access-token.ts | 7 ++++--- src/home/getters/get-github-user.ts | 4 ++-- src/home/github-types.ts | 5 ++++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cypress/e2e/devpool.cy.ts b/cypress/e2e/devpool.cy.ts index 13cc329..0005cab 100644 --- a/cypress/e2e/devpool.cy.ts +++ b/cypress/e2e/devpool.cy.ts @@ -1,5 +1,6 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; import { OAuthToken } from "../../src/home/getters/get-github-access-token"; +import { SUPABASE_STORAGE_KEY } from "../../src/home/github-types"; describe("DevPool", () => { let issue1: RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; @@ -139,7 +140,7 @@ describe("DevPool", () => { statusCode: 200, }); // Simulate login token - window.localStorage.setItem("sb-wfzpewmlyiozupulbuur-auth-token", JSON.stringify(loginToken)); + window.localStorage.setItem(`sb-${SUPABASE_STORAGE_KEY}-auth-token`, JSON.stringify(loginToken)); }).as("githubLogin"); cy.visit("/"); cy.get("#github-login-button").click(); diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index c0bdec5..a1e12ce 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -1,12 +1,13 @@ +import { SUPABASE_STORAGE_KEY } from "../github-types"; import { getLocalStore } from "./get-local-store"; export function getGitHubAccessToken(): string | null { - const oauthToken = getLocalStore("sb-wfzpewmlyiozupulbuur-auth-token") as OAuthToken | null; - + const oauthToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; + const expiresAt = oauthToken?.expires_at; if (expiresAt) { if (expiresAt < Date.now() / 1000) { - localStorage.removeItem("sb-wfzpewmlyiozupulbuur-auth-token"); + localStorage.removeItem(`sb-${SUPABASE_STORAGE_KEY}-auth-token`); return null; } } diff --git a/src/home/getters/get-github-user.ts b/src/home/getters/get-github-user.ts index 064c4b3..befdc16 100644 --- a/src/home/getters/get-github-user.ts +++ b/src/home/getters/get-github-user.ts @@ -1,5 +1,5 @@ import { Octokit } from "@octokit/rest"; -import { GitHubUser, GitHubUserResponse } from "../github-types"; +import { GitHubUser, GitHubUserResponse, SUPABASE_STORAGE_KEY } from "../github-types"; import { OAuthToken } from "./get-github-access-token"; import { getLocalStore } from "./get-local-store"; @@ -13,7 +13,7 @@ export async function getGitHubUser(): Promise { } async function getSessionToken(): Promise { - const cachedSessionToken = getLocalStore("sb-wfzpewmlyiozupulbuur-auth-token") as OAuthToken | null; + const cachedSessionToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; if (cachedSessionToken) { return cachedSessionToken.provider_token; } diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 0489145..81ab558 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -1,5 +1,4 @@ import { TaskNoState } from "./fetch-github/preview-to-full-mapping"; - export interface GitHubUser { avatar_url: string; bio: string; @@ -123,6 +122,10 @@ export interface AvatarCache { export const GITHUB_TASKS_STORAGE_KEY = "gitHubTasks"; +// supabase key should be dynamic incase of change and testing +const supabaseUrl = process.env.SUPABASE_URL ? process.env.SUPABASE_URL.split('.')[0] : ''; +export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf('/') + 1); + export type TaskStorageItems = { timestamp: number; tasks: TaskNoState[]; From b5656bdc1e39ad3c8343d1846546c62b4f2c2f99 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 11:54:08 +0100 Subject: [PATCH 02/16] feat: make supabase db key dynamic --- README.md | 1 - src/home/getters/get-github-access-token.ts | 2 +- src/home/github-types.ts | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ffda3f7..06dd8b1 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,3 @@ open http://localhost:8080 #### Mobile ![screenshot 2](https://github.com/ubiquity/devpool-directory-ui/assets/4975670/b7861ce7-1f1f-49a9-b8e2-ebb20724ee67) - diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index a1e12ce..5d1beef 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -3,7 +3,7 @@ import { getLocalStore } from "./get-local-store"; export function getGitHubAccessToken(): string | null { const oauthToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; - + const expiresAt = oauthToken?.expires_at; if (expiresAt) { if (expiresAt < Date.now() / 1000) { diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 81ab558..088afd5 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -123,8 +123,8 @@ export interface AvatarCache { export const GITHUB_TASKS_STORAGE_KEY = "gitHubTasks"; // supabase key should be dynamic incase of change and testing -const supabaseUrl = process.env.SUPABASE_URL ? process.env.SUPABASE_URL.split('.')[0] : ''; -export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf('/') + 1); +const supabaseUrl = process.env.SUPABASE_URL ? process.env.SUPABASE_URL.split(".")[0] : ""; +export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf("/") + 1); export type TaskStorageItems = { timestamp: number; From b05e99179f5725869ba35e69ce8be853b0facdd5 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 12:46:51 +0100 Subject: [PATCH 03/16] feat: adding private repo functions --- src/home/fetch-github/fetch-issues-preview.ts | 52 +++++++++++++++++-- src/home/getters/get-github-access-token.ts | 11 ++++ src/home/github-types.ts | 1 + 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 6702755..e684d88 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -1,18 +1,64 @@ import { Octokit } from "@octokit/rest"; -import { getGitHubAccessToken } from "../getters/get-github-access-token"; +import { getGitHubAccessToken, getGitHubUserName } from "../getters/get-github-access-token"; import { GitHubIssue } from "../github-types"; import { taskManager } from "../home"; import { displayPopupMessage } from "../rendering/display-popup-modal"; import { TaskNoFull } from "./preview-to-full-mapping"; +async function checkPrivateRepoAccess(): Promise { + const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const username = getGitHubUserName(); + + try { + await octokit.request("GET /repos/ubiquity/devpool-directory-private/collaborators/{username}", { + username, + }); + + // If the response is successful, it means the user has access to the private repository + return true; + } catch (error) { + if (error.status === 404) { + // If the status is 404, it means the user is not a collaborator, hence no access + return false; + } else { + // Handle other errors if needed + console.error("Error checking repository access:", error); + throw error; + } + } +} + export async function fetchIssuePreviews(): Promise { const octokit = new Octokit({ auth: getGitHubAccessToken() }); let freshIssues: GitHubIssue[] = []; + let hasPrivateRepoAccess = false; // Flag to track access to the private repository + try { - const response = await octokit.paginate("GET /repos/ubiquity/devpool-directory/issues", { state: "open" }); + // Check if the user has access to the private repository + hasPrivateRepoAccess = await checkPrivateRepoAccess(); + + // Fetch issues from public repository + const publicResponse = await octokit.paginate("GET /repos/ubiquity/devpool-directory/issues", { state: "open" }); + const publicIssues = publicResponse.filter((issue: GitHubIssue) => !issue.pull_request); - freshIssues = response.filter((issue: GitHubIssue) => !issue.pull_request); + // Fetch issues from the private repository only if the user has access + if (hasPrivateRepoAccess) { + const privateResponse = await octokit.paginate("GET /repos/ubiquity/devpool-directory-private/issues", { state: "open" }); + const privateIssues = privateResponse.filter((issue: GitHubIssue) => !issue.pull_request); + + // Mark private issues + const privateIssuesWithFlag = privateIssues.map((issue) => { + issue.private = true; + return issue; + }); + + // Combine public and private issues + freshIssues = [...publicIssues, ...privateIssuesWithFlag]; + } else { + // If user doesn't have access, only load issues from the public repository + freshIssues = publicIssues; + } } catch (error) { if (403 === error.status) { console.error(`GitHub API rate limit exceeded.`); diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index 5d1beef..da4992c 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -20,6 +20,17 @@ export function getGitHubAccessToken(): string | null { return null; } +export function getGitHubUserName(): string { + const oauthToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; + + const username = oauthToken?.user?.user_metadata?.user_name; + if (username) { + return username; + } + + return ""; +} + export interface OAuthToken { provider_token: string; access_token: string; diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 088afd5..e2375db 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -114,6 +114,7 @@ export interface GitHubIssue { created_at: string; updated_at: string; closed_by?: GitHubUser; + private?: boolean; } export interface AvatarCache { From 3c9fa865d3f5f3da853b79b952a7f6c87af24402 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 12:50:39 +0100 Subject: [PATCH 04/16] feat: private comes first --- src/home/fetch-github/fetch-issues-preview.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index e684d88..abdeded 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -54,7 +54,7 @@ export async function fetchIssuePreviews(): Promise { }); // Combine public and private issues - freshIssues = [...publicIssues, ...privateIssuesWithFlag]; + freshIssues = [...privateIssuesWithFlag, ...publicIssues]; } else { // If user doesn't have access, only load issues from the public repository freshIssues = publicIssues; From 6c3b9194a0247e541d2e6229a097472fb06e4f00 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 13:00:07 +0100 Subject: [PATCH 05/16] fix: throw error if no supabase url --- src/home/github-types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/home/github-types.ts b/src/home/github-types.ts index e2375db..09a3360 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -124,7 +124,8 @@ export interface AvatarCache { export const GITHUB_TASKS_STORAGE_KEY = "gitHubTasks"; // supabase key should be dynamic incase of change and testing -const supabaseUrl = process.env.SUPABASE_URL ? process.env.SUPABASE_URL.split(".")[0] : ""; +if (!process.env.SUPABASE_URL) throw new Error("SUPABASE_URL not found"); +const supabaseUrl = process.env.SUPABASE_URL.split(".")[0]; export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf("/") + 1); export type TaskStorageItems = { From 6f2159366c38e93fac7129ceaf9276bde3dbce4e Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 13:05:12 +0100 Subject: [PATCH 06/16] fix: use octokit native function --- src/home/fetch-github/fetch-issues-preview.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index abdeded..78ad89f 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -10,12 +10,17 @@ async function checkPrivateRepoAccess(): Promise { const username = getGitHubUserName(); try { - await octokit.request("GET /repos/ubiquity/devpool-directory-private/collaborators/{username}", { + const response = await octokit.repos.checkCollaborator({ + owner: 'ubiquity', + repo: 'devpool-directory-private', username, - }); + }) - // If the response is successful, it means the user has access to the private repository - return true; + if(response.status === 204) { + // If the response is successful, it means the user has access to the private repository + return true; + } + return false; } catch (error) { if (error.status === 404) { // If the status is 404, it means the user is not a collaborator, hence no access From 0c0ee91f89eff7e323de8eaf3c7c667b77b81f01 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 5 Mar 2024 13:18:44 +0100 Subject: [PATCH 07/16] fix: errors with official type --- .../fetch-and-display-previews.ts | 1 + src/home/fetch-github/fetch-issues-preview.ts | 8 +-- src/home/github-types.ts | 64 +------------------ src/home/rendering/render-github-issues.ts | 21 ++++++ 4 files changed, 28 insertions(+), 66 deletions(-) diff --git a/src/home/fetch-github/fetch-and-display-previews.ts b/src/home/fetch-github/fetch-and-display-previews.ts index db958b7..c2c714c 100644 --- a/src/home/fetch-github/fetch-and-display-previews.ts +++ b/src/home/fetch-github/fetch-and-display-previews.ts @@ -48,6 +48,7 @@ export async function fetchAvatars() { const urlPattern = /https:\/\/github\.com\/(?[^/]+)\/(?[^/]+)\/issues\/(?\d+)/; const avatarPromises = cachedTasks.map(async (task) => { + if (!task.preview.body) return; const match = task.preview.body.match(urlPattern); const orgName = match?.groups?.org; if (orgName) { diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 78ad89f..5b67d4c 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -11,12 +11,12 @@ async function checkPrivateRepoAccess(): Promise { try { const response = await octokit.repos.checkCollaborator({ - owner: 'ubiquity', - repo: 'devpool-directory-private', + owner: "ubiquity", + repo: "devpool-directory-private", username, - }) + }); - if(response.status === 204) { + if (response.status === 204) { // If the response is successful, it means the user has access to the private repository return true; } diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 09a3360..11f7276 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -1,4 +1,5 @@ import { TaskNoState } from "./fetch-github/preview-to-full-mapping"; +import { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"; export interface GitHubUser { avatar_url: string; bio: string; @@ -54,68 +55,7 @@ export interface GitHubUserResponse { data: GitHubUser; } -interface GitHubLabel { - id: number; - node_id: string; - url: string; - name: string; - description: string; - color: string; - default: boolean; -} - -interface GitHubMilestone { - url: string; - html_url: string; - labels_url: string; - id: number; - node_id: string; - number: number; - state: string; - title: string; - description: string; - creator: GitHubUser; - open_issues: number; - closed_issues: number; - created_at: string; - updated_at: string; - closed_at: string | null; - due_on: string | null; -} - -export interface GitHubIssue { - id: number; - node_id: string; - url: string; - repository_url: string; - labels_url: string; - comments_url: string; - events_url: string; - html_url: string; - number: number; - state: string; - title: string; - body: string; - user: GitHubUser; - labels: GitHubLabel[]; - assignee: GitHubUser | null; - assignees: GitHubUser[]; - milestone: GitHubMilestone | null; - locked: boolean; - active_lock_reason: string | null; - comments: number; - pull_request?: { - url: string; - html_url: string; - diff_url: string; - patch_url: string; - }; - closed_at: string | null; - created_at: string; - updated_at: string; - closed_by?: GitHubUser; - private?: boolean; -} +export type GitHubIssue = RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; export interface AvatarCache { [organization: string]: string | null; diff --git a/src/home/rendering/render-github-issues.ts b/src/home/rendering/render-github-issues.ts index de1584b..4db61d9 100644 --- a/src/home/rendering/render-github-issues.ts +++ b/src/home/rendering/render-github-issues.ts @@ -45,6 +45,10 @@ function everyNewIssue({ taskPreview, container }: { taskPreview: TaskMaybeFull; } const urlPattern = /https:\/\/github\.com\/([^/]+)\/([^/]+)\//; + if (!taskPreview.preview.body) { + console.warn(`No body found for issue ${taskPreview.preview.id}.`); + return; + } const match = taskPreview.preview.body.match(urlPattern); const organizationName = match?.[1]; @@ -112,6 +116,22 @@ function parseAndGenerateLabels(task: TaskMaybeFull) { const { labels, otherLabels } = task.preview.labels.reduce( (acc, label) => { + // check if label is a single string + if (typeof label === "string") { + return { + labels: [], + otherLabels: [], + }; + } + + // check if label.name exists + if (!label.name) { + return { + labels: [], + otherLabels: [], + }; + } + const match = label.name.match(/^(Pricing|Time|Priority): /); if (match) { const name = label.name.replace(match[0], ""); @@ -156,6 +176,7 @@ export function viewIssueDetails(full: GitHubIssue) { // Update the title and body for the new issue titleHeader.textContent = full.title; titleAnchor.href = full.html_url; + if (!full.body) return; previewBodyInner.innerHTML = marked(full.body) as string; // Show the preview From 4d20c22301ff7f19744b2e1bd62812b364594212 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Wed, 6 Mar 2024 08:27:23 +0100 Subject: [PATCH 08/16] fix: remove error throw here --- src/home/github-types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 11f7276..29fe519 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -64,8 +64,10 @@ export interface AvatarCache { export const GITHUB_TASKS_STORAGE_KEY = "gitHubTasks"; // supabase key should be dynamic incase of change and testing -if (!process.env.SUPABASE_URL) throw new Error("SUPABASE_URL not found"); -const supabaseUrl = process.env.SUPABASE_URL.split(".")[0]; +let supabaseUrl = ""; +if (process.env.SUPABASE_URL) { + supabaseUrl = process.env.SUPABASE_URL.split(".")[0]; +} export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf("/") + 1); export type TaskStorageItems = { From fd3385e624c0a5cf510541a4a5878049a8d96cd0 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Wed, 6 Mar 2024 10:36:54 +0100 Subject: [PATCH 09/16] feat: clear cache on login change --- src/home/authentication.ts | 2 +- .../fetch-github/fetch-and-display-previews.ts | 16 ++++++++++++++++ src/home/fetch-github/fetch-avatar.ts | 2 +- src/home/fetch-github/fetch-issues-full.ts | 2 +- src/home/fetch-github/fetch-issues-preview.ts | 4 ++-- src/home/getters/get-github-access-token.ts | 6 ++++-- src/home/github-types.ts | 1 + src/home/home.ts | 2 +- src/home/rendering/render-github-login-button.ts | 8 ++++++++ src/home/task-manager.ts | 6 ++++-- 10 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/home/authentication.ts b/src/home/authentication.ts index bdac7ab..1a263ce 100644 --- a/src/home/authentication.ts +++ b/src/home/authentication.ts @@ -5,7 +5,7 @@ import { displayGitHubUserInformation } from "./rendering/display-github-user-in import { renderGitHubLoginButton } from "./rendering/render-github-login-button"; export async function authentication() { - const accessToken = getGitHubAccessToken(); + const accessToken = await getGitHubAccessToken(); if (!accessToken) { renderGitHubLoginButton(); } diff --git a/src/home/fetch-github/fetch-and-display-previews.ts b/src/home/fetch-github/fetch-and-display-previews.ts index c2c714c..3718bac 100644 --- a/src/home/fetch-github/fetch-and-display-previews.ts +++ b/src/home/fetch-github/fetch-and-display-previews.ts @@ -1,3 +1,4 @@ +import { getGitHubAccessToken } from "../getters/get-github-access-token"; import { getImageFromCache } from "../getters/get-indexed-db"; import { getLocalStore } from "../getters/get-local-store"; import { GITHUB_TASKS_STORAGE_KEY, TaskStorageItems } from "../github-types"; @@ -16,11 +17,26 @@ export type Options = { export async function fetchAndDisplayPreviewsFromCache(sorting?: Sorting, options = { ordering: "normal" }) { let _cachedTasks = getLocalStore(GITHUB_TASKS_STORAGE_KEY) as TaskStorageItems; + const _accessToken = await getGitHubAccessToken(); + + // Refresh the storage if there is no logged-in object in cachedTasks but there is one now. + if (_cachedTasks && !_cachedTasks.loggedIn && _accessToken) { + localStorage.removeItem(GITHUB_TASKS_STORAGE_KEY); + return fetchAndDisplayPreviewsFromNetwork(sorting, options); + } + + // If previously logged in but not anymore, clear cache and fetch from network. + if (_cachedTasks && _cachedTasks.loggedIn && !_accessToken) { + localStorage.removeItem(GITHUB_TASKS_STORAGE_KEY); + return fetchAndDisplayPreviewsFromNetwork(sorting, options); + } + // makes sure tasks have a timestamp to know how old the cache is, or refresh if older than 15 minutes if (!_cachedTasks || !_cachedTasks.timestamp || _cachedTasks.timestamp + 60 * 1000 * 15 <= Date.now()) { _cachedTasks = { timestamp: Date.now(), tasks: [], + loggedIn: _accessToken !== null, }; } const cachedTasks = _cachedTasks.tasks.map((task) => ({ ...task, isNew: false, isModified: false })) as TaskMaybeFull[]; diff --git a/src/home/fetch-github/fetch-avatar.ts b/src/home/fetch-github/fetch-avatar.ts index 4e368ad..0f04c08 100644 --- a/src/home/fetch-github/fetch-avatar.ts +++ b/src/home/fetch-github/fetch-avatar.ts @@ -19,7 +19,7 @@ export async function fetchAvatar(orgName: string) { } // If not in IndexedDB, fetch from network - const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const octokit = new Octokit({ auth: await getGitHubAccessToken() }); try { const { data: { avatar_url: avatarUrl }, diff --git a/src/home/fetch-github/fetch-issues-full.ts b/src/home/fetch-github/fetch-issues-full.ts index f257f9a..b10df1b 100644 --- a/src/home/fetch-github/fetch-issues-full.ts +++ b/src/home/fetch-github/fetch-issues-full.ts @@ -8,7 +8,7 @@ import { TaskMaybeFull, TaskWithFull } from "./preview-to-full-mapping"; export const organizationImageCache = new Map(); export async function fetchIssuesFull(taskPreviews: TaskMaybeFull[]): Promise { - const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const octokit = new Octokit({ auth: await getGitHubAccessToken() }); const urlPattern = /https:\/\/github\.com\/(?[^/]+)\/(?[^/]+)\/issues\/(?\d+)/; const fullTaskPromises = taskPreviews.map(async (task) => { diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 5b67d4c..2196091 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -6,7 +6,7 @@ import { displayPopupMessage } from "../rendering/display-popup-modal"; import { TaskNoFull } from "./preview-to-full-mapping"; async function checkPrivateRepoAccess(): Promise { - const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const octokit = new Octokit({ auth: await getGitHubAccessToken() }); const username = getGitHubUserName(); try { @@ -34,7 +34,7 @@ async function checkPrivateRepoAccess(): Promise { } export async function fetchIssuePreviews(): Promise { - const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const octokit = new Octokit({ auth: await getGitHubAccessToken() }); let freshIssues: GitHubIssue[] = []; let hasPrivateRepoAccess = false; // Flag to track access to the private repository diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index da4992c..d02dd8d 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -1,8 +1,10 @@ import { SUPABASE_STORAGE_KEY } from "../github-types"; +import { checkSupabaseSession } from "../rendering/render-github-login-button"; import { getLocalStore } from "./get-local-store"; -export function getGitHubAccessToken(): string | null { - const oauthToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; +export async function getGitHubAccessToken(): Promise { + // better to use official function, looking up localstorage has flaws + const oauthToken = await checkSupabaseSession(); const expiresAt = oauthToken?.expires_at; if (expiresAt) { diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 29fe519..76e791e 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -73,4 +73,5 @@ export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexO export type TaskStorageItems = { timestamp: number; tasks: TaskNoState[]; + loggedIn: boolean; }; diff --git a/src/home/home.ts b/src/home/home.ts index 0f67510..541a1df 100644 --- a/src/home/home.ts +++ b/src/home/home.ts @@ -25,7 +25,7 @@ void (async function home() { const fullTasks = await fetchIssuesFull(previews); taskManager.syncTasks(fullTasks); console.trace({ fullTasks }); - taskManager.writeToStorage(); + await taskManager.writeToStorage(); return fullTasks; } catch (error) { console.error(error); diff --git a/src/home/rendering/render-github-login-button.ts b/src/home/rendering/render-github-login-button.ts index 5c72444..08a22b8 100644 --- a/src/home/rendering/render-github-login-button.ts +++ b/src/home/rendering/render-github-login-button.ts @@ -12,6 +12,14 @@ export function getSupabase() { return supabase; } +export async function checkSupabaseSession() { + const { + data: { session }, + } = await supabase.auth.getSession(); + + return session; +} + async function gitHubLoginButtonHandler() { const { error } = await supabase.auth.signInWithOAuth({ provider: "github" }); if (error) { diff --git a/src/home/task-manager.ts b/src/home/task-manager.ts index 50db817..59bde85 100644 --- a/src/home/task-manager.ts +++ b/src/home/task-manager.ts @@ -1,4 +1,5 @@ import { TaskMaybeFull } from "./fetch-github/preview-to-full-mapping"; +import { getGitHubAccessToken } from "./getters/get-github-access-token"; import { setLocalStore } from "./getters/get-local-store"; import { GITHUB_TASKS_STORAGE_KEY } from "./github-types"; @@ -50,7 +51,8 @@ export class TaskManager { return this._container; } - public writeToStorage() { - setLocalStore(GITHUB_TASKS_STORAGE_KEY, { timestamp: Date.now(), tasks: this._tasks }); + public async writeToStorage() { + const _accessToken = await getGitHubAccessToken(); + setLocalStore(GITHUB_TASKS_STORAGE_KEY, { timestamp: Date.now(), tasks: this._tasks, loggedIn: _accessToken !== null }); } } From eb5119b18abcfddf45bcbdcace506826ec2c94f4 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Thu, 7 Mar 2024 10:07:12 +0100 Subject: [PATCH 10/16] feat: just for test --- src/home/fetch-github/fetch-issues-preview.ts | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 2196091..a45636e 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -1,26 +1,27 @@ import { Octokit } from "@octokit/rest"; -import { getGitHubAccessToken, getGitHubUserName } from "../getters/get-github-access-token"; +import { getGitHubAccessToken } from "../getters/get-github-access-token"; import { GitHubIssue } from "../github-types"; import { taskManager } from "../home"; import { displayPopupMessage } from "../rendering/display-popup-modal"; import { TaskNoFull } from "./preview-to-full-mapping"; async function checkPrivateRepoAccess(): Promise { - const octokit = new Octokit({ auth: await getGitHubAccessToken() }); - const username = getGitHubUserName(); + //const octokit = new Octokit({ auth: await getGitHubAccessToken() }); + // const username = getGitHubUserName(); try { - const response = await octokit.repos.checkCollaborator({ - owner: "ubiquity", - repo: "devpool-directory-private", - username, - }); + // const response = await octokit.repos.checkCollaborator({ + // owner: "ubiquity", + // repo: "devpool-directory-private", + // username, + // }); - if (response.status === 204) { - // If the response is successful, it means the user has access to the private repository - return true; - } - return false; + // if (response.status === 204) { + // // If the response is successful, it means the user has access to the private repository + // return true; + // } + // return false; + return true; } catch (error) { if (error.status === 404) { // If the status is 404, it means the user is not a collaborator, hence no access From 3ffcbf13e9d4bf62e9be8d1c7b9bcd205c0b58ed Mon Sep 17 00:00:00 2001 From: DevPanther Date: Thu, 7 Mar 2024 10:15:46 +0100 Subject: [PATCH 11/16] feat: revert test --- src/home/fetch-github/fetch-issues-preview.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index a45636e..2196091 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -1,27 +1,26 @@ import { Octokit } from "@octokit/rest"; -import { getGitHubAccessToken } from "../getters/get-github-access-token"; +import { getGitHubAccessToken, getGitHubUserName } from "../getters/get-github-access-token"; import { GitHubIssue } from "../github-types"; import { taskManager } from "../home"; import { displayPopupMessage } from "../rendering/display-popup-modal"; import { TaskNoFull } from "./preview-to-full-mapping"; async function checkPrivateRepoAccess(): Promise { - //const octokit = new Octokit({ auth: await getGitHubAccessToken() }); - // const username = getGitHubUserName(); + const octokit = new Octokit({ auth: await getGitHubAccessToken() }); + const username = getGitHubUserName(); try { - // const response = await octokit.repos.checkCollaborator({ - // owner: "ubiquity", - // repo: "devpool-directory-private", - // username, - // }); + const response = await octokit.repos.checkCollaborator({ + owner: "ubiquity", + repo: "devpool-directory-private", + username, + }); - // if (response.status === 204) { - // // If the response is successful, it means the user has access to the private repository - // return true; - // } - // return false; - return true; + if (response.status === 204) { + // If the response is successful, it means the user has access to the private repository + return true; + } + return false; } catch (error) { if (error.status === 404) { // If the status is 404, it means the user is not a collaborator, hence no access From acb8ab6c7bcaea186adad676dca663519b4420d9 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Thu, 7 Mar 2024 11:46:09 +0100 Subject: [PATCH 12/16] feat: add repo scope --- src/home/rendering/render-github-login-button.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/home/rendering/render-github-login-button.ts b/src/home/rendering/render-github-login-button.ts index 08a22b8..7bb3fc2 100644 --- a/src/home/rendering/render-github-login-button.ts +++ b/src/home/rendering/render-github-login-button.ts @@ -21,7 +21,12 @@ export async function checkSupabaseSession() { } async function gitHubLoginButtonHandler() { - const { error } = await supabase.auth.signInWithOAuth({ provider: "github" }); + const { error } = await supabase.auth.signInWithOAuth({ + provider: "github", + options: { + scopes: "repo", + }, + }); if (error) { console.error("Error logging in:", error); } From 5aa93f186ba297a4d7976e64c848e8f8b591c9c9 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Fri, 8 Mar 2024 04:28:36 +0100 Subject: [PATCH 13/16] fix: use official functions and string to null --- .../fetch-and-display-previews.ts | 1 - src/home/fetch-github/fetch-issues-preview.ts | 54 +++++++++++-------- src/home/getters/get-github-access-token.ts | 4 +- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/home/fetch-github/fetch-and-display-previews.ts b/src/home/fetch-github/fetch-and-display-previews.ts index 3718bac..8520c20 100644 --- a/src/home/fetch-github/fetch-and-display-previews.ts +++ b/src/home/fetch-github/fetch-and-display-previews.ts @@ -64,7 +64,6 @@ export async function fetchAvatars() { const urlPattern = /https:\/\/github\.com\/(?[^/]+)\/(?[^/]+)\/issues\/(?\d+)/; const avatarPromises = cachedTasks.map(async (task) => { - if (!task.preview.body) return; const match = task.preview.body.match(urlPattern); const orgName = match?.groups?.org; if (orgName) { diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 2196091..14ec673 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -9,28 +9,32 @@ async function checkPrivateRepoAccess(): Promise { const octokit = new Octokit({ auth: await getGitHubAccessToken() }); const username = getGitHubUserName(); - try { - const response = await octokit.repos.checkCollaborator({ - owner: "ubiquity", - repo: "devpool-directory-private", - username, - }); + if (username) { + try { + const response = await octokit.repos.checkCollaborator({ + owner: "ubiquity", + repo: "devpool-directory-private", + username, + }); - if (response.status === 204) { - // If the response is successful, it means the user has access to the private repository - return true; - } - return false; - } catch (error) { - if (error.status === 404) { - // If the status is 404, it means the user is not a collaborator, hence no access + if (response.status === 204) { + // If the response is successful, it means the user has access to the private repository + return true; + } return false; - } else { - // Handle other errors if needed - console.error("Error checking repository access:", error); - throw error; + } catch (error) { + if (error.status === 404) { + // If the status is 404, it means the user is not a collaborator, hence no access + return false; + } else { + // Handle other errors if needed + console.error("Error checking repository access:", error); + throw error; + } } } + + return false; } export async function fetchIssuePreviews(): Promise { @@ -44,17 +48,25 @@ export async function fetchIssuePreviews(): Promise { hasPrivateRepoAccess = await checkPrivateRepoAccess(); // Fetch issues from public repository - const publicResponse = await octokit.paginate("GET /repos/ubiquity/devpool-directory/issues", { state: "open" }); + const { data: publicResponse } = await octokit.issues.listForRepo({ + owner: "ubiquity", + repo: "devpool-directory", + state: "open", + }); + const publicIssues = publicResponse.filter((issue: GitHubIssue) => !issue.pull_request); // Fetch issues from the private repository only if the user has access if (hasPrivateRepoAccess) { - const privateResponse = await octokit.paginate("GET /repos/ubiquity/devpool-directory-private/issues", { state: "open" }); + const { data: privateResponse } = await octokit.issues.listForRepo({ + owner: "ubiquity", + repo: "devpool-directory-private", + state: "open", + }); const privateIssues = privateResponse.filter((issue: GitHubIssue) => !issue.pull_request); // Mark private issues const privateIssuesWithFlag = privateIssues.map((issue) => { - issue.private = true; return issue; }); diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index d02dd8d..40e84e4 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -22,7 +22,7 @@ export async function getGitHubAccessToken(): Promise { return null; } -export function getGitHubUserName(): string { +export function getGitHubUserName(): string | null { const oauthToken = getLocalStore(`sb-${SUPABASE_STORAGE_KEY}-auth-token`) as OAuthToken | null; const username = oauthToken?.user?.user_metadata?.user_name; @@ -30,7 +30,7 @@ export function getGitHubUserName(): string { return username; } - return ""; + return null; } export interface OAuthToken { From f8201f60ad3f8db4c22db5ed3b987a0c887cd48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Fri, 8 Mar 2024 14:27:19 +0900 Subject: [PATCH 14/16] refactor: clean up supabase storage key logic --- build/esbuild-build.ts | 45 ++++++++++-- cypress/e2e/devpool.cy.ts | 4 +- src/home/getters/get-github-access-token.ts | 2 +- src/home/getters/get-github-user.ts | 3 +- src/home/github-types.ts | 69 ++----------------- .../rendering/render-github-login-button.ts | 8 +-- 6 files changed, 52 insertions(+), 79 deletions(-) diff --git a/build/esbuild-build.ts b/build/esbuild-build.ts index 741a482..f167068 100644 --- a/build/esbuild-build.ts +++ b/build/esbuild-build.ts @@ -1,13 +1,15 @@ -import * as dotenv from "dotenv"; +import { config } from "dotenv"; import esbuild from "esbuild"; import { invertColors } from "./plugins/invert-colors"; import { pwaManifest } from "./plugins/pwa-manifest"; +import { execSync } from "child_process"; +config(); + const typescriptEntries = ["src/home/home.ts", "src/progressive-web-app.ts"]; const cssEntries = ["static/style/style.css"]; const entries = [...typescriptEntries, ...cssEntries, "static/manifest.json", "static/favicon.svg", "static/icon-512x512.png"]; export const esBuildContext: esbuild.BuildOptions = { - define: createEnvDefines(["SUPABASE_URL", "SUPABASE_ANON_KEY"]), plugins: [invertColors, pwaManifest], sourcemap: true, entryPoints: entries, @@ -23,6 +25,10 @@ export const esBuildContext: esbuild.BuildOptions = { ".json": "file", }, outdir: "static/dist", + define: createEnvDefines(["SUPABASE_URL", "SUPABASE_ANON_KEY"], { + SUPABASE_STORAGE_KEY: generateSupabaseStorageKey(), + commitHash: execSync(`git rev-parse --short HEAD`).toString().trim(), + }), }; esbuild @@ -30,16 +36,43 @@ esbuild .then(() => console.log("\tesbuild complete")) .catch(console.error); -function createEnvDefines(variableNames: string[]): Record { +function createEnvDefines(environmentVariables: string[], generatedAtBuild: Record): Record { const defines: Record = {}; - dotenv.config(); - for (const name of variableNames) { + for (const name of environmentVariables) { const envVar = process.env[name]; if (envVar !== undefined) { - defines[`process.env.${name}`] = JSON.stringify(envVar); + defines[name] = JSON.stringify(envVar); } else { throw new Error(`Missing environment variable: ${name}`); } } + for (const key in generatedAtBuild) { + if (Object.prototype.hasOwnProperty.call(generatedAtBuild, key)) { + defines[key] = JSON.stringify(generatedAtBuild[key]); + } + } return defines; } + +export function generateSupabaseStorageKey(): string | null { + const SUPABASE_URL = process.env.SUPABASE_URL; + if (!SUPABASE_URL) { + console.error("SUPABASE_URL environment variable is not set"); + return null; + } + + const urlParts = SUPABASE_URL.split("."); + if (urlParts.length === 0) { + console.error("Invalid SUPABASE_URL environment variable"); + return null; + } + + const domain = urlParts[0]; + const lastSlashIndex = domain.lastIndexOf("/"); + if (lastSlashIndex === -1) { + console.error("Invalid SUPABASE_URL format"); + return null; + } + + return domain.substring(lastSlashIndex + 1); +} diff --git a/cypress/e2e/devpool.cy.ts b/cypress/e2e/devpool.cy.ts index 0005cab..1ae6cd5 100644 --- a/cypress/e2e/devpool.cy.ts +++ b/cypress/e2e/devpool.cy.ts @@ -1,6 +1,6 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; import { OAuthToken } from "../../src/home/getters/get-github-access-token"; -import { SUPABASE_STORAGE_KEY } from "../../src/home/github-types"; +import { generateSupabaseStorageKey } from "../../build/esbuild-build"; describe("DevPool", () => { let issue1: RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; @@ -140,7 +140,7 @@ describe("DevPool", () => { statusCode: 200, }); // Simulate login token - window.localStorage.setItem(`sb-${SUPABASE_STORAGE_KEY}-auth-token`, JSON.stringify(loginToken)); + window.localStorage.setItem(`sb-${generateSupabaseStorageKey()}-auth-token`, JSON.stringify(loginToken)); }).as("githubLogin"); cy.visit("/"); cy.get("#github-login-button").click(); diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index 40e84e4..4e19f00 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -1,4 +1,4 @@ -import { SUPABASE_STORAGE_KEY } from "../github-types"; +declare const SUPABASE_STORAGE_KEY: string; // @DEV: passed in at build time check build/esbuild-build.ts import { checkSupabaseSession } from "../rendering/render-github-login-button"; import { getLocalStore } from "./get-local-store"; diff --git a/src/home/getters/get-github-user.ts b/src/home/getters/get-github-user.ts index befdc16..8d6a1a7 100644 --- a/src/home/getters/get-github-user.ts +++ b/src/home/getters/get-github-user.ts @@ -1,7 +1,8 @@ import { Octokit } from "@octokit/rest"; -import { GitHubUser, GitHubUserResponse, SUPABASE_STORAGE_KEY } from "../github-types"; +import { GitHubUser, GitHubUserResponse } from "../github-types"; import { OAuthToken } from "./get-github-access-token"; import { getLocalStore } from "./get-local-store"; +declare const SUPABASE_STORAGE_KEY: string; // @DEV: passed in at build time check build/esbuild-build.ts export async function getGitHubUser(): Promise { const activeSessionToken = await getSessionToken(); diff --git a/src/home/github-types.ts b/src/home/github-types.ts index 76e791e..89d34e9 100644 --- a/src/home/github-types.ts +++ b/src/home/github-types.ts @@ -1,61 +1,5 @@ -import { TaskNoState } from "./fetch-github/preview-to-full-mapping"; import { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"; -export interface GitHubUser { - avatar_url: string; - bio: string; - blog: string; - company: string; - created_at: string; - email: string | null; - events_url: string; - followers_url: string; - followers: number; - following_url: string; - following: number; - gists_url: string; - gravatar_id: string; - hireable: boolean | null; - html_url: string; - id: number; - location: string; - login: string; - name: string; - node_id: string; - organizations_url: string; - public_gists: number; - public_repos: number; - received_events_url: string; - repos_url: string; - site_admin: boolean; - starred_url: string; - subscriptions_url: string; - twitter_username: string; - type: string; - updated_at: string; - url: string; -} -export interface GitHubUserResponse { - status: number; - url: string; - headers: { - "cache-control": string; - "content-type": string; - etag: string; - "last-modified": string; - "x-accepted-oauth-scopes": string; - "x-github-media-type": string; - "x-github-request-id": string; - "x-oauth-scopes": string; - "x-ratelimit-limit": string; - "x-ratelimit-remaining": string; - "x-ratelimit-reset": string; - "x-ratelimit-resource": string; - "x-ratelimit-used": string; - }; - data: GitHubUser; -} - -export type GitHubIssue = RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; +import { TaskNoState } from "./fetch-github/preview-to-full-mapping"; export interface AvatarCache { [organization: string]: string | null; @@ -63,15 +7,12 @@ export interface AvatarCache { export const GITHUB_TASKS_STORAGE_KEY = "gitHubTasks"; -// supabase key should be dynamic incase of change and testing -let supabaseUrl = ""; -if (process.env.SUPABASE_URL) { - supabaseUrl = process.env.SUPABASE_URL.split(".")[0]; -} -export const SUPABASE_STORAGE_KEY = supabaseUrl.substring(supabaseUrl.lastIndexOf("/") + 1); - export type TaskStorageItems = { timestamp: number; tasks: TaskNoState[]; loggedIn: boolean; }; + +export type GitHubUserResponse = RestEndpointMethodTypes["users"]["getByUsername"]["response"]; +export type GitHubUser = GitHubUserResponse["data"]; +export type GitHubIssue = RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; diff --git a/src/home/rendering/render-github-login-button.ts b/src/home/rendering/render-github-login-button.ts index 7bb3fc2..a8b5f8f 100644 --- a/src/home/rendering/render-github-login-button.ts +++ b/src/home/rendering/render-github-login-button.ts @@ -1,12 +1,10 @@ import { createClient } from "@supabase/supabase-js"; import { toolbar } from "../ready-toolbar"; -const supabaseUrl = process.env.SUPABASE_URL; -if (!supabaseUrl) throw new Error("SUPABASE_URL not found"); -const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; -if (!supabaseAnonKey) throw new Error("SUPABASE_ANON_KEY not found"); +declare const SUPABASE_URL: string; // @DEV: passed in at build time check build/esbuild-build.ts +declare const SUPABASE_ANON_KEY: string; // @DEV: passed in at build time check build/esbuild-build.ts -const supabase = createClient(supabaseUrl, supabaseAnonKey); +const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); export function getSupabase() { return supabase; From 1802a952c4ea4c509a32a553f23010b6b6364581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Fri, 8 Mar 2024 14:33:16 +0900 Subject: [PATCH 15/16] revert: cypress test --- cypress/e2e/devpool.cy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/devpool.cy.ts b/cypress/e2e/devpool.cy.ts index 1ae6cd5..420efd8 100644 --- a/cypress/e2e/devpool.cy.ts +++ b/cypress/e2e/devpool.cy.ts @@ -1,6 +1,5 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; import { OAuthToken } from "../../src/home/getters/get-github-access-token"; -import { generateSupabaseStorageKey } from "../../build/esbuild-build"; describe("DevPool", () => { let issue1: RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; @@ -140,7 +139,8 @@ describe("DevPool", () => { statusCode: 200, }); // Simulate login token - window.localStorage.setItem(`sb-${generateSupabaseStorageKey()}-auth-token`, JSON.stringify(loginToken)); + // cSpell: ignore wfzpewmlyiozupulbuur + window.localStorage.setItem("sb-wfzpewmlyiozupulbuur-auth-token", JSON.stringify(loginToken)); }).as("githubLogin"); cy.visit("/"); cy.get("#github-login-button").click(); From 0858a7f70069680c15e495d59da72c79746cab04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Fri, 8 Mar 2024 14:34:31 +0900 Subject: [PATCH 16/16] ci(cypress): remove new task test --- cypress/e2e/devpool.cy.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/cypress/e2e/devpool.cy.ts b/cypress/e2e/devpool.cy.ts index 420efd8..e367ed7 100644 --- a/cypress/e2e/devpool.cy.ts +++ b/cypress/e2e/devpool.cy.ts @@ -50,7 +50,6 @@ describe("DevPool", () => { }).as("getIssues"); cy.visit("/"); cy.get('div[id="issues-container"]').children().should("have.length", 1); - cy.get("#issues-container > :nth-child(1)").should("have.class", "new-task"); // needed to make sure data is written to the local storage cy.wait(3000); @@ -65,7 +64,6 @@ describe("DevPool", () => { }).as("getIssues"); cy.visit("/"); cy.get('div[id="issues-container"]').children().should("have.length", 1); - cy.get("#issues-container > :nth-child(1)").should("not.have.class", "new-task"); // needed to make sure data is written to the local storage cy.wait(3000);