Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function detectNext(app: Application): Promise<{ version: string | undefin
return { version: installedVersion };
}

const middlewareFileContents = `
const proxyFileContents = `
import { clerkMiddleware } from '@clerk/nextjs/server';
export default clerkMiddleware();

Expand All @@ -51,9 +51,9 @@ export const config = {
};
`;

const commonSetup = appConfigs.next.appRouterQuickstart.clone().removeFile('src/middleware.ts');
const commonSetup = appConfigs.next.appRouterQuickstart.clone().removeFile('src/proxy.ts');

test.describe('next start - missing middleware @quickstart', () => {
test.describe('next start - missing proxy @quickstart', () => {
test.describe.configure({ mode: 'parallel' });
let app: Application;

Expand All @@ -70,21 +70,21 @@ test.describe('next start - missing middleware @quickstart', () => {
await app.teardown();
});

test('Display error for missing middleware', async ({ page, context }) => {
test('Display error for missing proxy', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
await u.page.goToAppHome();

expect(app.serveOutput).toContain('Your Middleware exists at ./src/middleware.(ts|js)');
expect(app.serveOutput).toContain('Your Proxy exists at ./src/proxy.(ts|js)');
});
});

test.describe('next start - invalid middleware at root on src/ @quickstart', () => {
test.describe('next start - invalid proxy at root on src/ @quickstart', () => {
test.describe.configure({ mode: 'parallel' });
let app: Application;

test.beforeAll(async () => {
test.setTimeout(90_000);
app = await commonSetup.addFile('middleware.ts', () => middlewareFileContents).commit();
app = await commonSetup.addFile('proxy.ts', () => proxyFileContents).commit();
await app.setup();
await app.withEnv(appConfigs.envs.withEmailCodesQuickstart);
await app.build();
Expand All @@ -95,23 +95,20 @@ test.describe('next start - invalid middleware at root on src/ @quickstart', ()
await app.teardown();
});

test('Display suggestion for moving middleware to from `./middleware.ts` to `./src/middleware.ts`', async ({
page,
context,
}) => {
test('Display suggestion for moving proxy from `./proxy.ts` to `./src/proxy.ts`', async ({ page, context }) => {
const { version } = await detectNext(app);
const major = parseSemverMajor(version) ?? 0;
test.skip(major >= 16, 'Middleware detection is smarter in Next 16+.');
test.skip(major >= 16, 'Proxy detection is smarter in Next 16+.');
const u = createTestUtils({ app, page, context });
await u.page.goToAppHome();

expect(app.serveOutput).not.toContain('Your Middleware exists at ./src/middleware.(ts|js)');
expect(app.serveOutput).not.toContain('Your Proxy exists at ./src/proxy.(ts|js)');
expect(app.serveOutput).toContain(
'Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./src/middleware.ts. Currently located at ./middleware.ts',
'Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./src/proxy.ts. Currently located at ./proxy.ts',
);
});

test('Does not display misplaced middleware error on Next 16+', async ({ page, context }) => {
test('Does not display misplaced proxy error on Next 16+', async ({ page, context }) => {
const { version } = await detectNext(app);
const major = parseSemverMajor(version) ?? 0;
test.skip(major < 16, 'Only applicable on Next 16+');
Expand All @@ -121,13 +118,13 @@ test.describe('next start - invalid middleware at root on src/ @quickstart', ()
});
});

test.describe('next start - invalid middleware inside app on src/ @quickstart', () => {
test.describe('next start - invalid proxy inside app on src/ @quickstart', () => {
test.describe.configure({ mode: 'parallel' });
let app: Application;

test.beforeAll(async () => {
test.setTimeout(90_000);
app = await commonSetup.addFile('src/app/middleware.ts', () => middlewareFileContents).commit();
app = await commonSetup.addFile('src/app/proxy.ts', () => proxyFileContents).commit();
await app.setup();
await app.withEnv(appConfigs.envs.withEmailCodesQuickstart);
await app.build();
Expand All @@ -138,15 +135,15 @@ test.describe('next start - invalid middleware inside app on src/ @quickstart',
await app.teardown();
});

test('Display suggestion for moving middleware to from `./src/app/middleware.ts` to `./src/middleware.ts`', async ({
test('Display suggestion for moving proxy from `./src/app/proxy.ts` to `./src/proxy.ts`', async ({
page,
context,
}) => {
const u = createTestUtils({ app, page, context });
await u.page.goToAppHome();
expect(app.serveOutput).not.toContain('Your Middleware exists at ./src/middleware.(ts|js)');
expect(app.serveOutput).not.toContain('Your Proxy exists at ./src/proxy.(ts|js)');
expect(app.serveOutput).toContain(
'Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./src/middleware.ts. Currently located at ./src/app/middleware.ts',
'Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./src/proxy.ts. Currently located at ./src/app/proxy.ts',
);
});
});
4 changes: 2 additions & 2 deletions packages/nextjs/src/app-router/server/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export const auth: AuthFn = (async (options?: AuthOptions) => {

const stepsBasedOnSrcDirectory = async () => {
try {
const isSrcAppDir = await import('../../server/fs/middleware-location.js').then(m => m.hasSrcAppDir());
return [`Your Middleware exists at ./${isSrcAppDir ? 'src/' : ''}middleware.(ts|js)`];
const isSrcAppDir = await import('../../server/fs/proxy-location.js').then(m => m.hasSrcAppDir());
return [`Your Proxy exists at ./${isSrcAppDir ? 'src/' : ''}proxy.(ts|js)`];
} catch {
return [];
}
Expand Down
8 changes: 4 additions & 4 deletions packages/nextjs/src/server/createGetAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export const createAsyncGetAuth = ({
}

if (!detectClerkMiddleware(req)) {
const missConfiguredMiddlewareLocation = await import('./fs/middleware-location.js')
.then(m => m.suggestMiddlewareLocation())
const misconfiguredProxyLocation = await import('./fs/proxy-location.js')
.then(m => m.suggestProxyLocation())
.catch(() => undefined);

if (missConfiguredMiddlewareLocation) {
throw new Error(missConfiguredMiddlewareLocation);
if (misconfiguredProxyLocation) {
throw new Error(misconfiguredProxyLocation);
}

// still throw there is no suggested move location
Expand Down
6 changes: 3 additions & 3 deletions packages/nextjs/src/server/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export const getAuthAuthHeaderMissing = () => authAuthHeaderMissing('getAuth');

export const authAuthHeaderMissing = (helperName = 'auth', prefixSteps?: string[]) =>
`Clerk: ${helperName}() was called but Clerk can't detect usage of clerkMiddleware(). Please ensure the following:
- ${prefixSteps ? [...prefixSteps, ''].join('\n- ') : ' '}clerkMiddleware() is used in your Next.js Middleware.
- Your Middleware matcher is configured to match this route or page.
- If you are using the src directory, make sure the Middleware file is inside of it.
- ${prefixSteps ? [...prefixSteps, ''].join('\n- ') : ' '}clerkMiddleware() is used in your Next.js Proxy.
- Your Proxy matcher is configured to match this route or page.
- If you are using the src directory, make sure the Proxy file is inside of it.

