Skip to content

Commit

Permalink
Add support for Next 15 (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospassos authored Jan 15, 2025
1 parent 7bf7026 commit 751afe6
Show file tree
Hide file tree
Showing 15 changed files with 1,943 additions and 1,675 deletions.
3,431 changes: 1,842 additions & 1,589 deletions package-lock.json

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.json"
},
"peerDependencies": {
"next": "^13.0 || ^14.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
"next": "^13.0 || ^14.0 || ^15.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"dependencies": {
"@croct/plug": "^0.16.2",
"@croct/plug-react": "^0.9.0",
"@croct/plug-react": "^0.10.0",
"@croct/sdk": "^0.17.4",
"@vercel/functions": "^1.5.2",
"cookie": "^0.7.0",
"uuid": "^10.0.0"
},
Expand All @@ -49,13 +50,13 @@
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@croct/eslint-plugin": "^0.7.0",
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^16.0.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.1.0",
"@types/cookie": "^0.6.0",
"@types/jest": "^29.2.3",
"@types/node": "^22.0.0",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@types/set-cookie-parser": "^2.4.7",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
Expand All @@ -66,8 +67,8 @@
"jest-environment-jsdom": "^29.7.0",
"jest-environment-node": "^29.7.0",
"jest-extended": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"set-cookie-parser": "^2.6.0",
"ts-node": "^10.8.1",
"tsc-alias": "^1.8.8",
Expand Down
16 changes: 8 additions & 8 deletions src/CroctProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('<CroctProvider />', () => {
previewToken: getPreviewCookieOptions(),
},
},
expect.anything(),
undefined,
);
});

Expand Down Expand Up @@ -111,7 +111,7 @@ describe('<CroctProvider />', () => {
defaultPreferredLocale: config.defaultPreferredLocale,
disableCidMirroring: true,
},
expect.anything(),
undefined,
);
});

Expand All @@ -124,7 +124,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
appId: process.env.NEXT_PUBLIC_CROCT_APP_ID,
}),
expect.anything(),
undefined,
);
});

Expand All @@ -138,7 +138,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
debug: true,
}),
expect.anything(),
undefined,
);
});

Expand All @@ -152,7 +152,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
test: true,
}),
expect.anything(),
undefined,
);
});

Expand All @@ -166,7 +166,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
baseEndpointUrl: process.env.NEXT_PUBLIC_CROCT_BASE_ENDPOINT_URL,
}),
expect.anything(),
undefined,
);
});

Expand All @@ -180,7 +180,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
defaultFetchTimeout: 3000,
}),
expect.anything(),
undefined,
);
});

Expand All @@ -194,7 +194,7 @@ describe('<CroctProvider />', () => {
expect.objectContaining({
defaultPreferredLocale: process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE,
}),
expect.anything(),
undefined,
);
});
});
28 changes: 14 additions & 14 deletions src/config/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {Header} from '@/config/http';
import {getUserTokenCookieOptions} from '@/config/cookie';
import {getCookies, getHeaders, PartialRequest, PartialResponse, RouteContext} from '@/headers';

type ReadonlyCookies = ReturnType<typeof cookies>;
type ReadonlyCookies = Awaited<ReturnType<typeof cookies>>;

