Using `next/headers` in a monorepo app
Answered
German Shorthaired Pointer posted this in #help-forum
German Shorthaired PointerOP
I just bumped my version from 14.0.2 to 14.2.1 and I've been getting this error:
These functions are being used in the right places.
You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/react-essentials#server-componentsThese functions are being used in the right places.
createServerClient inside server components, createBrowserClient inside client components. How do I resolve thispackages/supabase-common:import {
createServerClient as serverFn,
createBrowserClient as browserFn,
type CookieOptions,
} from '@supabase/ssr';
import { SupabaseClient, User as SupabaseUser } from '@supabase/supabase-js';
import { cookies as nextCookies } from 'next/headers';
import { NextResponse, type NextRequest } from 'next/server';
export type User = SupabaseUser;
const getSupabaseCredentials = (): {
supabaseUrl: string;
supabaseAnonKey: string;
} => {
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!supabaseUrl || !supabaseAnonKey) {
throw new Error(
'Supabase URL and Anon Key must be set in environment variables.',
);
}
return { supabaseUrl, supabaseAnonKey };
};
export const createServerClient = <T = any>({
cookies,
}: {
cookies: typeof nextCookies;
}): SupabaseClient<T> => {
const cookieStore = cookies();
const { supabaseUrl, supabaseAnonKey } = getSupabaseCredentials();
return serverFn<T>(supabaseUrl, supabaseAnonKey, {
cookies: {
get: (name: string) => cookieStore.get(name)?.value,
},
});
};
export const createBrowserClient = <T = any>(): SupabaseClient<T> => {
const { supabaseUrl, supabaseAnonKey } = getSupabaseCredentials();
return browserFn<T>(supabaseUrl, supabaseAnonKey);
};
export const createRouteHandlerClient = <T = any>({
cookies,
}: {
cookies: typeof nextCookies;
}): SupabaseClient<T> => {
const cookieStore = cookies();
const { supabaseUrl, supabaseAnonKey } = getSupabaseCredentials();
return serverFn<T>(supabaseUrl, supabaseAnonKey, {
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
cookieStore.set({ name, value, ...options });
},
remove(name: string, options: CookieOptions) {
cookieStore.set({ name, value: '', ...options });
},
},
});
};
export const createMiddlewareClient = <T = any>({
req,
res,
}: {
req: NextRequest;
res: NextResponse;
}): SupabaseClient<T> => {
const { supabaseUrl, supabaseAnonKey } = getSupabaseCredentials();
return serverFn<T>(supabaseUrl, supabaseAnonKey, {
cookies: {
get(name: string) {
return req.cookies.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
req.cookies.set({
name,
value,
...options,
});
res = NextResponse.next({
request: {
headers: req.headers,
},
});
res.cookies.set({
name,
value,
...options,
});
},
remove(name: string, options: CookieOptions) {
res.cookies.set({
name,
value: '',
...options,
});
res = NextResponse.next({
request: {
headers: req.headers,
},
});
res.cookies.set({
name,
value: '',
...options,
});
},
},
});
};Answered by Rafael Almeida
you need to separate them into two different files, you can't import a file that imports
next/headers in a client component file2 Replies
you need to separate them into two different files, you can't import a file that imports
next/headers in a client component fileAnswer
German Shorthaired PointerOP
Ah that makes sense! Thank you