Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
- Updated NextJS to version 15. [#477](https://github.com/sourcebot-dev/sourcebot/pull/477)

## [4.6.4] - 2025-08-11

### Added
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@
"dotenv-cli": "^8.0.0",
"npm-run-all": "^4.1.5"
},
"packageManager": "yarn@4.7.0"
"packageManager": "yarn@4.7.0",
"resolutions": {
"prettier": "3.5.3"
}
}
2 changes: 1 addition & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/micromatch": "^4.0.9",
"@types/node": "^22.7.5",
"cross-env": "^7.0.3",
"json-schema-to-typescript": "^15.0.2",
"json-schema-to-typescript": "^15.0.4",
"tsc-watch": "^6.2.0",
"tsx": "^4.19.1",
"typescript": "^5.6.2",
Expand Down
1 change: 1 addition & 0 deletions packages/web/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# shadcn components
src/components/
next-env.d.ts
2 changes: 2 additions & 0 deletions packages/web/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const nextConfig = {
},
]
},

turbopack: {}
};

export default withSentryConfig(nextConfig, {
Expand Down
32 changes: 19 additions & 13 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbopack",
"build": "cross-env SKIP_ENV_VALIDATION=1 next build",
"start": "next start",
"lint": "cross-env SKIP_ENV_VALIDATION=1 next lint",
"lint": "cross-env SKIP_ENV_VALIDATION=1 eslint .",
"test": "vitest",
"dev:emails": "email dev --dir ./src/emails",
"stripe:listen": "stripe listen --forward-to http://localhost:3000/api/stripe"
Expand Down Expand Up @@ -146,7 +146,7 @@
"langfuse-vercel": "^3.38.4",
"lucide-react": "^0.517.0",
"micromatch": "^4.0.8",
"next": "14.2.30",
"next": "15.5.0",
"next-auth": "^5.0.0-beta.25",
"next-navigation-guard": "^0.2.0",
"next-themes": "^0.3.0",
Expand All @@ -157,9 +157,9 @@
"posthog-js": "^1.161.5",
"pretty-bytes": "^6.1.1",
"psl": "^1.15.0",
"react": "^18",
"react": "19.1.1",
"react-device-detect": "^2.2.3",
"react-dom": "^18",
"react-dom": "19.1.1",
"react-hook-form": "^7.53.0",
"react-hotkeys-hook": "^4.5.1",
"react-icons": "^5.3.0",
Expand Down Expand Up @@ -187,21 +187,23 @@
"zod-to-json-schema": "^3.24.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@tanstack/eslint-plugin-query": "^5.74.7",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.0",
"@types/micromatch": "^4.0.9",
"@types/node": "^20",
"@types/nodemailer": "^6.4.17",
"@types/psl": "^1.1.3",
"@types/react": "^18",
"@types/react-dom": "^18",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"@types/react": "19.1.10",
"@types/react-dom": "19.1.7",
"@typescript-eslint/eslint-plugin": "^8.40.0",
"@typescript-eslint/parser": "^8.40.0",
"cross-env": "^7.0.3",
"eslint": "^8",
"eslint-config-next": "14.2.6",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-config-next": "15.5.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"jsdom": "^25.0.1",
"npm-run-all": "^4.1.5",
"postcss": "^8",
Expand All @@ -211,5 +213,9 @@
"typescript": "^5",
"vite-tsconfig-paths": "^5.1.3",
"vitest": "^2.1.5"
},
"resolutions": {
"@types/react": "19.1.10",
"@types/react-dom": "19.1.7"
}
}
6 changes: 3 additions & 3 deletions packages/web/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export const withTenancyModeEnforcement = async<T>(mode: TenancyMode, fn: () =>

////// Actions ///////

export const createOrg = (name: string, domain: string): Promise<{ id: number } | ServiceError> => sew(() =>
export const createOrg = async (name: string, domain: string): Promise<{ id: number } | ServiceError> => sew(() =>
withTenancyModeEnforcement('multi', () =>
withAuth(async (userId) => {
const org = await prisma.org.create({
Expand Down Expand Up @@ -293,7 +293,7 @@ export const completeOnboarding = async (domain: string): Promise<{ success: boo
})
));

export const getSecrets = (domain: string): Promise<{ createdAt: Date; key: string; }[] | ServiceError> => sew(() =>
export const getSecrets = async (domain: string): Promise<{ createdAt: Date; key: string; }[] | ServiceError> => sew(() =>
withAuth((userId) =>
withOrgMembership(userId, domain, async ({ org }) => {
const secrets = await prisma.secret.findMany({
Expand Down Expand Up @@ -1990,7 +1990,7 @@ export const rejectAccountRequest = async (requestId: string, domain: string) =>
));

export const dismissMobileUnsupportedSplashScreen = async () => sew(async () => {
await cookies().set(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, 'true');
await (await cookies()).set(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, 'true');
return true;
});

Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/app/[domain]/agents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ const agents = [
},
];

export default function AgentsPage({ params: { domain } }: { params: { domain: string } }) {
export default async function AgentsPage(props: { params: Promise<{ domain: string }> }) {
const params = await props.params;

const {
domain
} = params;

return (
<div className="flex flex-col items-center overflow-hidden min-h-screen">
<NavigationMenu domain={domain} />
Expand Down
13 changes: 10 additions & 3 deletions packages/web/src/app/[domain]/browse/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import { Loader2 } from "lucide-react";
import { TreePreviewPanel } from "./components/treePreviewPanel";

interface BrowsePageProps {
params: {
params: Promise<{
path: string[];
domain: string;
};
}>;
}

export default async function BrowsePage({ params: { path: _rawPath, domain } }: BrowsePageProps) {
export default async function BrowsePage(props: BrowsePageProps) {
const params = await props.params;

const {
path: _rawPath,
domain
} = params;

const rawPath = decodeURIComponent(_rawPath.join('/'));
const { repoName, revisionName, path, pathType } = getBrowseParamsFromPathParam(rawPath);

Expand Down
7 changes: 4 additions & 3 deletions packages/web/src/app/[domain]/chat/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import { ChatSidePanel } from '../components/chatSidePanel';
import { ResizablePanelGroup } from '@/components/ui/resizable';

interface PageProps {
params: {
params: Promise<{
domain: string;
id: string;
};
}>;
}

export default async function Page({ params }: PageProps) {
export default async function Page(props: PageProps) {
const params = await props.params;
const languageModels = await getConfiguredLanguageModelsInfo();
const repos = await getRepos(params.domain);
const searchContexts = await getSearchContexts(params.domain);
Expand Down
7 changes: 4 additions & 3 deletions packages/web/src/app/[domain]/chat/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import { auth } from "@/auth";
import { AnimatedResizableHandle } from "@/components/ui/animatedResizableHandle";

interface PageProps {
params: {
params: Promise<{
domain: string;
};
}>;
}

export default async function Page({ params }: PageProps) {
export default async function Page(props: PageProps) {
const params = await props.params;
const languageModels = await getConfiguredLanguageModelsInfo();
const repos = await getRepos(params.domain);
const searchContexts = await getSearchContexts(params.domain);
Expand Down
55 changes: 30 additions & 25 deletions packages/web/src/app/[domain]/components/navigationMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,43 +57,48 @@ export const NavigationMenu = async ({
<NavigationMenuBase>
<NavigationMenuList>
<NavigationMenuItem>
<Link href={`/${domain}`} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Search
</NavigationMenuLink>
</Link>
<NavigationMenuLink
href={`/${domain}`}
className={navigationMenuTriggerStyle()}
>
Search
</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href={`/${domain}/repos`} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Repositories
</NavigationMenuLink>
</Link>
<NavigationMenuLink
href={`/${domain}/repos`}
className={navigationMenuTriggerStyle()}
>
Repositories
</NavigationMenuLink>
</NavigationMenuItem>
{isAuthenticated && (
<>
{env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === undefined && (
<NavigationMenuItem>
<Link href={`/${domain}/agents`} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Agents
</NavigationMenuLink>
</Link>
<NavigationMenuLink
href={`/${domain}/agents`}
className={navigationMenuTriggerStyle()}
>
Agents
</NavigationMenuLink>
</NavigationMenuItem>
)}
<NavigationMenuItem>
<Link href={`/${domain}/connections`} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Connections
</NavigationMenuLink>
</Link>
<NavigationMenuLink
href={`/${domain}/connections`}
className={navigationMenuTriggerStyle()}
>
Connections
</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<Link href={`/${domain}/settings`} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
Settings
</NavigationMenuLink>
</Link>
<NavigationMenuLink
href={`/${domain}/settings`}
className={navigationMenuTriggerStyle()}
>
Settings
</NavigationMenuLink>
</NavigationMenuItem>
</>
)}
Expand Down
12 changes: 7 additions & 5 deletions packages/web/src/app/[domain]/connections/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ import { CodeHostType } from "@/lib/utils"
import { env } from "@/env.mjs"

interface ConnectionManagementPageProps {
params: {
params: Promise<{
domain: string
id: string
},
searchParams: {
}>,
searchParams: Promise<{
tab: string
}
}>
}

export default async function ConnectionManagementPage({ params, searchParams }: ConnectionManagementPageProps) {
export default async function ConnectionManagementPage(props: ConnectionManagementPageProps) {
const searchParams = await props.searchParams;
const params = await props.params;
const connection = await getConnectionByDomain(Number(params.id), params.domain);
if (!connection) {
return <NotFound className="flex w-full h-full items-center justify-center" message="Connection not found" />
Expand Down
23 changes: 17 additions & 6 deletions packages/web/src/app/[domain]/connections/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@ import { auth } from "@/auth";
import { NavigationMenu } from "../components/navigationMenu";
import { redirect } from "next/navigation";

export default async function Layout({
children,
params: { domain },
}: Readonly<{
interface LayoutProps {
children: React.ReactNode;
params: { domain: string };
}>) {
params: Promise<{ domain: string }>;
}

export default async function Layout(
props: LayoutProps
) {
const params = await props.params;

const {
domain
} = params;

const {
children
} = props;

const session = await auth();
if (!session) {
return redirect(`/${domain}`);
Expand Down
9 changes: 4 additions & 5 deletions packages/web/src/app/[domain]/connections/new/[type]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import {
BitbucketCloudConnectionCreationForm,
BitbucketDataCenterConnectionCreationForm
} from "@/app/[domain]/components/connectionCreationForms";
import { useCallback } from "react";
import { useCallback, use } from "react";
import { useDomain } from "@/hooks/useDomain";

export default function NewConnectionPage({
params
}: { params: { type: string } }) {
export default function NewConnectionPage(props: { params: Promise<{ type: string }> }) {
const params = use(props.params);
const { type } = params;
const router = useRouter();
const domain = useDomain();
Expand Down Expand Up @@ -46,7 +45,7 @@ export default function NewConnectionPage({
if (type === 'bitbucket-server') {
return <BitbucketDataCenterConnectionCreationForm onCreated={onCreated} />;
}


router.push(`/${domain}/connections`);
}
10 changes: 8 additions & 2 deletions packages/web/src/app/[domain]/connections/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import { notFound, ServiceErrorException } from "@/lib/serviceError";
import { OrgRole } from "@sourcebot/db";
import { env } from "@/env.mjs";

export default async function ConnectionsPage({ params: { domain } }: { params: { domain: string } }) {
export default async function ConnectionsPage(props: { params: Promise<{ domain: string }> }) {
const params = await props.params;

const {
domain
} = params;

const connections = await getConnections(domain);
if (isServiceError(connections)) {
throw new ServiceErrorException(connections);
}

const membership = await getOrgMembership(domain);
if (isServiceError(membership)) {
return notFound();
throw new ServiceErrorException(notFound());
}

return (
Expand Down
Loading