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
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ bun run format
```

**Important:** Always run `bun run format` from the monorepo root after making
changes to ensure consistent formatting.
changes to ensure consistent formatting. For code changes, verification is not
complete until you have also run `bun run lint` from the monorepo root and the
relevant `bun run tsc` typecheck.

- Always preserve trailing newlines at the end of files.

Expand Down
32 changes: 32 additions & 0 deletions apps/docs/app/(diffshub)/(view)/[...path]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { redirect } from 'next/navigation';

import { ReviewUI } from '../_components/ReviewUI';

// Viewer route that mirrors the upstream path. GitHub is the public default,
// while hidden alternate domains can opt in through the `domain` query param.
export default async function DiffshubViewByPathPage({
params,
searchParams,
}: {
params: Promise<{ path: string[] }>;
searchParams: Promise<{ domain?: string | string[] }>;
}) {
const { path } = await params;
const { domain } = await searchParams;
if (path.length === 0) {
redirect('/');
}
const requestedDomain = Array.isArray(domain) ? domain[0] : domain;
const upstreamPath = `/${path.join('/')}`;
const host =
requestedDomain == null || requestedDomain === ''
? 'github.com'
: requestedDomain;
const url = `https://${host}${upstreamPath}`;

return (
<div className="flex h-dvh flex-col gap-2 bg-neutral-50 dark:bg-neutral-900">
<ReviewUI domain={requestedDomain} initialUrl={url} path={upstreamPath} />
</div>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from 'react';

import { DiffsHubLogo } from './DiffsHubLogo';
import { getGitHubPath } from './utils';
import { getPatchViewerHref } from './utils';
import { Button } from '@/components/ui/button';
import { ButtonGroup, ButtonGroupItem } from '@/components/ui/button-group';
import {
Expand Down Expand Up @@ -103,15 +103,15 @@ export const CodeViewHeader = memo(function CodeViewHeader({
(event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const normalizedURL = url.trim();
const githubPath = getGitHubPath(normalizedURL);
if (githubPath == null) {
const viewerHref = getPatchViewerHref(normalizedURL);
if (viewerHref == null) {
console.error('Invalid URL', normalizedURL);
return;
}

setURL(normalizedURL);
startTransition(() => {
router.push(githubPath);
router.push(viewerHref);
});
}
);
Expand Down
7 changes: 5 additions & 2 deletions apps/docs/app/(diffshub)/(view)/_components/ReviewUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ import {
} from './utils';

interface ReviewUIProps {
domain?: string;
initialUrl: string;
path: string;
}

export function ReviewUI({ initialUrl }: ReviewUIProps) {
export function ReviewUI({ domain, initialUrl, path }: ReviewUIProps) {
const isWorkerPoolReadyOrDisable = useIsWorkerPoolReadyOrDisabled();
const [diffStyle, setDiffStyle] = useState<'split' | 'unified'>('split');
const [fileTreeOverlayOpen, setFileTreeOverlayOpen] = useState(false);
Expand All @@ -56,8 +58,9 @@ export function ReviewUI({ initialUrl }: ReviewUIProps) {
treeSource,
viewerKey,
} = usePatchLoader({
initialUrl,
domain,
onLoadStart: handlePatchLoadStart,
path,
viewerRef,
});

Expand Down
40 changes: 16 additions & 24 deletions apps/docs/app/(diffshub)/(view)/_components/usePatchLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import type {
CodeViewSavedCommentItem,
CommentMetadata,
} from './types';
import { getGitHubPath } from './utils';

const STREAM_PUBLISH_FILE_BATCH_SIZE = 25;
const STREAM_PUBLISH_INTERVAL_MS = 100;
Expand All @@ -41,8 +40,9 @@ const STREAM_TREE_PUBLISH_FILE_BATCH_SIZE = 1_000;
const STREAM_TREE_PUBLISH_INTERVAL_MS = 1_000;

interface UsePatchLoaderOptions {
initialUrl: string;
domain?: string;
onLoadStart?(): void;
path: string;
viewerRef: RefObject<CodeViewHandle<CommentMetadata> | null>;
}

Expand All @@ -60,8 +60,9 @@ interface UsePatchLoaderResult {
}

export function usePatchLoader({
initialUrl,
domain,
onLoadStart,
path,
viewerRef,
}: UsePatchLoaderOptions): UsePatchLoaderResult {
const [initialItems, setInitialItems] = useState<
Expand All @@ -86,18 +87,12 @@ export function usePatchLoader({
const requestIdRef = useRef(0);

useEffect(() => {
const githubPath = getGitHubPath(initialUrl);
if (githubPath == null) {
setInitialItems([]);
setTreeSource(null);
setDiffStats(null);
setCommentFileByItemId(null);
setCommentSections([]);
setErrorMessage('Enter a valid GitHub URL.');
setLoadState('error');
return;
const patchRequestKey =
domain == null || domain === '' ? path : `${domain}${path}`;
const patchSearchParams = new URLSearchParams({ path });
if (domain != null && domain !== '') {
patchSearchParams.set('domain', domain);
}
const resolvedGitHubPath = githubPath;

const controller = new AbortController();
const requestId = ++requestIdRef.current;
Expand All @@ -116,7 +111,7 @@ export function usePatchLoader({

async function loadPatch() {
try {
const cacheKeyPrefix = encodeURIComponent(resolvedGitHubPath);
const cacheKeyPrefix = encodeURIComponent(patchRequestKey);
async function commitFullPatch(patchContent: string) {
if (!isCurrentRequest()) {
return;
Expand All @@ -127,10 +122,7 @@ export function usePatchLoader({
if (!isCurrentRequest()) {
return;
}
const loadedData = buildCodeViewData(
patchContent,
resolvedGitHubPath
);
const loadedData = buildCodeViewData(patchContent, patchRequestKey);
if (!isCurrentRequest()) {
return;
}
Expand All @@ -144,10 +136,10 @@ export function usePatchLoader({
}

console.time('-- request time');
const response = await fetch(
`/api/gh/diff?path=${encodeURIComponent(resolvedGitHubPath)}`,
{ cache: 'no-store', signal: controller.signal }
);
const response = await fetch(`/api/diff?${patchSearchParams}`, {
cache: 'no-store',
signal: controller.signal,
});
console.timeEnd('-- request time');

// This only catches route setup errors. GitHub fetch failures are
Expand Down Expand Up @@ -329,7 +321,7 @@ export function usePatchLoader({
return () => {
controller.abort();
};
}, [initialUrl, loadAttempt, onLoadStart, viewerRef]);
}, [domain, loadAttempt, onLoadStart, path, viewerRef]);

const retryLoad = useCallback(() => {
setLoadAttempt((attempt) => attempt + 1);
Expand Down
58 changes: 41 additions & 17 deletions apps/docs/app/(diffshub)/(view)/_components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,33 +56,57 @@ export function isSavedAnnotation(
export function getGitHubPath(input: string): string | undefined {
try {
const parsedURL = new URL(input);
if (parsedURL.hostname === GITHUB_HOST) {
if (parsedURL.pathname === '/') {
return undefined;
}
return parsedURL.pathname;
}
return getGitHubPathFromURL(parsedURL);
} catch {
return undefined;
}
}

if (parsedURL.hostname !== GITHUB_RAW_DIFF_HOST) {
return undefined;
export function getPatchViewerHref(input: string): string | undefined {
try {
const parsedURL = new URL(input);
const githubPath = getGitHubPathFromURL(parsedURL);
if (githubPath != null) {
return githubPath;
}

const rawDiffMatch = RAW_GITHUB_DIFF_PATH_PATTERN.exec(parsedURL.pathname);
if (rawDiffMatch == null) {
return undefined;
if (parsedURL.pathname !== '/') {
return `${parsedURL.pathname}?domain=${encodeURIComponent(
parsedURL.hostname
)}`;
}

const owner = rawDiffMatch[1];
const repo = rawDiffMatch[2];
const pullFile = rawDiffMatch[3];
if (owner == null || repo == null || pullFile == null) {
return undefined;
} catch {
return undefined;
}
}

function getGitHubPathFromURL(parsedURL: URL): string | undefined {
if (parsedURL.hostname === GITHUB_HOST) {
if (parsedURL.pathname === '/') {
return undefined;
}
return parsedURL.pathname;
}

return `/${owner}/${repo}/pull/${pullFile}`;
} catch {
if (parsedURL.hostname !== GITHUB_RAW_DIFF_HOST) {
return undefined;
}

const rawDiffMatch = RAW_GITHUB_DIFF_PATH_PATTERN.exec(parsedURL.pathname);
if (rawDiffMatch == null) {
return undefined;
}

const owner = rawDiffMatch[1];
const repo = rawDiffMatch[2];
const pullFile = rawDiffMatch[3];
if (owner == null || repo == null || pullFile == null) {
return undefined;
}

return `/${owner}/${repo}/pull/${pullFile}`;
}

// Translates the diff-level change type surfaced by @pierre/diffs into the
Expand Down
8 changes: 4 additions & 4 deletions apps/docs/app/(diffshub)/_home/HomeFetchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
useTransition,
} from 'react';

import { getGitHubPath } from '../(view)/_components/utils';
import { getPatchViewerHref } from '../(view)/_components/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

Expand All @@ -31,13 +31,13 @@ export const HomeFetchForm = memo(function HomeFetchForm() {
const formData = new FormData(event.currentTarget);
const urlField = formData.get('url');
const rawUrl = typeof urlField === 'string' ? urlField.trim() : '';
const githubPath = getGitHubPath(rawUrl);
if (githubPath == null) {
const viewerHref = getPatchViewerHref(rawUrl);
if (viewerHref == null) {
setErrorMessage('Enter a valid GitHub URL.');
return;
}

startTransition(() => router.push(githubPath));
startTransition(() => router.push(viewerHref));
},
[router]
);
Expand Down
File renamed without changes.
Loading
Loading