Skip to content

Commit

Permalink
feat: use @tanstack/solid-query for caching
Browse files Browse the repository at this point in the history
  • Loading branch information
c0rydoras authored Mar 13, 2024
1 parent 525ba4a commit 3616afe
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 112 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@typescript-eslint/eslint-plugin": "7.1.1",
"@typescript-eslint/parser": "7.1.1",
"autoprefixer": "10.4.18",
"@tanstack/solid-query-devtools": "^5.18.0",
"concurrently": "^8.2.2",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
Expand All @@ -48,6 +49,7 @@
},
"dependencies": {
"@solid-primitives/local-store": "^1.1.4",
"@tanstack/solid-query": "^5.18.0",
"@tauri-apps/api": "1.5.3",
"@tauri-apps/cli": "1.5.11",
"solid-heroicons": "^3.2.4",
Expand Down
32 changes: 32 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 12 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { invoke } from '@tauri-apps/api/tauri';
import { Icon } from 'solid-heroicons';
import { lockClosed, magnifyingGlass } from 'solid-heroicons/outline';
import { createEffect, createResource, For, Show, type Component } from 'solid-js';
import { For, Show, type Component } from 'solid-js';
import { Dynamic } from 'solid-js/web';
import vault from './assets/vault-logo.svg';
import Breadcrumbs from './Breadcrumbs';
Expand All @@ -11,16 +10,9 @@ import Search from './Search';
import SearchIndex from './SearchIndex';
import SecretList from './SecretList';
import SecretView from './SecretView';
import { Toaster, toast } from 'solid-toast';
import { setState, state } from './state';

const listKVS = async (): Promise<null | string[]> => {
try {
return await invoke('list_kvs');
} catch (e) {
toast.error(e);
}
};
import { fetchKVS, toSorted } from './utils';
import { createQuery } from '@tanstack/solid-query';

const Home = () => <strong>Select a KV to get started</strong>;

Expand All @@ -34,11 +26,11 @@ const pageMap: { [key: string]: Component } = {
};

const App: Component = () => {
const [kvs, { refetch }] = createResource(listKVS);

createEffect(() => {
if (state.page === 'home') refetch();
});
const kvsQuery = createQuery(() => ({
queryKey: ['kvs'],
queryFn: fetchKVS,
enabled: state.page !== 'login',
}));

return (
<>
Expand Down Expand Up @@ -81,11 +73,11 @@ const App: Component = () => {
classList={{ hidden: state.page === 'login' }}
>
<div class="mt-4">
{state.page !== 'login' && kvs.loading && (
<Show when={kvsQuery.isPending}>
<strong>Loading...</strong>
)}
<Show when={state.page !== 'login' && kvs()}>
<For each={kvs().sort()}>
</Show>
<Show when={kvsQuery.isSuccess}>
<For each={toSorted(kvsQuery.data)}>
{(kv) => <Node kv={kv} path="" icon={lockClosed} />}
</For>
</Show>
Expand All @@ -97,7 +89,6 @@ const App: Component = () => {
</h1>
<Dynamic component={pageMap[state.page]} />
</main>
<Toaster position="bottom-right" />
</div>
</>
);
Expand Down
61 changes: 48 additions & 13 deletions src/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
import { For } from 'solid-js';
import { For, Show, createSignal } from 'solid-js';
import { setState, state } from './state';
import { splitPath } from './utils';
import { createQuery, useQueryClient } from '@tanstack/solid-query';
import { Icon } from 'solid-heroicons';
import { arrowPath } from 'solid-heroicons/outline';

const Breadcrumbs = () => {
const [spinning, setSpinning] = createSignal(false);
const queryClient = useQueryClient();
const handleClick = (segment: string) => {
const path = splitPath(state.path)
.slice(0, splitPath(state.path).indexOf(segment) + 1)
.join('');
setState({ page: 'list', path });
};

const queryKey = () => (state.kv ? ['paths', state.kv, state.path] : ['kvs']);
const query = createQuery(() => ({
queryKey: queryKey(),
enabled: false,
}));

const refresh = async () => {
setSpinning(true);
await queryClient.refetchQueries({ queryKey: queryKey() });
setSpinning(false);
};

return (
<div>
<span onClick={() => setState({ page: 'list', path: '' })}>{state.kv}</span>
<For each={splitPath(state.path)}>
{(segment) => (
<span
class="[&:not(:last-of-type)]:cursor-pointer"
onClick={() => handleClick(segment)}
>
{segment}
<>
<div class="flex py-2">
<div class="w-full">
<span onClick={() => setState({ page: 'list', path: '' })}>
{state.kv}
</span>
)}
</For>
</div>
<For each={splitPath(state.path)}>
{(segment) => (
<span
class="[&:not(:last-of-type)]:cursor-pointer"
onClick={() => handleClick(segment)}
>
{segment}
</span>
)}
</For>
</div>
<Show when={state.page !== 'login'}>
<button
class="disabled:text-slate-900"
classList={{
'animate-[0.5s_spin_linear_infinite]': spinning(),
}}
disabled={query.isPending}
onClick={refresh}
>
<Icon path={arrowPath} class="w-[1em]" />
</button>
</Show>
</div>
</>
);
};

Expand Down
48 changes: 22 additions & 26 deletions src/Node.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { invoke } from '@tauri-apps/api/tauri';
import { Icon } from 'solid-heroicons';
import {
chevronDown,
Expand All @@ -8,6 +7,8 @@ import {
} from 'solid-heroicons/outline';
import { createSignal, For, JSXElement, Show, type Component } from 'solid-js';
import Item from './Item';
import { createQuery } from '@tanstack/solid-query';
import { fetchPaths, toSorted } from './utils';

type NodeProps = {
icon: { path: JSXElement; outline: boolean; mini: boolean };
Expand All @@ -17,36 +18,20 @@ type NodeProps = {
};

const Node: Component<NodeProps> = (props) => {
const [children, setChildren] = createSignal([]);
const [expanded, setExpanded] = createSignal(false);
const query = createQuery(() => ({
queryKey: ['paths', props.kv, props.path],
queryFn: () => fetchPaths({ mount: props.kv, path: props.path }),
enabled: expanded(),
}));

const chevron = () => (expanded() ? chevronDown : chevronRight);

const listPath = async () => {
setExpanded((v) => !v);
if (!expanded()) return;

const response: string[] = await invoke('list_path', {
mount: props.kv,
path: props.path,
});

if (!(response instanceof Array)) return;
response.sort();
setChildren(
response.map((subpath) => ({
kv: props.kv,
path: props.path + subpath,
icon: subpath.endsWith('/') ? folder : documentIcon,
})),
);
};

return (
<div>
<div>
<Show when={props.path.endsWith('/') || props.path === ''}>
<button class="inline-block" onClick={listPath}>
<button class="inline-block" onClick={() => setExpanded((v) => !v)}>
<Icon path={chevron()} class="inline h-[1em]" />
</button>
</Show>
Expand All @@ -55,9 +40,20 @@ const Node: Component<NodeProps> = (props) => {
<div class="pl-4">
<Show when={expanded()}>
<div>
<For each={children()}>
{(child) => <Node class="ml-10" {...child} />}
</For>
<Show when={query.isPending}>
<strong>loading...</strong>
</Show>
<Show when={query.isSuccess}>
<For
each={toSorted(query.data).map((subpath) => ({
kv: props.kv,
path: props.path + subpath,
icon: subpath.endsWith('/') ? folder : documentIcon,
}))}
>
{(node) => <Node {...node} />}
</For>
</Show>
</div>
</Show>
</div>
Expand Down
32 changes: 17 additions & 15 deletions src/SecretList.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { document as documentIcon, folder } from 'solid-heroicons/outline';
import {
createEffect,
createResource,
createSignal,
For,
Show,
type Component,
} from 'solid-js';
import { createEffect, createSignal, For, Show, type Component } from 'solid-js';
import Item from './Item';
import { fetchPaths } from './utils';
import { state } from './state';
import { createQuery } from '@tanstack/solid-query';
import { toSorted } from './utils';

const ListView: Component = () => {
const [secrets] = createResource(
() => ({ mount: state.kv, path: state.path }),
fetchPaths,
);
console.log(state.path);
const query = createQuery(() => ({
queryKey: ['paths', state.kv, state.path],
queryFn: () => fetchPaths({ mount: state.kv, path: state.path }),
enabled: !state.path || state.path.endsWith('/'),
}));

const [search, setSearch] = createSignal('');

Expand All @@ -35,9 +32,14 @@ const ListView: Component = () => {
onInput={(e) => setSearch(e.currentTarget.value)}
placeholder="Filter results..."
/>
{secrets.loading && <strong>Loading...</strong>}
<Show when={secrets()}>
<For each={secrets()}>
<Show when={query.isPending}>
<strong>loading...</strong>
</Show>
<Show when={query.isError}>
<strong>{query.error.toString()}</strong>
</Show>
<Show when={query.isSuccess}>
<For each={toSorted(query.data)}>
{(item) => (
<div>
<Show when={item.includes(search()) || search() === ''}>
Expand Down
21 changes: 14 additions & 7 deletions src/SecretView.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { writeText } from '@tauri-apps/api/clipboard';
import { createResource, For, Show, type Component } from 'solid-js';
import { For, Show, type Component } from 'solid-js';
import toast from 'solid-toast';
import { fetchSecret } from './utils';
import { state } from './state';
import { createQuery } from '@tanstack/solid-query';

const SecretView: Component = () => {
const [secrets] = createResource(
() => ({ mount: state.kv, path: state.path }),
fetchSecret,
);
const query = createQuery(() => ({
queryKey: ['paths', state.kv, state.path],
queryFn: () => fetchSecret({ mount: state.kv, path: state.path }),
}));

return (
<div>
Expand All @@ -25,8 +26,14 @@ const SecretView: Component = () => {
</tr>
</thead>
<tbody>
<Show when={secrets()} fallback={<strong>Loading...</strong>}>
<For each={Object.entries(secrets())}>
<Show when={query.isPending}>
<strong>loading...</strong>
</Show>
<Show when={query.isError}>
<strong>{query.error.toString()}</strong>
</Show>
<Show when={query.isSuccess}>
<For each={Object.entries(query.data)}>
{([key, value]) => (
<tr class="border-b bg-white dark:border-gray-700 dark:bg-gray-800">
<th
Expand Down
Loading

0 comments on commit 3616afe

Please sign in to comment.