feat: update dependencies and refactor pullRequestsStore to use RxJS Observable

This commit is contained in:
Kiril Videlov 2023-11-12 19:32:44 +01:00 committed by Kiril Videlov
parent b4c11c9e6a
commit 94ff6cb3b9
7 changed files with 62 additions and 33 deletions

View File

@ -75,6 +75,7 @@
"prettier-plugin-svelte": "^3.0.3", "prettier-plugin-svelte": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.6", "prettier-plugin-tailwindcss": "^0.5.6",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"svelte": "^4.2.2", "svelte": "^4.2.2",
"svelte-check": "^3.5.2", "svelte-check": "^3.5.2",
"svelte-floating-ui": "^1.5.3", "svelte-floating-ui": "^1.5.3",

View File

@ -1,34 +1,41 @@
import { asyncWritable, type Loadable } from '@square/svelte-store'; import type { Loadable } from '@square/svelte-store';
import lscache from 'lscache'; import lscache from 'lscache';
import { Observable, EMPTY } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { storeToObservable } from '$lib/rxjs/store';
import { PullRequest, type GitHubIntegrationContext } from '$lib/github/types'; import { PullRequest, type GitHubIntegrationContext } from '$lib/github/types';
import { newClient } from '$lib/github/client'; import { newClient } from '$lib/github/client';
import type { CustomStore } from '$lib/vbranches/types';
// Uses the cached value as the initial state and also in the event of being offline // Uses the cached value as the initial state and also in the event of being offline
export function listPullRequestsWithCache( export function listPullRequestsWithCache(
ghContextStore: Loadable<GitHubIntegrationContext | undefined> ghContextStore: Loadable<GitHubIntegrationContext | undefined>
): CustomStore<PullRequest[] | undefined> { ): Observable<PullRequest[]> {
const store = asyncWritable( const ghContextObservable = storeToObservable(ghContextStore);
ghContextStore, const prsObservable = ghContextObservable.pipe(
async (ctx, set) => { switchMap((ctx) => {
if (!ctx) return []; if (!ctx) return EMPTY;
const key = ctx.owner + '/' + ctx.repo; const obs: Observable<PullRequest[]> = new Observable((observer) => {
const cachedValue = lscache.get(key); const key = ctx.owner + '/' + ctx.repo;
if (cachedValue) set(cachedValue); const cachedPrs = lscache.get(key);
const prs = await listPullRequests(ctx); if (cachedPrs) {
if (prs) { observer.next(cachedPrs);
lscache.set(key, prs, 1440); // 1 day ttl }
} const request = listPullRequests(ctx);
return prs; request.then((prs) => {
}, if (prs) {
undefined, observer.next(prs);
{ trackState: true } lscache.set(key, prs, 1440); // 1 day ttl
) as CustomStore<PullRequest[] | undefined>; }
return store; });
});
return obs;
})
);
return prsObservable;
} }
async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequest[] | undefined> { async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequest[]> {
const octokit = newClient(ctx); const octokit = newClient(ctx);
try { try {
const rsp = await octokit.rest.pulls.list({ const rsp = await octokit.rest.pulls.list({
@ -37,7 +44,8 @@ async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequ
}); });
return rsp.data.map(PullRequest.fromApi); return rsp.data.map(PullRequest.fromApi);
} catch (e) { } catch (e) {
console.log(e); console.error(e);
return [];
} }
} }

View File

@ -0,0 +1,15 @@
import type { Readable, Writable, Unsubscriber } from 'svelte/store';
import { Observable } from 'rxjs';
export function storeToObservable<T>(svelteStore: Writable<T> | Readable<T>): Observable<T> {
let unsubscribe: Unsubscriber;
const observable = new Observable<T>((subscriber) => {
unsubscribe = svelteStore.subscribe((val) => {
subscriber.next(val);
});
return () => {
unsubscribe();
};
});
return observable;
}

View File

@ -51,7 +51,6 @@ export const load: LayoutLoad = async ({ params }) => {
const projectStore = getProjectStore(params.projectId); const projectStore = getProjectStore(params.projectId);
const pullRequestsStore = listPullRequestsWithCache(githubContextStore); const pullRequestsStore = listPullRequestsWithCache(githubContextStore);
const pullRequestsState = pullRequestsStore.state;
return { return {
projectId, projectId,
@ -68,7 +67,6 @@ export const load: LayoutLoad = async ({ params }) => {
remoteBranchState, remoteBranchState,
projectStore, projectStore,
githubContextStore, githubContextStore,
pullRequestsStore, pullRequestsStore
pullRequestsState
}; };
}; };

View File

@ -17,11 +17,12 @@
import DomainButton from './DomainButton.svelte'; import DomainButton from './DomainButton.svelte';
import IconBranch from '$lib/icons/IconBranch.svelte'; import IconBranch from '$lib/icons/IconBranch.svelte';
import IconSettings from '$lib/icons/IconSettings.svelte'; import IconSettings from '$lib/icons/IconSettings.svelte';
import type { Observable } from 'rxjs';
export let branchesWithContentStore: CustomStore<Branch[] | undefined>; export let branchesWithContentStore: CustomStore<Branch[] | undefined>;
export let remoteBranchStore: CustomStore<RemoteBranch[] | undefined>; export let remoteBranchStore: CustomStore<RemoteBranch[] | undefined>;
export let baseBranchStore: CustomStore<BaseBranch | undefined>; export let baseBranchStore: CustomStore<BaseBranch | undefined>;
export let pullRequestsStore: CustomStore<PullRequest[] | undefined>; export let pullRequestsStore: Observable<PullRequest[]>;
export let branchController: BranchController; export let branchController: BranchController;
export let project: Project; export let project: Project;
export let githubContext: GitHubIntegrationContext | undefined; export let githubContext: GitHubIntegrationContext | undefined;

View File

@ -6,11 +6,10 @@
import type { PullRequest } from '$lib/github/types'; import type { PullRequest } from '$lib/github/types';
import { showMenu } from 'tauri-plugin-context-menu'; import { showMenu } from 'tauri-plugin-context-menu';
import { projectPullRequestListingFilter, ListPRsFilter } from '$lib/config/config'; import { projectPullRequestListingFilter, ListPRsFilter } from '$lib/config/config';
import type { Loadable } from '@square/svelte-store'; import type { Observable } from 'rxjs';
export let projectId: string; export let projectId: string;
export let pullRequestsStore: Loadable<PullRequest[] | undefined>; export let pullRequestsStore: Observable<PullRequest[]>;
$: pullRequestsState = pullRequestsStore?.state;
let rbViewport: HTMLElement; let rbViewport: HTMLElement;
let rbContents: HTMLElement; let rbContents: HTMLElement;
@ -72,11 +71,9 @@
class="hide-native-scrollbar flex max-h-full flex-grow flex-col overflow-y-scroll overscroll-none" class="hide-native-scrollbar flex max-h-full flex-grow flex-col overflow-y-scroll overscroll-none"
> >
<div bind:this={rbContents}> <div bind:this={rbContents}>
{#if $pullRequestsState?.isLoading} {#if !$pullRequestsStore}
<span>loading...</span> <span>loading...</span>
{:else if $pullRequestsState?.isError} {:else}
<span>something went wrong</span>
{:else if $pullRequestsStore}
{#each filterPRs($pullRequestsStore, $filterChoice) as pr, i} {#each filterPRs($pullRequestsStore, $filterChoice) as pr, i}
<a <a
href="/{projectId}/pull/{pr.number}" href="/{projectId}/pull/{pr.number}"

View File

@ -188,6 +188,9 @@ importers:
reflect-metadata: reflect-metadata:
specifier: ^0.1.13 specifier: ^0.1.13
version: 0.1.13 version: 0.1.13
rxjs:
specifier: ^7.8.1
version: 7.8.1
svelte: svelte:
specifier: ^4.2.2 specifier: ^4.2.2
version: 4.2.2 version: 4.2.2
@ -3857,6 +3860,12 @@ packages:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
dev: true dev: true
/rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
dependencies:
tslib: 2.6.2
dev: true
/sade@1.8.1: /sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'} engines: {node: '>=6'}