Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ jobs:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
bun-version: "1.3.10"
cache: true

- name: Install dependencies
run: bun install --frozen-lockfile
Expand All @@ -36,7 +37,8 @@ jobs:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
bun-version: "1.3.10"
cache: true

- name: Install dependencies
run: bun install --frozen-lockfile
Expand All @@ -54,7 +56,8 @@ jobs:
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
bun-version: "1.3.10"
cache: true

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
8 changes: 2 additions & 6 deletions Dockerfile.project
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# ----------------------------------------------------------------------------
# Stage 1: Base
# ----------------------------------------------------------------------------
FROM oven/bun:1.3.9-debian AS base
FROM oven/bun:1.3.10-debian AS base

LABEL maintainer="Betterbase Team"
LABEL description="Betterbase Project - AI-Native Backend Platform"
Expand Down Expand Up @@ -54,14 +54,10 @@ RUN bun install --frozen-lockfile
# ----------------------------------------------------------------------------
# Stage 3: Builder
# ----------------------------------------------------------------------------
FROM base AS builder
FROM deps AS builder

WORKDIR /app

# Copy lockfile and install all dependencies
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

# Copy source code
COPY . .

Expand Down
15 changes: 4 additions & 11 deletions apps/dashboard/src/components/auth/SetupGuard.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router";
import { checkSetup } from "../../lib/api";

export function SetupGuard({ children }: { children: React.ReactNode }) {
const navigate = useNavigate();
const [checking, setChecking] = useState(true);

useEffect(() => {
// Try hitting /admin/auth/setup without a token.
// If setup is complete, login page is appropriate.
// If setup is not done, /admin/auth/setup returns 201, not 410.
fetch(`${import.meta.env.VITE_API_URL ?? "http://localhost:3001"}/admin/auth/setup`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ _check: true }), // Will fail validation but we only care about 410
})
.then((res) => {
if (res.status === 410) {
// Setup complete — redirect to login
checkSetup()
.then((isSetup: boolean) => {
if (isSetup) {
navigate("/login", { replace: true });
}
setChecking(false);
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/layouts/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const nav = [
{ label: "Projects", href: "/projects", icon: FolderOpen },
{ label: "Storage", href: "/storage", icon: HardDrive },
{ label: "Logs", href: "/logs", icon: ScrollText },
{ label: "Observability", href: "/observability", icon: BarChart2 },
{ label: "Observability", href: "/observability", icon: Activity },
{ label: "Metrics", href: "/metrics", icon: BarChart2 },
{ label: "Audit Log", href: "/audit", icon: Shield },
{ label: "Team", href: "/team", icon: Users },
{
Expand Down
7 changes: 6 additions & 1 deletion apps/dashboard/src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const API_BASE = import.meta.env.VITE_API_URL ?? "http://localhost:3001";
const API_BASE = import.meta.env.VITE_API_URL;

export class ApiError extends Error {
constructor(
Expand Down Expand Up @@ -94,3 +94,8 @@ export const api = {
return res.blob();
},
};

export async function checkSetup(): Promise<boolean> {
const res = await fetch(`${API_BASE}/admin/auth/setup-status`);
return res.status !== 410;
}
10 changes: 8 additions & 2 deletions apps/dashboard/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

export function formatDate(date: string | Date, opts?: Intl.DateTimeFormatOptions) {
export function formatDate(
date: string | Date | null | undefined,
opts?: Intl.DateTimeFormatOptions,
) {
if (!date) return "N/A";
const d = new Date(date);
if (isNaN(d.getTime())) return "N/A";
return new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
...opts,
}).format(new Date(date));
}).format(d);
}

export function formatRelative(date: string | Date): string {
Expand Down
Loading
Loading