function createCookieJar(cookies: Record<string, string> = {}): ReadonlyCookies {
const jar: Record<string, string> = {...cookies};
Expand Down Expand Up @@ -167,7 +167,7 @@ describe('getRequestContext', () => {
});

describe('resolveRequestContext', () => {
it('should return the request context', () => {
it('should return the request context', async () => {
const headers = new Headers();
const cookies = createCookieJar();

Expand All @@ -194,10 +194,10 @@ describe('resolveRequestContext', () => {
headers.set(Header.PREVIEW_TOKEN, request.previewToken);
headers.set(Header.PREFERRED_LOCALE, request.preferredLocale);

jest.mocked(getHeaders).mockReturnValue(headers);
jest.mocked(getCookies).mockReturnValue(cookies);
jest.mocked(getHeaders).mockResolvedValue(headers);
jest.mocked(getCookies).mockResolvedValue(cookies);

expect(resolveRequestContext(route)).toEqual(request);
await expect(resolveRequestContext(route)).resolves.toEqual(request);

expect(getHeaders).toHaveBeenCalledWith(route);
expect(getCookies).toHaveBeenCalledWith(route);
Expand All @@ -210,7 +210,7 @@ describe('resolvePreferredLocale', () => {
jest.clearAllMocks();
});

it('should return the preferred locale from the headers', () => {
it('should return the preferred locale from the headers', async () => {
const headers = new Headers();

headers.set(Header.PREFERRED_LOCALE, 'en');
Expand All @@ -220,23 +220,23 @@ describe('resolvePreferredLocale', () => {
res: {} as PartialResponse,
};

jest.mocked(getHeaders).mockReturnValue(headers);
jest.mocked(getHeaders).mockResolvedValue(headers);

expect(resolvePreferredLocale(route)).toEqual('en');
await expect(resolvePreferredLocale(route)).resolves.toEqual('en');
expect(getHeaders).toHaveBeenCalledWith(route);
});

it('should return the preferred locale from the environment', () => {
it('should return the preferred locale from the environment', async () => {
process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE = 'en';

jest.mocked(getHeaders).mockReturnValue(new Headers());
jest.mocked(getHeaders).mockResolvedValue(new Headers());

expect(resolvePreferredLocale()).toEqual('en');
await expect(resolvePreferredLocale()).resolves.toEqual('en');
});

it('should return null when the preferred locale is missing', () => {
jest.mocked(getHeaders).mockReturnValue(new Headers());
it('should return null when the preferred locale is missing', async () => {
jest.mocked(getHeaders).mockResolvedValue(new Headers());

expect(resolvePreferredLocale()).toBeNull();
await expect(resolvePreferredLocale()).resolves.toBeNull();
});
});
8 changes: 4 additions & 4 deletions src/config/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export type RequestContext = {
preferredLocale?: string,
};

export function resolveRequestContext(route?: RouteContext): RequestContext {
return getRequestContext(getHeaders(route), getCookies(route));
export async function resolveRequestContext(route?: RouteContext): Promise<RequestContext> {
return getRequestContext(await getHeaders(route), await getCookies(route));
}

export function getRequestContext(headers: HeaderReader, cookies: CookieReader): RequestContext {
Expand Down Expand Up @@ -78,8 +78,8 @@ export function getRequestContext(headers: HeaderReader, cookies: CookieReader):
return context;
}

export function resolvePreferredLocale(route?: RouteContext): string|null {
return getPreferredLocale(getHeaders(route));
export async function resolvePreferredLocale(route?: RouteContext): Promise<string|null> {
return getPreferredLocale(await getHeaders(route));
}

function getPreferredLocale(headers: HeaderReader): string|null {
Expand Down
28 changes: 14 additions & 14 deletions src/headers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ describe('getHeaders', () => {
mockHeaders.mockReset();
});

it('should use next/headers if available', () => {
it('should use next/headers if available', async () => {
const get = jest.fn(() => 'test');

mockHeaders.mockReturnValue({
get: get,
});

const header = getHeaders();
const header = await getHeaders();

expect(header.get('test')).toBe('test');

Expand Down Expand Up @@ -105,14 +105,14 @@ describe('getHeaders', () => {
response: response,
};
})(),
])('should use the $name if specified', scenario => {
])('should use the $name if specified', async scenario => {
const {request, response} = scenario;

mockHeaders.mockImplementation(() => {
throw new Error('next/headers requires app router');
});

const headers = getHeaders({
const headers = await getHeaders({
req: request,
res: response,
});
Expand All @@ -128,7 +128,7 @@ describe('getCookies', () => {
mockCookies.mockReset();
});

it('should use next/headers if available', () => {
it('should use next/headers if available', async () => {
const get = jest.fn(() => ({value: 'foo'}));
const set = jest.fn();

Expand All @@ -137,7 +137,7 @@ describe('getCookies', () => {
set: set,
});

const cookies = getCookies();
const cookies = await getCookies();

expect(cookies.get('test')).toEqual({value: 'foo'});

Expand Down Expand Up @@ -303,14 +303,14 @@ describe('getCookies', () => {
response: response,
};
})(),
])('should use the $name if specified', scenario => {
])('should use the $name if specified', async scenario => {
const {request, response} = scenario;

mockCookies.mockImplementation(() => {
throw new Error('next/headers requires app router');
});

const cookies = getCookies({
const cookies = await getCookies({
req: request,
res: response,
});
Expand All @@ -319,7 +319,7 @@ describe('getCookies', () => {
expect(cookies.get('test')).toBeUndefined();
});

it('should set a cookie to NextResponse', () => {
it('should set a cookie to NextResponse', async () => {
mockCookies.mockImplementation(() => {
throw new Error('next/headers requires app router');
});
Expand All @@ -336,7 +336,7 @@ describe('getCookies', () => {
} as Partial<NextResponse['cookies']> as NextResponse['cookies'],
} satisfies PartialResponse;

const cookies = getCookies({
const cookies = await getCookies({
req: request,
res: response,
});
Expand All @@ -350,7 +350,7 @@ describe('getCookies', () => {
expect(response.cookies.set).toHaveBeenCalledWith('test', 'value', options);
});

it('should set a cookie to NextApiResponse/ServerResponse', () => {
it('should set a cookie to NextApiResponse/ServerResponse', async () => {
mockCookies.mockImplementation(() => {
throw new Error('next/headers requires app router');
});
Expand All @@ -365,7 +365,7 @@ describe('getCookies', () => {
setHeader: jest.fn(),
} satisfies PartialResponse;

const cookies = getCookies({
const cookies = await getCookies({
req: request,
res: response,
});
Expand All @@ -379,7 +379,7 @@ describe('getCookies', () => {
expect(response.setHeader).toHaveBeenCalledWith('Set-Cookie', ['test=value; Domain=example.com']);
});

it('should preserve existing cookies when setting a new cookie', () => {
it('should preserve existing cookies when setting a new cookie', async () => {
mockCookies.mockImplementation(() => {
throw new Error('next/headers requires app router');
});
Expand All @@ -404,7 +404,7 @@ describe('getCookies', () => {
setHeader: jest.fn(),
} satisfies PartialResponse;

const cookies = getCookies({
const cookies = await getCookies({
req: request,
res: response,
});
Expand Down
Loading

0 comments on commit 751afe6

Please sign in to comment.