diff --git a/.dockerignore b/.dockerignore index ebd695d7bc..8e1f18ad76 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,53 @@ -LICENSE -ROADMAP.md -README.md +# dependencies +/node_modules +/apps/*/node_modules +/packages/*/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* +bun-debug.log* +# env files (can opt-in for committing if needed) +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# ide +.idea +.vscode +.turbo +i18n.cache +apps/mail/scripts.ts .gitignore .husky .github .devcontainer -.env.example \ No newline at end of file +.env.example diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 7fd14f9a4c..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -# Use the latest Bun canary image for access to latest features and performance improvements -FROM oven/bun:canary AS base - -# Set working directory inside the container -WORKDIR /app - -# Install global CLI tools for monorepo management and frontend framework -RUN bun install -g next turbo - -# Pre-copy lockfiles and monorepo config to leverage Docker layer caching during dependency resolution -COPY package.json bun.lock turbo.json ./ - -# Prepare directory structure for scoped dependency installs -RUN mkdir -p apps packages - -# Copy only the relevant package manifests to enable selective installation and caching -COPY apps/*/package.json ./apps/ -COPY packages/*/package.json ./packages/ -COPY packages/tsconfig/ ./packages/tsconfig/ - -# Install dependencies for the monorepo. This step benefits from above caching strategy. -RUN bun install - -# Copy the rest of the codebase into the container -COPY . . - -# Run `bun install` again in case any additional dependencies are introduced after full source copy -RUN bun install - -# Build all apps/packages via defined turbo pipeline -RUN bun run build - -# Use a smaller, stable Bun Alpine image for the production stage to minimize final image size -FROM oven/bun:1.2.11-alpine AS production - -# Set working directory in production image -WORKDIR /app - -# Copy fully built app from build stage -COPY --from=base /app /app - -# Set production environment variables -ENV NODE_ENV=production -ENV NODE_OPTIONS=--no-experimental-fetch - -# Add custom entrypoint script and ensure it is executable -COPY entrypoint.sh /app/entrypoint.sh -RUN chmod +x /app/entrypoint.sh - -# Expose application port -EXPOSE 3000 - -# Define container entrypoint script (e.g., to run DB migrations, start server, etc.) -ENTRYPOINT ["/app/entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 2212f96542..2d802f91c5 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ You can set up Zero in two ways: bun install # Start database locally - bun docker:up + bun docker:db:up ``` 2. **Set Up Environment** @@ -81,7 +81,7 @@ You can set up Zero in two ways: ``` - Configure your environment variables (see below) - Setup cloudflare with `bun run cf-install`, you will need to run this everytime there is a `.env` change - - Start the database with the provided docker compose setup: `bun docker:up` + - Start the database with the provided docker compose setup: `bun docker:db:up` - Initialize the database: `bun db:push` 3. **Start the App** @@ -211,7 +211,7 @@ Zero uses PostgreSQL for storing data. Here's how to set it up: Run this command to start a local PostgreSQL instance: ```bash - bun docker:up + bun docker:db:up ``` This creates a database with: diff --git a/apps/mail/app/(auth)/login/login-client.tsx b/apps/mail/app/(auth)/login/login-client.tsx index 9af92b1d5b..7ea98b1559 100644 --- a/apps/mail/app/(auth)/login/login-client.tsx +++ b/apps/mail/app/(auth)/login/login-client.tsx @@ -10,7 +10,7 @@ import { TriangleAlert } from 'lucide-react'; import { useRouter } from 'next/navigation'; import Image from 'next/image'; import { toast } from 'sonner'; -import Link from 'next/link'; +import { env } from '@/lib/env'; interface EnvVarStatus { name: string; @@ -121,7 +121,7 @@ function LoginClientContent({ providers, isProd }: LoginClientProps) { toast.promise( signIn.social({ provider: provider.id as any, - callbackURL: `${process.env.NEXT_PUBLIC_APP_URL}/mail`, + callbackURL: `${env.NEXT_PUBLIC_APP_URL}/mail`, }), { error: 'Login redirect failed', diff --git a/apps/mail/app/(auth)/login/page.tsx b/apps/mail/app/(auth)/login/page.tsx index 2512986a9c..cb6655a014 100644 --- a/apps/mail/app/(auth)/login/page.tsx +++ b/apps/mail/app/(auth)/login/page.tsx @@ -1,24 +1,28 @@ import { authProviders, customProviders, isProviderEnabled } from '@zero/server/auth-providers'; import { LoginClient } from './login-client'; +import { env } from '@/lib/env'; export default function LoginPage() { - const envNodeEnv = process.env.NODE_ENV; + const envNodeEnv = env.NODE_ENV; const isProd = envNodeEnv === 'production'; - const authProviderStatus = authProviders(process.env as Record).map( + const authProviderStatus = authProviders(env as unknown as Record).map( (provider) => { const envVarStatus = - provider.envVarInfo?.map((envVar) => ({ - name: envVar.name, - set: !!process.env[envVar.name], - source: envVar.source, - defaultValue: envVar.defaultValue, - })) || []; + provider.envVarInfo?.map((envVar) => { + const envVarName = envVar.name as keyof typeof env; + return { + name: envVar.name, + set: !!env[envVarName], + source: envVar.source, + defaultValue: envVar.defaultValue, + }; + }) || []; return { id: provider.id, name: provider.name, - enabled: isProviderEnabled(provider, process.env as Record), + enabled: isProviderEnabled(provider, env as Record), required: provider.required, envVarInfo: provider.envVarInfo, envVarStatus, diff --git a/apps/mail/app/(routes)/settings/connections/page.tsx b/apps/mail/app/(routes)/settings/connections/page.tsx index da11b5a620..28266134e9 100644 --- a/apps/mail/app/(routes)/settings/connections/page.tsx +++ b/apps/mail/app/(routes)/settings/connections/page.tsx @@ -24,6 +24,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { useTranslations } from 'next-intl'; import { useState } from 'react'; +import { env } from '@/lib/env'; import Image from 'next/image'; import { toast } from 'sonner'; @@ -147,7 +148,7 @@ export default function ConnectionsPage() { onClick={async () => { await authClient.linkSocial({ provider: connection.providerId, - callbackURL: `${process.env.NEXT_PUBLIC_APP_URL}/settings/connections`, + callbackURL: `${env.NEXT_PUBLIC_APP_URL}/settings/connections`, }); }} > diff --git a/apps/mail/app/layout.tsx b/apps/mail/app/layout.tsx index bdf968d022..cdbbcee57e 100644 --- a/apps/mail/app/layout.tsx +++ b/apps/mail/app/layout.tsx @@ -2,6 +2,7 @@ import { ClientProviders } from '@/providers/client-providers'; import { ServerProviders } from '@/providers/server-providers'; import { SpeedInsights } from '@vercel/speed-insights/next'; import { Geist, Geist_Mono } from 'next/font/google'; +import { PublicEnvScript } from 'next-runtime-env'; import { siteConfig } from '@/lib/site-config'; import type { PropsWithChildren } from 'react'; import type { Viewport } from 'next'; @@ -33,6 +34,7 @@ export default async function RootLayout({ children }: PropsWithChildren) {