feat: config.js

This commit is contained in:
Vasily Zubarev
2025-04-03 14:36:16 +02:00
parent f523b1f8ba
commit f1a26e511e
26 changed files with 165 additions and 126 deletions

View File

@@ -4,7 +4,7 @@ import DashboardUnsortedWidget from "@/components/dashboard/unsorted-widget"
import { WelcomeWidget } from "@/components/dashboard/welcome-widget"
import { Separator } from "@/components/ui/separator"
import { getCurrentUser } from "@/lib/auth"
import { APP_DESCRIPTION } from "@/lib/constants"
import config from "@/lib/config"
import { getUnsortedFiles } from "@/models/files"
import { getSettings } from "@/models/settings"
import { TransactionFilters } from "@/models/transactions"
@@ -12,7 +12,7 @@ import { Metadata } from "next"
export const metadata: Metadata = {
title: "Dashboard",
description: APP_DESCRIPTION,
description: config.app.description,
}
export default async function Dashboard({ searchParams }: { searchParams: Promise<TransactionFilters> }) {

View File

@@ -4,7 +4,7 @@ import { AppSidebar } from "@/components/sidebar/sidebar"
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"
import { Toaster } from "@/components/ui/sonner"
import { getCurrentUser } from "@/lib/auth"
import { APP_DESCRIPTION, APP_TITLE } from "@/lib/constants"
import config from "@/lib/config"
import { getUnsortedFilesCount } from "@/models/files"
import type { Metadata, Viewport } from "next"
import "../globals.css"
@@ -13,9 +13,9 @@ import { NotificationProvider } from "./context"
export const metadata: Metadata = {
title: {
template: "%s | TaxHacker",
default: APP_TITLE,
default: config.app.title,
},
description: APP_DESCRIPTION,
description: config.app.description,
icons: {
icon: "/favicon.ico",
shortcut: "/favicon.ico",
@@ -38,13 +38,14 @@ export default async function RootLayout({ children }: { children: React.ReactNo
<SidebarProvider>
<MobileMenu unsortedFilesCount={unsortedFilesCount} />
<AppSidebar
unsortedFilesCount={unsortedFilesCount}
profile={{
id: user.id,
name: user.name || "",
email: user.email,
avatar: user.avatar || undefined,
}}
unsortedFilesCount={unsortedFilesCount}
isSelfHosted={config.selfHosted.isEnabled}
/>
<SidebarInset className="w-full h-full mt-[60px] md:mt-0 overflow-auto">{children}</SidebarInset>
</SidebarProvider>

View File

@@ -1,5 +1,6 @@
import LLMSettingsForm from "@/components/settings/llm-settings-form"
import { getCurrentUser } from "@/lib/auth"
import config from "@/lib/config"
import { getFields } from "@/models/fields"
import { getSettings } from "@/models/settings"
@@ -11,7 +12,7 @@ export default async function LlmSettingsPage() {
return (
<>
<div className="w-full max-w-2xl">
<LLMSettingsForm settings={settings} fields={fields} />
<LLMSettingsForm settings={settings} fields={fields} showApiKey={config.selfHosted.isEnabled} />
</div>
</>
)

View File

@@ -6,7 +6,7 @@ import { buildLLMPrompt } from "@/ai/prompt"
import { fieldsToJsonSchema } from "@/ai/schema"
import { transactionFormSchema } from "@/forms/transactions"
import { getCurrentUser } from "@/lib/auth"
import { IS_SELF_HOSTED_MODE } from "@/lib/constants"
import config from "@/lib/config"
import { getTransactionFileUploadPath, getUserUploadsDirectory } from "@/lib/files"
import { DEFAULT_PROMPT_ANALYSE_NEW_FILE } from "@/models/defaults"
import { deleteFile, getFileById, updateFile } from "@/models/files"
@@ -50,7 +50,7 @@ export async function analyzeFileAction(
prompt,
schema,
attachments,
IS_SELF_HOSTED_MODE ? settings.openai_api_key : process.env.OPENAI_API_KEY || ""
config.selfHosted.isEnabled ? settings.openai_api_key : process.env.OPENAI_API_KEY || ""
)
console.log("Analysis results:", results)

View File

@@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import AnalyzeForm from "@/components/unsorted/analyze-form"
import { getCurrentUser } from "@/lib/auth"
import { IS_SELF_HOSTED_MODE } from "@/lib/constants"
import config from "@/lib/config"
import { getCategories } from "@/models/categories"
import { getCurrencies } from "@/models/currencies"
import { getFields } from "@/models/fields"
@@ -36,7 +36,7 @@ export default async function UnsortedPage() {
<h2 className="text-3xl font-bold tracking-tight">You have {files.length} unsorted files</h2>
</header>
{IS_SELF_HOSTED_MODE && !settings.openai_api_key && (
{config.selfHosted.isEnabled && !settings.openai_api_key && (
<Alert>
<Settings className="h-4 w-4 mt-2" />
<div className="flex flex-row justify-between pt-2">

View File

@@ -1,12 +1,12 @@
import { LoginForm } from "@/components/auth/login-form"
import { Card, CardContent, CardTitle } from "@/components/ui/card"
import { ColoredText } from "@/components/ui/colored-text"
import { IS_SELF_HOSTED_MODE, SELF_HOSTED_REDIRECT_URL } from "@/lib/constants"
import config from "@/lib/config"
import { redirect } from "next/navigation"
export default async function LoginPage() {
if (IS_SELF_HOSTED_MODE) {
redirect(SELF_HOSTED_REDIRECT_URL)
if (config.selfHosted.isEnabled) {
redirect(config.selfHosted.redirectUrl)
}
return (

View File

@@ -3,7 +3,7 @@ import { FormInput } from "@/components/forms/simple"
import { Button } from "@/components/ui/button"
import { Card, CardDescription, CardTitle } from "@/components/ui/card"
import { ColoredText } from "@/components/ui/colored-text"
import { IS_SELF_HOSTED_MODE, SELF_HOSTED_REDIRECT_URL } from "@/lib/constants"
import config from "@/lib/config"
import { DEFAULT_CURRENCIES, DEFAULT_SETTINGS } from "@/models/defaults"
import { getSelfHostedUser } from "@/models/users"
import { ShieldAlert } from "lucide-react"
@@ -11,7 +11,7 @@ import { redirect } from "next/navigation"
import { selfHostedGetStartedAction } from "../actions"
export default async function SelfHostedWelcomePage() {
if (!IS_SELF_HOSTED_MODE) {
if (!config.selfHosted.isEnabled) {
return (
<Card className="w-full max-w-xl mx-auto p-8 flex flex-col items-center justify-center gap-6">
<CardTitle className="text-2xl font-bold flex items-center gap-2">
@@ -31,7 +31,7 @@ export default async function SelfHostedWelcomePage() {
const user = await getSelfHostedUser()
if (user) {
redirect(SELF_HOSTED_REDIRECT_URL)
redirect(config.selfHosted.redirectUrl)
}
return (

View File

@@ -1,17 +1,17 @@
import { AUTH_LOGIN_URL, IS_SELF_HOSTED_MODE, SELF_HOSTED_WELCOME_URL } from "@/lib/constants"
import config from "@/lib/config"
import { createUserDefaults, isDatabaseEmpty } from "@/models/defaults"
import { getSelfHostedUser } from "@/models/users"
import { revalidatePath } from "next/cache"
import { redirect } from "next/navigation"
export async function GET(request: Request) {
if (!IS_SELF_HOSTED_MODE) {
redirect(AUTH_LOGIN_URL)
if (!config.selfHosted.isEnabled) {
redirect(config.auth.loginUrl)
}
const user = await getSelfHostedUser()
if (!user) {
redirect(SELF_HOSTED_WELCOME_URL)
redirect(config.selfHosted.welcomeUrl)
}
if (await isDatabaseEmpty(user.id)) {

View File

@@ -1,11 +1,12 @@
import SignupForm from "@/components/auth/signup-form"
import { Card, CardContent, CardTitle } from "@/components/ui/card"
import { ColoredText } from "@/components/ui/colored-text"
import { IS_SELF_HOSTED_MODE, SELF_HOSTED_REDIRECT_URL } from "@/lib/constants"
import config from "@/lib/config"
import { redirect } from "next/navigation"
export default async function LoginPage() {
if (IS_SELF_HOSTED_MODE) {
redirect(SELF_HOSTED_REDIRECT_URL)
if (config.selfHosted.isEnabled) {
redirect(config.selfHosted.redirectUrl)
}
return (
@@ -15,10 +16,13 @@ export default async function LoginPage() {
<ColoredText>TaxHacker: Cloud Edition</ColoredText>
</CardTitle>
<CardContent className="w-full">
<div className="text-center text-md text-muted-foreground">
Creating new account is disabled for now. Please use the self-hosted version.
</div>
{/* <SignupForm /> */}
{config.auth.disableSignup ? (
<div className="text-center text-md text-muted-foreground">
Creating new account is disabled for now. Please use the self-hosted version.
</div>
) : (
<SignupForm />
)}
</CardContent>
</Card>
)

View File

@@ -1,5 +1,6 @@
"use server"
import config from "@/lib/config"
import { resend, sendNewsletterWelcomeEmail } from "@/lib/email"
export async function subscribeToNewsletterAction(email: string) {
@@ -9,7 +10,7 @@ export async function subscribeToNewsletterAction(email: string) {
}
const existingContacts = await resend.contacts.list({
audienceId: process.env.RESEND_AUDIENCE_ID as string,
audienceId: config.email.audienceId,
})
if (existingContacts.data) {
@@ -22,7 +23,7 @@ export async function subscribeToNewsletterAction(email: string) {
await resend.contacts.create({
email,
audienceId: process.env.RESEND_AUDIENCE_ID as string,
audienceId: config.email.audienceId,
unsubscribed: false,
})

View File

@@ -1,13 +1,13 @@
import config from "@/lib/config"
import type { Metadata, Viewport } from "next"
import "./globals.css"
import { APP_DESCRIPTION, APP_TITLE } from "@/lib/constants"
export const metadata: Metadata = {
title: {
template: "%s | TaxHacker",
default: APP_TITLE,
default: config.app.title,
},
description: APP_DESCRIPTION,
description: config.app.description,
icons: {
icon: "/favicon.ico",
shortcut: "/favicon.ico",

View File

@@ -1,13 +1,13 @@
import LandingPage from "@/app/landing/landing"
import { getSession } from "@/lib/auth"
import { IS_SELF_HOSTED_MODE, SELF_HOSTED_REDIRECT_URL } from "@/lib/constants"
import config from "@/lib/config"
import { redirect } from "next/navigation"
export default async function Home() {
const session = await getSession()
if (!session) {
if (IS_SELF_HOSTED_MODE) {
redirect(SELF_HOSTED_REDIRECT_URL)
if (config.selfHosted.isEnabled) {
redirect(config.selfHosted.redirectUrl)
}
return <LandingPage />
}