For more details, see https://clerk.com/err/auth-middleware
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ function hasSrcAppDir() {
return !!existsSync(projectWithAppSrc);
}

function suggestMiddlewareLocation() {
function suggestProxyLocation() {
const fileExtensions = ['ts', 'js'] as const;
const suggestionMessage = (
extension: (typeof fileExtensions)[number],
to: 'src/' | '',
from: 'src/app/' | 'app/' | '',
) =>
`Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./${to}middleware.${extension}. Currently located at ./${from}middleware.${extension}`;
`Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./${to}proxy.${extension}. Currently located at ./${from}proxy.${extension}`;

const { existsSync } = nodeFsOrThrow();
const path = nodePathOrThrow();
Expand All @@ -26,30 +26,28 @@ function suggestMiddlewareLocation() {
const projectWithAppSrcPath = path.join(cwd(), 'src', 'app');
const projectWithAppPath = path.join(cwd(), 'app');

const checkMiddlewareLocation = (
const checkProxyLocation = (
basePath: string,
to: 'src/' | '',
from: 'src/app/' | 'app/' | '',
): string | undefined => {
for (const fileExtension of fileExtensions) {
if (existsSync(path.join(basePath, `middleware.${fileExtension}`))) {
if (existsSync(path.join(basePath, `proxy.${fileExtension}`))) {
return suggestionMessage(fileExtension, to, from);
}
}
return undefined;
};

if (existsSync(projectWithAppSrcPath)) {
return (
checkMiddlewareLocation(projectWithAppSrcPath, 'src/', 'src/app/') || checkMiddlewareLocation(cwd(), 'src/', '')
);
return checkProxyLocation(projectWithAppSrcPath, 'src/', 'src/app/') || checkProxyLocation(cwd(), 'src/', '');
}

if (existsSync(projectWithAppPath)) {
return checkMiddlewareLocation(projectWithAppPath, '', 'app/');
return checkProxyLocation(projectWithAppPath, '', 'app/');
}

return undefined;
}

export { suggestMiddlewareLocation, hasSrcAppDir };
export { suggestProxyLocation, hasSrcAppDir };
Loading