diff options
57 files changed, 255 insertions, 192 deletions
diff --git a/.husky/pre-commit b/.husky/pre-commit index 09be6810..1c6782b0 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1,3 @@ pnpm typecheck -pnpm format +pnpm format --check pnpm lint diff --git a/apps/browser-extension/package.json b/apps/browser-extension/package.json index cc5068b7..35c899bc 100644 --- a/apps/browser-extension/package.json +++ b/apps/browser-extension/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", + "format": "prettier .", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "typecheck": "tsc --noEmit" diff --git a/apps/browser-extension/src/BookmarkSavedPage.tsx b/apps/browser-extension/src/BookmarkSavedPage.tsx index 5ff2cd39..54f62796 100644 --- a/apps/browser-extension/src/BookmarkSavedPage.tsx +++ b/apps/browser-extension/src/BookmarkSavedPage.tsx @@ -1,9 +1,10 @@ -import { Link, useNavigate, useParams } from "react-router-dom"; -import { api } from "./utils/trpc"; -import usePluginSettings from "./utils/settings"; +import { useState } from "react"; import { ArrowUpRightFromSquare, Trash } from "lucide-react"; +import { Link, useNavigate, useParams } from "react-router-dom"; + import Spinner from "./Spinner"; -import { useState } from "react"; +import usePluginSettings from "./utils/settings"; +import { api } from "./utils/trpc"; export default function BookmarkSavedPage() { const { bookmarkId } = useParams(); diff --git a/apps/browser-extension/src/Layout.tsx b/apps/browser-extension/src/Layout.tsx index 3eb85abd..bf760362 100644 --- a/apps/browser-extension/src/Layout.tsx +++ b/apps/browser-extension/src/Layout.tsx @@ -1,6 +1,6 @@ -import { Outlet } from "react-router-dom"; import { Home, RefreshCw, Settings, X } from "lucide-react"; -import { useNavigate } from "react-router-dom"; +import { Outlet, useNavigate } from "react-router-dom"; + import usePluginSettings from "./utils/settings"; export default function Layout() { diff --git a/apps/browser-extension/src/NotConfiguredPage.tsx b/apps/browser-extension/src/NotConfiguredPage.tsx index cad87303..298e9f5e 100644 --- a/apps/browser-extension/src/NotConfiguredPage.tsx +++ b/apps/browser-extension/src/NotConfiguredPage.tsx @@ -1,7 +1,8 @@ import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; -import usePluginSettings from "./utils/settings"; + import Logo from "./Logo"; +import usePluginSettings from "./utils/settings"; export default function NotConfiguredPage() { const navigate = useNavigate(); diff --git a/apps/browser-extension/src/OptionsPage.tsx b/apps/browser-extension/src/OptionsPage.tsx index 6407b3cc..9670558e 100644 --- a/apps/browser-extension/src/OptionsPage.tsx +++ b/apps/browser-extension/src/OptionsPage.tsx @@ -1,9 +1,10 @@ import React, { useEffect } from "react"; -import usePluginSettings from "./utils/settings"; -import { api } from "./utils/trpc"; -import Spinner from "./Spinner"; import { useNavigate } from "react-router-dom"; + import Logo from "./Logo"; +import Spinner from "./Spinner"; +import usePluginSettings from "./utils/settings"; +import { api } from "./utils/trpc"; export default function OptionsPage() { const navigate = useNavigate(); diff --git a/apps/browser-extension/src/SavePage.tsx b/apps/browser-extension/src/SavePage.tsx index 638af149..9cc1521a 100644 --- a/apps/browser-extension/src/SavePage.tsx +++ b/apps/browser-extension/src/SavePage.tsx @@ -1,7 +1,8 @@ import { useEffect, useState } from "react"; +import { Navigate } from "react-router-dom"; + import Spinner from "./Spinner"; import { api } from "./utils/trpc"; -import { Navigate } from "react-router-dom"; export default function SavePage() { const [error, setError] = useState<string | undefined>(undefined); diff --git a/apps/browser-extension/src/SignInPage.tsx b/apps/browser-extension/src/SignInPage.tsx index 5c49965c..a9b77e83 100644 --- a/apps/browser-extension/src/SignInPage.tsx +++ b/apps/browser-extension/src/SignInPage.tsx @@ -1,8 +1,9 @@ import { useState } from "react"; -import { api } from "./utils/trpc"; -import usePluginSettings from "./utils/settings"; import { useNavigate } from "react-router-dom"; + import Logo from "./Logo"; +import usePluginSettings from "./utils/settings"; +import { api } from "./utils/trpc"; export default function SignInPage() { const navigate = useNavigate(); diff --git a/apps/browser-extension/src/main.tsx b/apps/browser-extension/src/main.tsx index 085a5a69..65456012 100644 --- a/apps/browser-extension/src/main.tsx +++ b/apps/browser-extension/src/main.tsx @@ -1,14 +1,17 @@ import ReactDOM from "react-dom/client"; + import "./index.css"; -import OptionsPage from "./OptionsPage.tsx"; -import NotConfiguredPage from "./NotConfiguredPage.tsx"; -import { Providers } from "./utils/providers.tsx"; + +import { HashRouter, Route, Routes } from "react-router-dom"; + +import BookmarkDeletedPage from "./BookmarkDeletedPage.tsx"; import BookmarkSavedPage from "./BookmarkSavedPage.tsx"; -import { HashRouter, Routes, Route } from "react-router-dom"; import Layout from "./Layout.tsx"; +import NotConfiguredPage from "./NotConfiguredPage.tsx"; +import OptionsPage from "./OptionsPage.tsx"; import SavePage from "./SavePage.tsx"; -import BookmarkDeletedPage from "./BookmarkDeletedPage.tsx"; import SignInPage from "./SignInPage.tsx"; +import { Providers } from "./utils/providers.tsx"; function App() { return ( diff --git a/apps/browser-extension/src/utils/providers.tsx b/apps/browser-extension/src/utils/providers.tsx index d20f2512..7b14b22c 100644 --- a/apps/browser-extension/src/utils/providers.tsx +++ b/apps/browser-extension/src/utils/providers.tsx @@ -1,10 +1,11 @@ +import { useEffect, useState } from "react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { httpBatchLink } from "@trpc/client"; -import { useEffect, useState } from "react"; -import { api } from "./trpc"; -import usePluginSettings, { getPluginSettings } from "./settings"; import superjson from "superjson"; +import usePluginSettings, { getPluginSettings } from "./settings"; +import { api } from "./trpc"; + function getTRPCClient(address: string) { return api.createClient({ links: [ diff --git a/apps/browser-extension/src/utils/trpc.ts b/apps/browser-extension/src/utils/trpc.ts index da21a55a..9b025df1 100644 --- a/apps/browser-extension/src/utils/trpc.ts +++ b/apps/browser-extension/src/utils/trpc.ts @@ -1,4 +1,5 @@ import { createTRPCReact } from "@trpc/react-query"; + import type { AppRouter } from "@hoarder/trpc/routers/_app"; export const api = createTRPCReact<AppRouter>(); diff --git a/apps/browser-extension/vite.config.ts b/apps/browser-extension/vite.config.ts index 29c6bc6e..42ecc28d 100644 --- a/apps/browser-extension/vite.config.ts +++ b/apps/browser-extension/vite.config.ts @@ -1,6 +1,7 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react-swc"; import { crx } from "@crxjs/vite-plugin"; +import react from "@vitejs/plugin-react-swc"; +import { defineConfig } from "vite"; + import manifest from "./manifest.json"; // https://vitejs.dev/config/ diff --git a/apps/mobile/app.json b/apps/mobile/app.json index 028286e4..fec59de5 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -39,10 +39,7 @@ "NSExtensionActivationSupportsMovieWithMaxCount": 0, "NSExtensionActivationSupportsText": true }, - "androidIntentFilters": [ - "text/*", - "image/*" - ] + "androidIntentFilters": ["text/*", "image/*"] } ], "expo-secure-store", diff --git a/apps/mobile/app/dashboard/(tabs)/_layout.tsx b/apps/mobile/app/dashboard/(tabs)/_layout.tsx index fe40215e..7967b5c6 100644 --- a/apps/mobile/app/dashboard/(tabs)/_layout.tsx +++ b/apps/mobile/app/dashboard/(tabs)/_layout.tsx @@ -1,8 +1,8 @@ import React, { useEffect } from "react"; +import { Platform } from "react-native"; +import * as NavigationBar from "expo-navigation-bar"; import { Tabs } from "expo-router"; import { ClipboardList, Home, Search, Settings } from "lucide-react-native"; -import { Platform } from "react-native"; -import * as NavigationBar from 'expo-navigation-bar'; export default function TabLayout() { useEffect(() => { diff --git a/apps/mobile/app/dashboard/(tabs)/index.tsx b/apps/mobile/app/dashboard/(tabs)/index.tsx index 804eb0b5..5dccc845 100644 --- a/apps/mobile/app/dashboard/(tabs)/index.tsx +++ b/apps/mobile/app/dashboard/(tabs)/index.tsx @@ -3,21 +3,21 @@ import * as Haptics from "expo-haptics"; import * as ImagePicker from "expo-image-picker"; import { useRouter } from "expo-router"; import UpdatingBookmarkList from "@/components/bookmarks/UpdatingBookmarkList"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import PageTitle from "@/components/ui/PageTitle"; +import { useToast } from "@/components/ui/Toast"; import useAppSettings from "@/lib/settings"; import { useUploadAsset } from "@/lib/upload"; import { MenuView } from "@react-native-menu/menu"; import { SquarePen } from "lucide-react-native"; -import { useToast } from "@/components/ui/Toast"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; function HeaderRight() { - const {toast} = useToast(); + const { toast } = useToast(); const router = useRouter(); const { settings } = useAppSettings(); const { uploadAsset } = useUploadAsset(settings, { onError: (e) => { - toast({message: e, variant: "destructive"}); + toast({ message: e, variant: "destructive" }); }, }); return ( @@ -69,7 +69,10 @@ function HeaderRight() { shouldOpenOnLongPress={false} > <View className="my-auto px-4"> - <SquarePen color="rgb(0, 122, 255)" onPress={() => Haptics.selectionAsync()} /> + <SquarePen + color="rgb(0, 122, 255)" + onPress={() => Haptics.selectionAsync()} + /> </View> </MenuView> ); diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx index 0350ebd2..767b9256 100644 --- a/apps/mobile/app/dashboard/(tabs)/lists.tsx +++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from "react"; import { FlatList, Pressable, Text, View } from "react-native"; import { Link } from "expo-router"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; +import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; import { ChevronRight } from "lucide-react-native"; -import PageTitle from "@/components/ui/PageTitle"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; export default function Lists() { const [refreshing, setRefreshing] = useState(false); @@ -51,9 +51,7 @@ export default function Lists() { return ( <CustomSafeAreaView> <FlatList - ListHeaderComponent={ - <PageTitle title="Lists" /> - } + ListHeaderComponent={<PageTitle title="Lists" />} contentContainerStyle={{ gap: 5, }} diff --git a/apps/mobile/app/dashboard/(tabs)/search.tsx b/apps/mobile/app/dashboard/(tabs)/search.tsx index bcaee5af..0a4dcbfd 100644 --- a/apps/mobile/app/dashboard/(tabs)/search.tsx +++ b/apps/mobile/app/dashboard/(tabs)/search.tsx @@ -1,13 +1,13 @@ import { useState } from "react"; import { View } from "react-native"; import BookmarkList from "@/components/bookmarks/BookmarkList"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; import { Input } from "@/components/ui/Input"; import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; import { keepPreviousData } from "@tanstack/react-query"; import { useDebounce } from "use-debounce"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; export default function Search() { const [search, setSearch] = useState(""); diff --git a/apps/mobile/app/dashboard/(tabs)/settings.tsx b/apps/mobile/app/dashboard/(tabs)/settings.tsx index 0dbf7da6..c2db2846 100644 --- a/apps/mobile/app/dashboard/(tabs)/settings.tsx +++ b/apps/mobile/app/dashboard/(tabs)/settings.tsx @@ -1,9 +1,9 @@ import { Text, View } from "react-native"; import { Button } from "@/components/ui/Button"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import PageTitle from "@/components/ui/PageTitle"; import { useSession } from "@/lib/session"; import { api } from "@/lib/trpc"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; export default function Dashboard() { const { logout } = useSession(); diff --git a/apps/mobile/app/dashboard/archive.tsx b/apps/mobile/app/dashboard/archive.tsx index e622a3e4..2fe5d274 100644 --- a/apps/mobile/app/dashboard/archive.tsx +++ b/apps/mobile/app/dashboard/archive.tsx @@ -1,11 +1,14 @@ import UpdatingBookmarkList from "@/components/bookmarks/UpdatingBookmarkList"; -import PageTitle from "@/components/ui/PageTitle"; import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; +import PageTitle from "@/components/ui/PageTitle"; export default function Archive() { return ( <CustomSafeAreaView> - <UpdatingBookmarkList query={{archived: true}} header={<PageTitle title="🗄️ Archive" />} /> + <UpdatingBookmarkList + query={{ archived: true }} + header={<PageTitle title="🗄️ Archive" />} + /> </CustomSafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/favourites.tsx b/apps/mobile/app/dashboard/favourites.tsx index 213cc918..abda5cfa 100644 --- a/apps/mobile/app/dashboard/favourites.tsx +++ b/apps/mobile/app/dashboard/favourites.tsx @@ -1,6 +1,6 @@ import UpdatingBookmarkList from "@/components/bookmarks/UpdatingBookmarkList"; -import PageTitle from "@/components/ui/PageTitle"; import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; +import PageTitle from "@/components/ui/PageTitle"; export default function Favourites() { return ( diff --git a/apps/mobile/app/dashboard/lists/[slug].tsx b/apps/mobile/app/dashboard/lists/[slug].tsx index c0b86a0f..d42cc653 100644 --- a/apps/mobile/app/dashboard/lists/[slug].tsx +++ b/apps/mobile/app/dashboard/lists/[slug].tsx @@ -1,10 +1,10 @@ import { View } from "react-native"; import { Stack, useLocalSearchParams } from "expo-router"; import UpdatingBookmarkList from "@/components/bookmarks/UpdatingBookmarkList"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; export default function ListView() { const { slug } = useLocalSearchParams(); diff --git a/apps/mobile/app/dashboard/tags/[slug].tsx b/apps/mobile/app/dashboard/tags/[slug].tsx index 26aa47ec..ea1ef63d 100644 --- a/apps/mobile/app/dashboard/tags/[slug].tsx +++ b/apps/mobile/app/dashboard/tags/[slug].tsx @@ -1,10 +1,10 @@ import { View } from "react-native"; import { Stack, useLocalSearchParams } from "expo-router"; import UpdatingBookmarkList from "@/components/bookmarks/UpdatingBookmarkList"; +import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; -import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; export default function TagView() { const { slug } = useLocalSearchParams(); diff --git a/apps/mobile/app/index.tsx b/apps/mobile/app/index.tsx index 235b19e4..dbbea97e 100644 --- a/apps/mobile/app/index.tsx +++ b/apps/mobile/app/index.tsx @@ -1,16 +1,16 @@ -import { useIsLoggedIn } from "@/lib/session"; import { Redirect } from "expo-router"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; +import { useIsLoggedIn } from "@/lib/session"; export default function App() { const isLoggedIn = useIsLoggedIn(); - if (isLoggedIn === undefined) { - // Wait until it's loaded - return <FullPageSpinner />; - } else if (isLoggedIn) { - return <Redirect href="dashboard" /> - } else { - return <Redirect href="signin" /> - } + if (isLoggedIn === undefined) { + // Wait until it's loaded + return <FullPageSpinner />; + } else if (isLoggedIn) { + return <Redirect href="dashboard" />; + } else { + return <Redirect href="signin" />; + } } diff --git a/apps/mobile/app/signin.tsx b/apps/mobile/app/signin.tsx index 2255424e..8402bd43 100644 --- a/apps/mobile/app/signin.tsx +++ b/apps/mobile/app/signin.tsx @@ -69,9 +69,7 @@ export default function Signin() { value={settings.address} autoCapitalize="none" keyboardType="url" - onChangeText={(e) => - setSettings({ ...settings, address: e }) - } + onChangeText={(e) => setSettings({ ...settings, address: e })} /> </View> <View className="gap-2"> diff --git a/apps/mobile/components/Logo.tsx b/apps/mobile/components/Logo.tsx index 9fdd1083..ba949ed4 100644 --- a/apps/mobile/components/Logo.tsx +++ b/apps/mobile/components/Logo.tsx @@ -1,11 +1,9 @@ -import * as React from "react" -import type { SvgProps} from "react-native-svg"; -import Svg, { Path } from "react-native-svg" +import type { SvgProps } from "react-native-svg"; +import * as React from "react"; +import Svg, { Path } from "react-native-svg"; + const Logo = (props: SvgProps) => ( - <Svg - viewBox="0 0 507 96" - {...props} - > + <Svg viewBox="0 0 507 96" {...props}> <Path d="M341.09 287.81c-.72-2.79-1.89-5.27-3.51-7.42s-3.74-3.9-6.34-5.26-6.5-2.32-10.33-2.04c-14.17 1.03-14.91 13.45-16.19 15.72l-.23-7v-24.46h-19.44v73.7h19.44v-22.5c0-3.4.89-7.2 2.63-9.5 1.73-2.3 4.2-2.5 7.45-2.5 1.66 0 3.01.32 4.07.96s1.91 1.51 2.55 2.6c.64 1.1 1.07 2.36 1.3 3.8.23 1.43.34 2.94.34 4.52v22.62h19.33v-34.87c0-2.79-.36-5.58-1.07-8.37m68.79 1.58c-1.66-3.69-3.92-6.83-6.79-9.39-2.87-2.57-6.19-4.53-9.96-5.89-3.78-1.36-7.81-2.04-12.11-2.04s-8.25.68-12.06 2.04-7.13 3.32-9.96 5.89c-2.83 2.56-5.07 5.7-6.73 9.39q-2.49 5.55-2.49 12.45c0 4.6.83 8.78 2.49 12.51 1.66 3.74 3.9 6.91 6.73 9.51s6.15 4.62 9.96 6.05q5.715 2.16 12.06 2.16c4.23 0 8.33-.72 12.11-2.16 3.77-1.43 7.09-3.45 9.96-6.05s5.13-5.77 6.79-9.51q2.49-5.595 2.49-12.51c0-4.61-.83-8.75-2.49-12.45m-16.24 17.77c-.57 1.74-1.42 3.31-2.55 4.7-1.13 1.4-2.53 2.51-4.19 3.34s-3.58 1.24-5.77 1.24-4.11-.41-5.77-1.24-3.06-1.94-4.19-3.34a14.6 14.6 0 0 1-2.55-4.7c-.56-1.73-.85-3.51-.85-5.32s.29-3.58.85-5.32c.57-1.73 1.4-3.26 2.49-4.58 1.1-1.32 2.47-2.4 4.13-3.23s3.59-1.24 5.78-1.24 4.11.41 5.77 1.24 3.06 1.91 4.19 3.23 2 2.85 2.6 4.58c.6 1.74.91 3.51.91 5.32s-.29 3.59-.85 5.32m73.12-18.62c-.95-3.73-2.44-6.83-4.47-9.28q-3.06-3.675-7.98-5.43c-3.29-1.17-7.3-1.76-12.06-1.76s-9.11.8-13.52 2.38c-4.42 1.59-8.29 3.96-11.61 7.13l9.4 10.08c1.73-1.59 3.83-2.95 6.28-4.08s5-1.7 7.64-1.7c2.87 0 5.28.66 7.25 1.98 1.96 1.33 2.94 3.38 2.94 6.17v.91c-4.08 0-8.26.22-12.57.68-4.3.45-8.2 1.36-11.71 2.71-3.51 1.36-6.38 3.29-8.6 5.78-2.23 2.49-3.34 5.77-3.34 9.84 0 3.33.64 6.12 1.92 8.38s2.93 4.08 4.93 5.43c1.99 1.36 4.2 2.34 6.62 2.95 2.41.6 4.75.9 7.01.9 3.4 0 5.93-.34 8.66-1.97 4.32-2.57 7.31-13.68 7.31-13.68l.33 8.28v6h16.98v-28.41c0-5.13-.47-9.56-1.41-13.3zm-15.57 19.08c0 3.54-1 6.35-2.99 8.43-2.01 2.07-4.89 3.11-8.66 3.11-.91 0-1.85-.09-2.83-.28-.99-.19-1.85-.51-2.61-.96a5.9 5.9 0 0 1-1.87-1.81c-.49-.76-.73-1.66-.73-2.72 0-1.66.53-3 1.58-4.02 1.06-1.02 2.4-1.79 4.02-2.32q2.43-.795 5.55-1.08c2.07-.18 4.13-.28 6.17-.28h2.37zm60.17-35.21c-.72-.07-1.46-.11-2.21-.11-3.47 0-6.53.91-9.17 2.74-2.64 1.82-4.68 10.18-6.11 13.06h-.23v-14.15h-17.88v56.14l18.56.22v-28.95c0-1.13.23-2.45.68-3.95.45-1.51 1.19-2.9 2.21-4.18s2.37-2.37 4.07-3.28c1.7-.9 3.79-1.35 6.28-1.35.76 0 1.53.04 2.32.11.67.07 1.36.18 2.05.36.13.03.26.06.39.1l.06-1.16.73-15.26c-.45-.15-1.04-.26-1.75-.34" transform="translate(-173 -247)" @@ -15,6 +13,5 @@ const Logo = (props: SvgProps) => ( transform="translate(-173 -247)" /> </Svg> -) -export default Logo - +); +export default Logo; diff --git a/apps/mobile/components/bookmarks/BookmarkList.tsx b/apps/mobile/components/bookmarks/BookmarkList.tsx index 9176f66d..7477992d 100644 --- a/apps/mobile/components/bookmarks/BookmarkList.tsx +++ b/apps/mobile/components/bookmarks/BookmarkList.tsx @@ -16,11 +16,11 @@ export default function BookmarkList({ isRefreshing, }: { bookmarks: ZBookmark[]; - onRefresh: () => void, - isRefreshing: boolean, - fetchNextPage?: () => void, + onRefresh: () => void; + isRefreshing: boolean; + fetchNextPage?: () => void; header?: React.ReactElement; - isFetchingNextPage?: boolean, + isFetchingNextPage?: boolean; }) { const flatListRef = useRef(null); useScrollToTop(flatListRef); diff --git a/apps/mobile/components/ui/PageTitle.tsx b/apps/mobile/components/ui/PageTitle.tsx index 1d1a8400..57b19e7d 100644 --- a/apps/mobile/components/ui/PageTitle.tsx +++ b/apps/mobile/components/ui/PageTitle.tsx @@ -1,4 +1,4 @@ -import {Text} from "react-native"; +import { Text } from "react-native"; export default function PageTitle({ title }: { title: string }) { return <Text className="p-4 text-4xl font-bold">{title}</Text>; diff --git a/apps/mobile/index.ts b/apps/mobile/index.ts index 5b834183..80d3d998 100644 --- a/apps/mobile/index.ts +++ b/apps/mobile/index.ts @@ -1 +1 @@ -import 'expo-router/entry'; +import "expo-router/entry"; diff --git a/apps/mobile/lib/upload.ts b/apps/mobile/lib/upload.ts index d511becc..56b2c7a5 100644 --- a/apps/mobile/lib/upload.ts +++ b/apps/mobile/lib/upload.ts @@ -1,38 +1,40 @@ import { useMutation } from "@tanstack/react-query"; +import type { ZBookmark } from "@hoarder/trpc/types/bookmarks"; +import { + zUploadErrorSchema, + zUploadResponseSchema, +} from "@hoarder/trpc/types/uploads"; + import type { Settings } from "./settings"; import { api } from "./trpc"; -import type { ZBookmark } from "@hoarder/trpc/types/bookmarks"; -import { zUploadResponseSchema, zUploadErrorSchema } from "@hoarder/trpc/types/uploads"; export function useUploadAsset( settings: Settings, - options: { onSuccess?: (bookmark: ZBookmark) => void; onError?: (e: string) => void }, + options: { + onSuccess?: (bookmark: ZBookmark) => void; + onError?: (e: string) => void; + }, ) { const invalidateAllBookmarks = api.useUtils().bookmarks.getBookmarks.invalidate; - const { - mutate: createBookmark, - isPending: isCreatingBookmark, - } = api.bookmarks.createBookmark.useMutation({ - onSuccess: (d) => { - invalidateAllBookmarks(); - if (options.onSuccess) { - options.onSuccess(d); - } - }, - onError: (e) => { - if (options.onError) { - options.onError(e.message); - } - }, - }); + const { mutate: createBookmark, isPending: isCreatingBookmark } = + api.bookmarks.createBookmark.useMutation({ + onSuccess: (d) => { + invalidateAllBookmarks(); + if (options.onSuccess) { + options.onSuccess(d); + } + }, + onError: (e) => { + if (options.onError) { + options.onError(e.message); + } + }, + }); - const { - mutate: uploadAsset, - isPending: isUploading, - } = useMutation({ + const { mutate: uploadAsset, isPending: isUploading } = useMutation({ mutationFn: async (file: { type: string; name: string; uri: string }) => { const formData = new FormData(); // @ts-expect-error This is a valid api in react native diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 15b2057b..04fd8821 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -8,6 +8,7 @@ "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", + "format": "prettier .", "lint": "eslint .", "typecheck": "tsc --noEmit" }, diff --git a/apps/mobile/tailwind.config.ts b/apps/mobile/tailwind.config.ts index 9eb1eb4a..8d6f3785 100644 --- a/apps/mobile/tailwind.config.ts +++ b/apps/mobile/tailwind.config.ts @@ -1,4 +1,5 @@ import type { Config } from "tailwindcss"; + import base from "@hoarder/tailwind-config/native"; const config = { diff --git a/apps/workers/crawlerWorker.ts b/apps/workers/crawlerWorker.ts index 3f7bff94..d1ebbdaa 100644 --- a/apps/workers/crawlerWorker.ts +++ b/apps/workers/crawlerWorker.ts @@ -1,8 +1,10 @@ import assert from "assert"; import * as dns from "dns"; +import type { Job } from "bullmq"; +import type { Browser } from "puppeteer"; import { Readability } from "@mozilla/readability"; import { Mutex } from "async-mutex"; -import { Job, Worker } from "bullmq"; +import { Worker } from "bullmq"; import DOMPurify from "dompurify"; import { eq } from "drizzle-orm"; import { isShuttingDown } from "exit"; @@ -15,11 +17,11 @@ import metascraperReadability from "metascraper-readability"; import metascraperTitle from "metascraper-title"; import metascraperTwitter from "metascraper-twitter"; import metascraperUrl from "metascraper-url"; -import { Browser } from "puppeteer"; import puppeteer from "puppeteer-extra"; import AdblockerPlugin from "puppeteer-extra-plugin-adblocker"; import StealthPlugin from "puppeteer-extra-plugin-stealth"; +import type { ZCrawlLinkRequest } from "@hoarder/shared/queues"; import { db } from "@hoarder/db"; import { bookmarkLinks } from "@hoarder/db/schema"; import serverConfig from "@hoarder/shared/config"; @@ -29,7 +31,6 @@ import { OpenAIQueue, queueConnectionDetails, SearchIndexingQueue, - ZCrawlLinkRequest, zCrawlLinkRequestSchema, } from "@hoarder/shared/queues"; @@ -83,7 +84,7 @@ async function launchBrowser() { }, 5000); return; } - browser.on("disconnected", async (): Promise<void> => { + browser.on("disconnected", () => { if (isShuttingDown) { logger.info( "The puppeteer browser got disconnected. But we're shutting down so won't restart it.", @@ -93,7 +94,7 @@ async function launchBrowser() { logger.info( "The puppeteer browser got disconnected. Will attempt to launch it again.", ); - await launchBrowser(); + launchBrowser(); }); }); } diff --git a/apps/workers/exit.ts b/apps/workers/exit.ts index 156cf2c6..29bfa5ef 100644 --- a/apps/workers/exit.ts +++ b/apps/workers/exit.ts @@ -3,7 +3,7 @@ import logger from "@hoarder/shared/logger"; export let isShuttingDown = false; export const shutdownPromise = new Promise((resolve) => { - process.on('SIGTERM', () => { + process.on("SIGTERM", () => { logger.info("Received SIGTERM, shutting down ..."); isShuttingDown = true; resolve(""); diff --git a/apps/workers/index.ts b/apps/workers/index.ts index 4db524ef..24bdc67b 100644 --- a/apps/workers/index.ts +++ b/apps/workers/index.ts @@ -1,14 +1,15 @@ import "dotenv/config"; + import { CrawlerWorker } from "./crawlerWorker"; +import { shutdownPromise } from "./exit"; import { OpenAiWorker } from "./openaiWorker"; import { SearchIndexingWorker } from "./searchWorker"; -import { shutdownPromise } from "./exit"; async function main() { const [crawler, openai, search] = [ await CrawlerWorker.build(), - await OpenAiWorker.build(), - await SearchIndexingWorker.build(), + OpenAiWorker.build(), + SearchIndexingWorker.build(), ]; await Promise.any([ diff --git a/apps/workers/inference.ts b/apps/workers/inference.ts index 3b0b5943..13b10aba 100644 --- a/apps/workers/inference.ts +++ b/apps/workers/inference.ts @@ -124,7 +124,9 @@ class OllamaInferenceClient implements InferenceClient { // Using stream + accumulating the response so far is a workaround. // https://github.com/ollama/ollama-js/issues/72 totalTokens = NaN; - logger.warn(`Got an exception from ollama, will still attempt to deserialize the response we got so far: ${e}`) + logger.warn( + `Got an exception from ollama, will still attempt to deserialize the response we got so far: ${e}`, + ); } return { response, totalTokens }; @@ -139,6 +141,10 @@ class OllamaInferenceClient implements InferenceClient { _contentType: string, image: string, ): Promise<InferenceResponse> { - return await this.runModel(serverConfig.inference.imageModel, prompt, image); + return await this.runModel( + serverConfig.inference.imageModel, + prompt, + image, + ); } } diff --git a/apps/workers/openaiWorker.ts b/apps/workers/openaiWorker.ts index ee48d148..bb8015a5 100644 --- a/apps/workers/openaiWorker.ts +++ b/apps/workers/openaiWorker.ts @@ -1,7 +1,9 @@ -import { Job, Worker } from "bullmq"; +import type { Job } from "bullmq"; +import { Worker } from "bullmq"; import { and, eq, inArray } from "drizzle-orm"; import { z } from "zod"; +import type { ZOpenAIRequest } from "@hoarder/shared/queues"; import { db } from "@hoarder/db"; import { bookmarks, bookmarkTags, tagsOnBookmarks } from "@hoarder/db/schema"; import { readAsset } from "@hoarder/shared/assetdb"; @@ -10,11 +12,11 @@ import { OpenAIQueue, queueConnectionDetails, SearchIndexingQueue, - ZOpenAIRequest, zOpenAIRequestSchema, } from "@hoarder/shared/queues"; -import { InferenceClient, InferenceClientFactory } from "./inference"; +import type { InferenceClient } from "./inference"; +import { InferenceClientFactory } from "./inference"; const openAIResponseSchema = z.object({ tags: z.array(z.string()), @@ -41,7 +43,7 @@ async function attemptMarkTaggingStatus( } export class OpenAiWorker { - static async build() { + static build() { logger.info("Starting inference worker ..."); const worker = new Worker<ZOpenAIRequest, void>( OpenAIQueue.name, @@ -52,16 +54,16 @@ export class OpenAiWorker { }, ); - worker.on("completed", async (job): Promise<void> => { + worker.on("completed", (job) => { const jobId = job?.id ?? "unknown"; logger.info(`[inference][${jobId}] Completed successfully`); - await attemptMarkTaggingStatus(job?.data, "success"); + attemptMarkTaggingStatus(job?.data, "success"); }); - worker.on("failed", async (job, error): Promise<void> => { + worker.on("failed", (job, error) => { const jobId = job?.id ?? "unknown"; logger.error(`[inference][${jobId}] inference job failed: ${error}`); - await attemptMarkTaggingStatus(job?.data, "failure"); + attemptMarkTaggingStatus(job?.data, "failure"); }); return worker; @@ -90,11 +92,11 @@ function buildPrompt( bookmark: NonNullable<Awaited<ReturnType<typeof fetchBookmark>>>, ) { const truncateContent = (content: string) => { - let words = content.split(" "); - if (words.length > 1500) { - words = words.slice(1500); - content = words.join(" "); - } + let words = content.split(" "); + if (words.length > 1500) { + words = words.slice(1500); + content = words.join(" "); + } return content; }; if (bookmark.link) { diff --git a/apps/workers/package.json b/apps/workers/package.json index 27a02f88..c9de43a4 100644 --- a/apps/workers/package.json +++ b/apps/workers/package.json @@ -44,6 +44,8 @@ "scripts": { "start": "tsx watch index.ts", "start:prod": "tsx index.ts", + "lint": "eslint .", + "format": "prettier . --ignore-path ../../.prettierignore", "typecheck": "tsc --noEmit" }, "eslintConfig": { diff --git a/apps/workers/searchWorker.ts b/apps/workers/searchWorker.ts index ae916441..79b0c8c1 100644 --- a/apps/workers/searchWorker.ts +++ b/apps/workers/searchWorker.ts @@ -14,7 +14,7 @@ import { import { getSearchIdxClient } from "@hoarder/shared/search"; export class SearchIndexingWorker { - static async build() { + static build() { logger.info("Starting search indexing worker ..."); const worker = new Worker<ZSearchIndexingRequest, void>( SearchIndexingQueue.name, diff --git a/packages/shared/assetdb.ts b/packages/shared/assetdb.ts index 0840eec2..8fd4da16 100644 --- a/packages/shared/assetdb.ts +++ b/packages/shared/assetdb.ts @@ -22,7 +22,7 @@ export async function saveAsset({ }: { userId: string; assetId: string; - asset: Buffer, + asset: Buffer; metadata: z.infer<typeof zAssetMetadataSchema>; }) { const assetDir = getAssetDir(userId, assetId); @@ -30,7 +30,10 @@ export async function saveAsset({ await Promise.all([ fs.promises.writeFile(path.join(assetDir, "asset.bin"), asset), - fs.promises.writeFile(path.join(assetDir, "metadata.json"), JSON.stringify(metadata)), + fs.promises.writeFile( + path.join(assetDir, "metadata.json"), + JSON.stringify(metadata), + ), ]); } @@ -42,14 +45,16 @@ export async function readAsset({ assetId: string; }) { const assetDir = getAssetDir(userId, assetId); - - const [asset, metadataStr] = await Promise.all([ + + const [asset, metadataStr] = await Promise.all([ fs.promises.readFile(path.join(assetDir, "asset.bin")), - fs.promises.readFile(path.join(assetDir, "metadata.json"), {encoding: "utf8"}), + fs.promises.readFile(path.join(assetDir, "metadata.json"), { + encoding: "utf8", + }), ]); const metadata = zAssetMetadataSchema.parse(JSON.parse(metadataStr)); - return {asset, metadata}; + return { asset, metadata }; } export async function deleteAsset({ @@ -60,5 +65,5 @@ export async function deleteAsset({ assetId: string; }) { const assetDir = getAssetDir(userId, assetId); - await fs.promises.rm(path.join(assetDir), {recursive: true}); + await fs.promises.rm(path.join(assetDir), { recursive: true }); } diff --git a/packages/shared/logger.ts b/packages/shared/logger.ts index 471ec7ab..f406b447 100644 --- a/packages/shared/logger.ts +++ b/packages/shared/logger.ts @@ -1,4 +1,5 @@ import winston from "winston"; + import serverConfig from "./config"; const logger = winston.createLogger({ diff --git a/packages/shared/package.json b/packages/shared/package.json index 716248e8..032f3db5 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -15,6 +15,11 @@ "@hoarder/prettier-config": "workspace:^0.1.0", "@hoarder/tsconfig": "workspace:^0.1.0" }, + "scripts": { + "typecheck": "tsc --noEmit", + "format": "prettier . --ignore-path ../../.prettierignore", + "lint": "eslint ." + }, "main": "index.ts", "eslintConfig": { "root": true, diff --git a/packages/shared/search.ts b/packages/shared/search.ts index 8422d79e..7cd81061 100644 --- a/packages/shared/search.ts +++ b/packages/shared/search.ts @@ -1,7 +1,9 @@ -import { MeiliSearch, Index } from "meilisearch"; -import serverConfig from "./config"; +import type { Index } from "meilisearch"; +import { MeiliSearch } from "meilisearch"; import { z } from "zod"; +import serverConfig from "./config"; + export const zBookmarkIdxSchema = z.object({ id: z.string(), userId: z.string(), @@ -51,15 +53,29 @@ export async function getSearchIdxClient(): Promise<Index<ZBookmarkIdx> | null> const desiredSortableAttributes = ["createdAt"].sort(); const settings = await idxFound.getSettings(); - if (JSON.stringify(settings.filterableAttributes?.sort()) != JSON.stringify(desiredFilterableAttributes)) { - console.log(`[meilisearch] Updating desired filterable attributes to ${desiredFilterableAttributes} from ${settings.filterableAttributes}`); - const taskId = await idxFound.updateFilterableAttributes(desiredFilterableAttributes); + if ( + JSON.stringify(settings.filterableAttributes?.sort()) != + JSON.stringify(desiredFilterableAttributes) + ) { + console.log( + `[meilisearch] Updating desired filterable attributes to ${desiredFilterableAttributes} from ${settings.filterableAttributes}`, + ); + const taskId = await idxFound.updateFilterableAttributes( + desiredFilterableAttributes, + ); await searchClient.waitForTask(taskId.taskUid); } - if (JSON.stringify(settings.sortableAttributes?.sort()) != JSON.stringify(desiredSortableAttributes)) { - console.log(`[meilisearch] Updating desired sortable attributes to ${desiredSortableAttributes} from ${settings.sortableAttributes}`); - const taskId = await idxFound.updateSortableAttributes(desiredSortableAttributes); + if ( + JSON.stringify(settings.sortableAttributes?.sort()) != + JSON.stringify(desiredSortableAttributes) + ) { + console.log( + `[meilisearch] Updating desired sortable attributes to ${desiredSortableAttributes} from ${settings.sortableAttributes}`, + ); + const taskId = await idxFound.updateSortableAttributes( + desiredSortableAttributes, + ); await searchClient.waitForTask(taskId.taskUid); } idxClient = idxFound; diff --git a/packages/trpc/auth.ts b/packages/trpc/auth.ts index c766dd9a..846c07b6 100644 --- a/packages/trpc/auth.ts +++ b/packages/trpc/auth.ts @@ -1,7 +1,8 @@ import { randomBytes } from "crypto"; -import { apiKeys } from "@hoarder/db/schema"; import * as bcrypt from "bcryptjs"; + import { db } from "@hoarder/db"; +import { apiKeys } from "@hoarder/db/schema"; // API Keys diff --git a/packages/trpc/index.ts b/packages/trpc/index.ts index 51c713c0..4055fa5d 100644 --- a/packages/trpc/index.ts +++ b/packages/trpc/index.ts @@ -1,20 +1,21 @@ -import { db } from "@hoarder/db"; -import serverConfig from "@hoarder/shared/config"; -import { TRPCError, initTRPC } from "@trpc/server"; +import { initTRPC, TRPCError } from "@trpc/server"; import superjson from "superjson"; import { ZodError } from "zod"; -type User = { +import type { db } from "@hoarder/db"; +import serverConfig from "@hoarder/shared/config"; + +interface User { id: string; name?: string | null | undefined; email?: string | null | undefined; role: "admin" | "user" | null; -}; +} -export type Context = { +export interface Context { user: User | null; db: typeof db; -}; +} // Avoid exporting the entire t-object // since it's not very descriptive. @@ -29,7 +30,7 @@ const t = initTRPC.context<Context>().create({ data: { ...shape.data, zodError: - error.code === 'BAD_REQUEST' && error.cause instanceof ZodError + error.code === "BAD_REQUEST" && error.cause instanceof ZodError ? error.cause.flatten() : null, }, @@ -53,7 +54,7 @@ export const publicProcedure = procedure; export const authedProcedure = procedure.use(function isAuthed(opts) { const user = opts.ctx.user; - if (!user || !user.id) { + if (!user?.id) { throw new TRPCError({ code: "UNAUTHORIZED" }); } diff --git a/packages/trpc/package.json b/packages/trpc/package.json index 411397dc..ec858ca5 100644 --- a/packages/trpc/package.json +++ b/packages/trpc/package.json @@ -6,6 +6,8 @@ "type": "module", "scripts": { "typecheck": "tsc --noEmit", + "format": "prettier . --ignore-path ../../.prettierignore", + "lint": "eslint .", "test": "vitest" }, "dependencies": { diff --git a/packages/trpc/routers/_app.ts b/packages/trpc/routers/_app.ts index 780fd76d..577b523e 100644 --- a/packages/trpc/routers/_app.ts +++ b/packages/trpc/routers/_app.ts @@ -5,6 +5,7 @@ import { bookmarksAppRouter } from "./bookmarks"; import { listsAppRouter } from "./lists"; import { tagsAppRouter } from "./tags"; import { usersAppRouter } from "./users"; + export const appRouter = router({ bookmarks: bookmarksAppRouter, apiKeys: apiKeysAppRouter, diff --git a/packages/trpc/routers/admin.ts b/packages/trpc/routers/admin.ts index 8a7b592d..4a7c6a80 100644 --- a/packages/trpc/routers/admin.ts +++ b/packages/trpc/routers/admin.ts @@ -1,6 +1,6 @@ -import { adminProcedure, router } from "../index"; -import { z } from "zod"; import { count } from "drizzle-orm"; +import { z } from "zod"; + import { bookmarks, users } from "@hoarder/db/schema"; import { LinkCrawlerQueue, @@ -8,6 +8,8 @@ import { SearchIndexingQueue, } from "@hoarder/shared/queues"; +import { adminProcedure, router } from "../index"; + export const adminAppRouter = router({ stats: adminProcedure .output( diff --git a/packages/trpc/routers/apiKeys.ts b/packages/trpc/routers/apiKeys.ts index 3093b433..deeb108f 100644 --- a/packages/trpc/routers/apiKeys.ts +++ b/packages/trpc/routers/apiKeys.ts @@ -1,9 +1,11 @@ -import { generateApiKey, validatePassword } from "../auth"; -import { authedProcedure, publicProcedure, router } from "../index"; +import { TRPCError } from "@trpc/server"; +import { and, eq } from "drizzle-orm"; import { z } from "zod"; + import { apiKeys } from "@hoarder/db/schema"; -import { eq, and } from "drizzle-orm"; -import { TRPCError } from "@trpc/server"; + +import { generateApiKey, validatePassword } from "../auth"; +import { authedProcedure, publicProcedure, router } from "../index"; const zApiKeySchema = z.object({ id: z.string(), diff --git a/packages/trpc/routers/bookmarks.test.ts b/packages/trpc/routers/bookmarks.test.ts index 724a9998..58f4739d 100644 --- a/packages/trpc/routers/bookmarks.test.ts +++ b/packages/trpc/routers/bookmarks.test.ts @@ -1,5 +1,7 @@ -import { CustomTestContext, defaultBeforeEach } from "../testUtils"; -import { expect, describe, test, beforeEach, assert } from "vitest"; +import { assert, beforeEach, describe, expect, test } from "vitest"; + +import type { CustomTestContext } from "../testUtils"; +import { defaultBeforeEach } from "../testUtils"; beforeEach<CustomTestContext>(defaultBeforeEach(true)); diff --git a/packages/trpc/routers/bookmarks.ts b/packages/trpc/routers/bookmarks.ts index 4fb29c4c..9611829f 100644 --- a/packages/trpc/routers/bookmarks.ts +++ b/packages/trpc/routers/bookmarks.ts @@ -21,19 +21,19 @@ import { } from "@hoarder/shared/queues"; import { getSearchIdxClient } from "@hoarder/shared/search"; -import { authedProcedure, Context, router } from "../index"; +import type { Context } from "../index"; +import type { ZBookmark, ZBookmarkContent } from "../types/bookmarks"; +import type { ZBookmarkTags } from "../types/tags"; +import { authedProcedure, router } from "../index"; import { DEFAULT_NUM_BOOKMARKS_PER_PAGE, zBareBookmarkSchema, - ZBookmark, - ZBookmarkContent, zBookmarkSchema, zGetBookmarksRequestSchema, zGetBookmarksResponseSchema, zNewBookmarkRequestSchema, zUpdateBookmarksRequestSchema, } from "../types/bookmarks"; -import { ZBookmarkTags } from "../types/tags"; export const ensureBookmarkOwnership = experimental_trpcMiddleware<{ ctx: Context; @@ -423,29 +423,29 @@ export const bookmarksAppRouter = router({ input.ids ? inArray(bookmarks.id, input.ids) : undefined, input.tagId !== undefined ? exists( - ctx.db - .select() - .from(tagsOnBookmarks) - .where( - and( - eq(tagsOnBookmarks.bookmarkId, bookmarks.id), - eq(tagsOnBookmarks.tagId, input.tagId), + ctx.db + .select() + .from(tagsOnBookmarks) + .where( + and( + eq(tagsOnBookmarks.bookmarkId, bookmarks.id), + eq(tagsOnBookmarks.tagId, input.tagId), + ), ), - ), - ) + ) : undefined, input.listId !== undefined ? exists( - ctx.db - .select() - .from(bookmarksInLists) - .where( - and( - eq(bookmarksInLists.bookmarkId, bookmarks.id), - eq(bookmarksInLists.listId, input.listId), + ctx.db + .select() + .from(bookmarksInLists) + .where( + and( + eq(bookmarksInLists.bookmarkId, bookmarks.id), + eq(bookmarksInLists.listId, input.listId), + ), ), - ), - ) + ) : undefined, input.cursor ? lte(bookmarks.createdAt, input.cursor) : undefined, ), diff --git a/packages/trpc/routers/lists.ts b/packages/trpc/routers/lists.ts index db5bb38e..fb6d8637 100644 --- a/packages/trpc/routers/lists.ts +++ b/packages/trpc/routers/lists.ts @@ -5,7 +5,8 @@ import { z } from "zod"; import { SqliteError } from "@hoarder/db"; import { bookmarkLists, bookmarksInLists } from "@hoarder/db/schema"; -import { authedProcedure, Context, router } from "../index"; +import type { Context } from "../index"; +import { authedProcedure, router } from "../index"; import { zBookmarkListSchema } from "../types/lists"; import { ensureBookmarkOwnership } from "./bookmarks"; diff --git a/packages/trpc/routers/users.test.ts b/packages/trpc/routers/users.test.ts index 87814407..ea342d33 100644 --- a/packages/trpc/routers/users.test.ts +++ b/packages/trpc/routers/users.test.ts @@ -1,9 +1,7 @@ -import { - CustomTestContext, - defaultBeforeEach, - getApiCaller, -} from "../testUtils"; -import { expect, describe, test, beforeEach, assert } from "vitest"; +import { assert, beforeEach, describe, expect, test } from "vitest"; + +import type { CustomTestContext } from "../testUtils"; +import { defaultBeforeEach, getApiCaller } from "../testUtils"; beforeEach<CustomTestContext>(defaultBeforeEach(false)); diff --git a/packages/trpc/testUtils.ts b/packages/trpc/testUtils.ts index d5f24def..67fbddcc 100644 --- a/packages/trpc/testUtils.ts +++ b/packages/trpc/testUtils.ts @@ -1,7 +1,8 @@ -import { users } from "@hoarder/db/schema"; import { getInMemoryDB } from "@hoarder/db/drizzle"; -import { appRouter } from "./routers/_app"; +import { users } from "@hoarder/db/schema"; + import { createCallerFactory } from "./index"; +import { appRouter } from "./routers/_app"; export function getTestDB() { return getInMemoryDB(true); @@ -63,7 +64,7 @@ export async function buildTestContext( }; } -export function defaultBeforeEach(seedDB: boolean = true) { +export function defaultBeforeEach(seedDB = true) { return async (context: object) => { Object.assign(context, await buildTestContext(seedDB)); }; diff --git a/packages/trpc/tsconfig.json b/packages/trpc/tsconfig.json index 80329662..dbd0afdc 100644 --- a/packages/trpc/tsconfig.json +++ b/packages/trpc/tsconfig.json @@ -5,6 +5,5 @@ "exclude": ["node_modules"], "compilerOptions": { "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json" - }, + } } - diff --git a/packages/trpc/types/bookmarks.ts b/packages/trpc/types/bookmarks.ts index 1b78d6da..b6c8691f 100644 --- a/packages/trpc/types/bookmarks.ts +++ b/packages/trpc/types/bookmarks.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { zBookmarkTagSchema } from "./tags"; export const zBookmarkedLinkSchema = z.object({ @@ -30,7 +31,7 @@ export const zBookmarkContentSchema = z.discriminatedUnion("type", [ zBookmarkedLinkSchema, zBookmarkedTextSchema, zBookmarkedAssetSchema, - z.object({type: z.literal("unknown")}), + z.object({ type: z.literal("unknown") }), ]); export type ZBookmarkContent = z.infer<typeof zBookmarkContentSchema>; diff --git a/packages/trpc/vitest.config.ts b/packages/trpc/vitest.config.ts index c3d02f71..41fd70c4 100644 --- a/packages/trpc/vitest.config.ts +++ b/packages/trpc/vitest.config.ts @@ -1,7 +1,7 @@ /// <reference types="vitest" /> -import { defineConfig } from "vitest/config"; import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; // https://vitejs.dev/config/ export default defineConfig({ diff --git a/tooling/eslint/base.js b/tooling/eslint/base.js index 7a4f9377..285993ef 100644 --- a/tooling/eslint/base.js +++ b/tooling/eslint/base.js @@ -38,6 +38,7 @@ const config = { "**/.eslintrc.cjs", ".next", "dist", + "build", "pnpm-lock.yaml", ], reportUnusedDisableDirectives: true, |
