aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/browser-extension/package.json7
-rw-r--r--packages/browser-extension/src/App.tsx11
-rw-r--r--packages/browser-extension/src/OptionsPage.tsx6
-rw-r--r--packages/browser-extension/src/SavePage.tsx83
-rw-r--r--packages/browser-extension/src/main.tsx5
-rw-r--r--packages/browser-extension/src/providers.tsx30
-rw-r--r--packages/browser-extension/src/utils/providers.tsx40
-rw-r--r--packages/browser-extension/src/utils/settings.ts (renamed from packages/browser-extension/src/settings.ts)0
-rw-r--r--packages/browser-extension/src/utils/trpc.ts4
-rw-r--r--packages/web/package.json1
-rw-r--r--pnpm-lock.yaml90
11 files changed, 224 insertions, 53 deletions
diff --git a/packages/browser-extension/package.json b/packages/browser-extension/package.json
index 297ba18e..b205a257 100644
--- a/packages/browser-extension/package.json
+++ b/packages/browser-extension/package.json
@@ -10,12 +10,19 @@
"preview": "vite preview"
},
"dependencies": {
+ "@hoarder/trpc": "0.1.0",
+ "@tanstack/react-query": "^5.24.8",
+ "@trpc/client": "11.0.0-next-beta.308",
+ "@trpc/next": "11.0.0-next-beta.308",
+ "@trpc/react-query": "11.0.0-next-beta.308",
+ "@trpc/server": "11.0.0-next-beta.308",
"@types/chrome": "^0.0.260",
"lucide-react": "^0.330.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"use-chrome-storage": "^1.2.2",
+ "superjson": "^2.2.1",
"zod": "^3.22.4"
},
"devDependencies": {
diff --git a/packages/browser-extension/src/App.tsx b/packages/browser-extension/src/App.tsx
index 1044363b..279c8b7a 100644
--- a/packages/browser-extension/src/App.tsx
+++ b/packages/browser-extension/src/App.tsx
@@ -1,6 +1,6 @@
-import { Settings, X } from "lucide-react";
+import { RefreshCw, Settings, X } from "lucide-react";
import SavePage from "./SavePage";
-import usePluginSettings from "./settings";
+import usePluginSettings from "./utils/settings";
import { useNavigate } from "react-router-dom";
function App() {
@@ -18,9 +18,14 @@ function App() {
return (
<div className="flex flex-col space-y-2">
- <SavePage settings={settings} />
+ <SavePage />
<hr />
<div className="flex justify-end space-x-3">
+ {process.env.NODE_ENV == "development" && (
+ <button onClick={() => navigate(0)}>
+ <RefreshCw className="w-4" />
+ </button>
+ )}
<button onClick={() => navigate("/options")}>
<Settings className="w-4" />
</button>
diff --git a/packages/browser-extension/src/OptionsPage.tsx b/packages/browser-extension/src/OptionsPage.tsx
index 11a1a76d..5cb4a45b 100644
--- a/packages/browser-extension/src/OptionsPage.tsx
+++ b/packages/browser-extension/src/OptionsPage.tsx
@@ -1,5 +1,5 @@
import { useRef, useState } from "react";
-import usePluginSettings from "./settings";
+import usePluginSettings from "./utils/settings";
export default function OptionsPage() {
const [settings, setSettings, _1, _2, _3] = usePluginSettings();
@@ -38,7 +38,7 @@ export default function OptionsPage() {
<label className="m-auto h-full">Server Address</label>
<input
ref={addressRef}
- defaultValue={settings.address || "https://demo.hoarder.app"}
+ value={settings.address || "https://demo.hoarder.app"}
className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
/>
</div>
@@ -46,7 +46,7 @@ export default function OptionsPage() {
<label className="m-auto h-full">API Key</label>
<input
ref={apiKeyRef}
- defaultValue={settings.apiKey}
+ value={settings.apiKey}
className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
/>
</div>
diff --git a/packages/browser-extension/src/SavePage.tsx b/packages/browser-extension/src/SavePage.tsx
index 955cc7cb..003d4025 100644
--- a/packages/browser-extension/src/SavePage.tsx
+++ b/packages/browser-extension/src/SavePage.tsx
@@ -1,13 +1,19 @@
import { useEffect, useState } from "react";
-import { Settings } from "./settings";
import Spinner from "./Spinner";
+import { api } from "./utils/trpc";
-export default function SavePage({ settings }: { settings: Settings }) {
- const [loading, setLoading] = useState(true);
+export default function SavePage() {
const [error, setError] = useState<string | undefined>(undefined);
+ const { mutate: createBookmark, status } =
+ api.bookmarks.createBookmark.useMutation({
+ onError: (e) => {
+ setError("Something went wrong: " + e.message);
+ },
+ });
+
useEffect(() => {
- async function runFetch() {
+ async function runSave() {
let currentUrl;
const [currentTab] = await chrome.tabs.query({
active: true,
@@ -17,52 +23,37 @@ export default function SavePage({ settings }: { settings: Settings }) {
currentUrl = currentTab.url;
} else {
setError("Couldn't find the URL of the current tab");
- setLoading(false);
return;
}
- try {
- const resp = await fetch(
- `${settings.address}/api/trpc/bookmarks.createBookmark`,
- {
- method: "POST",
- headers: {
- Authorization: `Bearer ${settings.apiKey}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- json: {
- type: "link",
- url: currentUrl,
- },
- }),
- },
- );
- if (!resp.ok) {
- setError(
- "Something went wrong: " + JSON.stringify(await resp.json()),
- );
- }
- } catch (e) {
- setError("Message: " + (e as Error).message);
- }
-
- setLoading(false);
+ createBookmark({
+ type: "link",
+ url: currentUrl,
+ });
}
- runFetch();
- }, [settings]);
-
- if (loading) {
- return (
- <div className="m-auto">
- <Spinner />
- </div>
- );
- }
+ runSave();
+ }, [createBookmark]);
- if (error) {
- return <div className="text-red-500">{error} ...</div>;
+ switch (status) {
+ case "error": {
+ return <div className="text-red-500">{error}</div>;
+ }
+ case "success": {
+ return <div className="m-auto text-lg">Bookmark Saved</div>;
+ }
+ case "pending": {
+ return (
+ <div className="m-auto">
+ <Spinner />
+ </div>
+ );
+ }
+ case "idle": {
+ return (
+ <div className="m-auto">
+ <Spinner />
+ </div>
+ );
+ }
}
-
- return <div className="m-auto text-lg">Bookmark Saved</div>;
}
diff --git a/packages/browser-extension/src/main.tsx b/packages/browser-extension/src/main.tsx
index c4f5a2d9..3e269982 100644
--- a/packages/browser-extension/src/main.tsx
+++ b/packages/browser-extension/src/main.tsx
@@ -5,6 +5,7 @@ import "./index.css";
import { createHashRouter, RouterProvider } from "react-router-dom";
import OptionsPage from "./OptionsPage.tsx";
import NotConfiguredPage from "./NotConfiguredPage.tsx";
+import { Providers } from "./utils/providers.tsx";
const router = createHashRouter([
{
@@ -24,7 +25,9 @@ const router = createHashRouter([
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<div className="w-96 p-4">
- <RouterProvider router={router} />
+ <Providers>
+ <RouterProvider router={router} />
+ </Providers>
</div>
</React.StrictMode>,
);
diff --git a/packages/browser-extension/src/providers.tsx b/packages/browser-extension/src/providers.tsx
new file mode 100644
index 00000000..a055f3d1
--- /dev/null
+++ b/packages/browser-extension/src/providers.tsx
@@ -0,0 +1,30 @@
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { httpBatchLink } from "@trpc/client";
+import React, { useState } from "react";
+import { trpc } from "./trpc";
+
+export function App() {
+ const [queryClient] = useState(() => new QueryClient());
+ const [trpcClient] = useState(() =>
+ trpc.createClient({
+ links: [
+ httpBatchLink({
+ url: "http://localhost:3000/trpc",
+ // You can pass any HTTP headers you wish here
+ async headers() {
+ return {
+ // authorization: getAuthCookie(),
+ };
+ },
+ }),
+ ],
+ }),
+ );
+ return (
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
+ <QueryClientProvider client={queryClient}>
+ {/* Your app here */}
+ </QueryClientProvider>
+ </trpc.Provider>
+ );
+}
diff --git a/packages/browser-extension/src/utils/providers.tsx b/packages/browser-extension/src/utils/providers.tsx
new file mode 100644
index 00000000..c11331f0
--- /dev/null
+++ b/packages/browser-extension/src/utils/providers.tsx
@@ -0,0 +1,40 @@
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { httpBatchLink } from "@trpc/client";
+import { useCallback, useEffect, useState } from "react";
+import { api } from "./trpc";
+import usePluginSettings from "./settings";
+import superjson from "superjson";
+
+export function Providers({ children }: { children: React.ReactNode }) {
+ const [settings] = usePluginSettings();
+ const [queryClient] = useState(() => new QueryClient());
+
+ const getTrpcClient = useCallback(() => {
+ console.log(settings);
+ return api.createClient({
+ links: [
+ httpBatchLink({
+ url: `${settings.address}/api/trpc`,
+ async headers() {
+ return {
+ Authorization: `Bearer ${settings.apiKey}`,
+ };
+ },
+ transformer: superjson,
+ }),
+ ],
+ });
+ }, [settings]);
+
+ const [trpcClient, setTrpcClient] = useState(getTrpcClient());
+
+ useEffect(() => {
+ setTrpcClient(getTrpcClient());
+ }, [getTrpcClient]);
+
+ return (
+ <api.Provider client={trpcClient} queryClient={queryClient}>
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
+ </api.Provider>
+ );
+}
diff --git a/packages/browser-extension/src/settings.ts b/packages/browser-extension/src/utils/settings.ts
index ee7f0722..ee7f0722 100644
--- a/packages/browser-extension/src/settings.ts
+++ b/packages/browser-extension/src/utils/settings.ts
diff --git a/packages/browser-extension/src/utils/trpc.ts b/packages/browser-extension/src/utils/trpc.ts
new file mode 100644
index 00000000..da21a55a
--- /dev/null
+++ b/packages/browser-extension/src/utils/trpc.ts
@@ -0,0 +1,4 @@
+import { createTRPCReact } from "@trpc/react-query";
+import type { AppRouter } from "@hoarder/trpc/routers/_app";
+
+export const api = createTRPCReact<AppRouter>();
diff --git a/packages/web/package.json b/packages/web/package.json
index e0c9d407..e8dfcbe1 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -36,6 +36,7 @@
"@trpc/next": "11.0.0-next-beta.304",
"@trpc/react-query": "^11.0.0-next-beta.304",
"@trpc/server": "11.0.0-next-beta.304",
+ "bcrypt": "^5.1.1",
"better-sqlite3": "^9.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dc333de5..caf3f970 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -69,6 +69,24 @@ importers:
packages/browser-extension:
dependencies:
+ '@hoarder/trpc':
+ specifier: 0.1.0
+ version: link:../trpc
+ '@tanstack/react-query':
+ specifier: ^5.24.8
+ version: 5.24.8(react@18.2.0)
+ '@trpc/client':
+ specifier: 11.0.0-next-beta.308
+ version: 11.0.0-next-beta.308(@trpc/server@11.0.0-next-beta.308)
+ '@trpc/next':
+ specifier: 11.0.0-next-beta.308
+ version: 11.0.0-next-beta.308(@tanstack/react-query@5.24.8)(@trpc/client@11.0.0-next-beta.308)(@trpc/react-query@11.0.0-next-beta.308)(@trpc/server@11.0.0-next-beta.308)(next@14.1.1)(react-dom@18.2.0)(react@18.2.0)
+ '@trpc/react-query':
+ specifier: 11.0.0-next-beta.308
+ version: 11.0.0-next-beta.308(@tanstack/react-query@5.24.8)(@trpc/client@11.0.0-next-beta.308)(@trpc/server@11.0.0-next-beta.308)(react-dom@18.2.0)(react@18.2.0)
+ '@trpc/server':
+ specifier: 11.0.0-next-beta.308
+ version: 11.0.0-next-beta.308
'@types/chrome':
specifier: ^0.0.260
version: 0.0.260
@@ -84,6 +102,9 @@ importers:
react-router-dom:
specifier: ^6.22.0
version: 6.22.1(react-dom@18.2.0)(react@18.2.0)
+ superjson:
+ specifier: ^2.2.1
+ version: 2.2.1
use-chrome-storage:
specifier: ^1.2.2
version: 1.3.0(react@18.2.0)
@@ -297,6 +318,9 @@ importers:
'@trpc/server':
specifier: 11.0.0-next-beta.304
version: 11.0.0-next-beta.304
+ bcrypt:
+ specifier: ^5.1.1
+ version: 5.1.1
better-sqlite3:
specifier: ^9.4.3
version: 9.4.3
@@ -3836,6 +3860,10 @@ packages:
resolution: {integrity: sha512-xYhxiMUPh1JzamVK8VwwkBpIBXVYRyIBW9gjSN+/BB4kL1nS86gnRWeW8L+sacCj1RiyEsysJe3GSvtbIpHdWw==}
dev: false
+ /@tanstack/query-core@5.24.8:
+ resolution: {integrity: sha512-yH7KnfXMf10p1U5GffTQzFi2Miiw6WJZImGYGdV7eqa5ZbKO8qVx9lOA9SfhIaJXomrMp1Yz5w/CBhVM3yWeTA==}
+ dev: false
+
/@tanstack/query-devtools@5.24.0:
resolution: {integrity: sha512-pThim455t69zrZaQKa7IRkEIK8UBTS+gHVAdNfhO72Xh4rWpMc63ovRje5/n6iw63+d6QiJzVadsJVdPoodSeQ==}
dev: false
@@ -3860,6 +3888,15 @@ packages:
react: 18.2.0
dev: false
+ /@tanstack/react-query@5.24.8(react@18.2.0):
+ resolution: {integrity: sha512-jB3JS9SzDmBySk9VVOTPt/0ixWEb3K3dy9IExlVl/1NouY3N7HzAqG/1d4m6E9eFfKJoLvA/hBksaLu0lw627A==}
+ peerDependencies:
+ react: ^18.0.0
+ dependencies:
+ '@tanstack/query-core': 5.24.8
+ react: 18.2.0
+ dev: false
+
/@tootallnate/quickjs-emscripten@0.23.0:
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
dev: false
@@ -3872,6 +3909,14 @@ packages:
'@trpc/server': 11.0.0-next-beta.304
dev: false
+ /@trpc/client@11.0.0-next-beta.308(@trpc/server@11.0.0-next-beta.308):
+ resolution: {integrity: sha512-bg8EV6qVZZl6/v9HhfmntEbPcjtzi3MFhdHUv9l24HLkLAJPvBCMMsjjFZG6PX+jwyXTFjSBGzaXwpnNtdE1tQ==}
+ peerDependencies:
+ '@trpc/server': 11.0.0-next-beta.308+955edd79a
+ dependencies:
+ '@trpc/server': 11.0.0-next-beta.308
+ dev: false
+
/@trpc/next@11.0.0-next-beta.304(@tanstack/react-query@5.24.6)(@trpc/client@11.0.0-next-beta.304)(@trpc/react-query@11.0.0-next-beta.304)(@trpc/server@11.0.0-next-beta.304)(next@14.1.1)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-bCCnkzqEpl6Z3R11fzPHxNxdgvoCZ2yDWxQZQlFPANSJVihjzLCMCK60AjXawDXdVUEqbA/OXP6htZeozjmWZg==}
peerDependencies:
@@ -3897,6 +3942,31 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@trpc/next@11.0.0-next-beta.308(@tanstack/react-query@5.24.8)(@trpc/client@11.0.0-next-beta.308)(@trpc/react-query@11.0.0-next-beta.308)(@trpc/server@11.0.0-next-beta.308)(next@14.1.1)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-zur2BkpI4NzKlg5P0RxGwk9yzYMuaKlXrS4vgwEsnr8CrVTqgClnStLsQOD14gwWRilp5QaJcFiPE2607OzQAg==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.0.0
+ '@trpc/client': 11.0.0-next-beta.308+955edd79a
+ '@trpc/react-query': 11.0.0-next-beta.308+955edd79a
+ '@trpc/server': 11.0.0-next-beta.308+955edd79a
+ next: '*'
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+ peerDependenciesMeta:
+ '@tanstack/react-query':
+ optional: true
+ '@trpc/react-query':
+ optional: true
+ dependencies:
+ '@tanstack/react-query': 5.24.8(react@18.2.0)
+ '@trpc/client': 11.0.0-next-beta.308(@trpc/server@11.0.0-next-beta.308)
+ '@trpc/react-query': 11.0.0-next-beta.308(@tanstack/react-query@5.24.8)(@trpc/client@11.0.0-next-beta.308)(@trpc/server@11.0.0-next-beta.308)(react-dom@18.2.0)(react@18.2.0)
+ '@trpc/server': 11.0.0-next-beta.308
+ next: 14.1.1(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@trpc/react-query@11.0.0-next-beta.304(@tanstack/react-query@5.24.6)(@trpc/client@11.0.0-next-beta.304)(@trpc/server@11.0.0-next-beta.304)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-DkfNUVxxEgKtel5Z9DUaw815oy8VGK7i626FrUs7PRQ7PEcQ5WDBXbYXsukOqx+qEpx09dgiWBBG6LGQf6U9Dg==}
peerDependencies:
@@ -3913,10 +3983,30 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
+ /@trpc/react-query@11.0.0-next-beta.308(@tanstack/react-query@5.24.8)(@trpc/client@11.0.0-next-beta.308)(@trpc/server@11.0.0-next-beta.308)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-+0g42nW0zOXfpRN90aMuhPZ/BvwQu4IOiWP5xByRq2E+EWrWxJAFdxgS4xpKR49KlM+vKLSgkqj5yeYXyd82hw==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.0.0
+ '@trpc/client': 11.0.0-next-beta.308+955edd79a
+ '@trpc/server': 11.0.0-next-beta.308+955edd79a
+ react: '>=18.2.0'
+ react-dom: '>=18.2.0'
+ dependencies:
+ '@tanstack/react-query': 5.24.8(react@18.2.0)
+ '@trpc/client': 11.0.0-next-beta.308(@trpc/server@11.0.0-next-beta.308)
+ '@trpc/server': 11.0.0-next-beta.308
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@trpc/server@11.0.0-next-beta.304:
resolution: {integrity: sha512-vviyE80LZ8LFML/w0usDjcUbduhsBtLBO+MKXhAtRfo25FxajhDFWvuvdqglAlTxFmCuH7oX+GxfCTjcsnnHyQ==}
dev: false
+ /@trpc/server@11.0.0-next-beta.308:
+ resolution: {integrity: sha512-GdYgcbecAafHQszqMVeHrX45c0hhAISvB+w9Ja40nZcb4kgaNvhflSVIn8XbHKUG8urmYI9kTL2k8hD/59/LMA==}
+ dev: false
+
/@tsconfig/node10@1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}