From 7eb0770a561a5f6ea7e1dad6acb26f91b9ec7922 Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Tue, 10 Sep 2024 09:04:06 -0600 Subject: [PATCH] Update SDK --- package-lock.json | 48 +++++++++++++++++++------------------- package.json | 8 +++---- src/CroctProvider.test.tsx | 36 ++++++++++++++++++++++++++++ src/CroctProvider.tsx | 4 ++++ src/config/context.test.ts | 21 ++++++++++++++++- src/config/context.ts | 5 +++- src/config/http.ts | 2 +- src/middleware.test.ts | 4 ++-- src/middleware.ts | 2 +- 9 files changed, 96 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index ebc8a0d..d480e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "0.0.0-dev", "license": "MIT", "dependencies": { - "@croct/plug": "^0.15.0", - "@croct/plug-react": "^0.7.2", - "@croct/sdk": "^0.16.2", + "@croct/plug": "^0.16.0", + "@croct/plug-react": "^0.8.0", + "@croct/sdk": "^0.17.2", "cookie": "^0.6.0", "uuid": "^10.0.0" }, @@ -29,7 +29,7 @@ "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", "@types/set-cookie-parser": "^2.4.7", - "@types/uuid": "^9.0.5", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "babel-loader": "^9.1.0", @@ -2098,24 +2098,24 @@ "license": "MIT" }, "node_modules/@croct/plug": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@croct/plug/-/plug-0.15.0.tgz", - "integrity": "sha512-S7ZGZrqLqKaHQrWJw0Z2NdaYzveZn06NtBk9TLpHNYanj+a30VRgiXJmBul5bQayHn+UyzrsQYHp8qW49Oo+pA==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@croct/plug/-/plug-0.16.0.tgz", + "integrity": "sha512-oNmUj8ib02DqWIGalO5Z04RQTWOVNpc0YyH2HxlwyZQHmAY6cWiJeXkJU80pZRD3FTtC5Wadnox/6Y8AdISvlg==", "license": "MIT", "dependencies": { - "@croct/json": "^2.0.1", - "@croct/sdk": "^0.16.2", - "tslib": "^2.2.0" + "@croct/json": "^2.1.0", + "@croct/sdk": "^0.17.2", + "tslib": "^2.7.0" } }, "node_modules/@croct/plug-react": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@croct/plug-react/-/plug-react-0.7.2.tgz", - "integrity": "sha512-nmIQEglt6md4q52hJ84CtoswrhP6OFYrqjy0fTQhGA9/jRmEbMFn6zh0Za+a1XLA7nQWBV7esyquWXMqJ6ux3w==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@croct/plug-react/-/plug-react-0.8.0.tgz", + "integrity": "sha512-1mLwt4mK0GDhVAGg7HWr3Vw9sYzq4Ek9mUg16mr2pCf/j6baDboFmAetUVpRUlWd43/L20QPnJnDWlqnFAfS6Q==", "license": "MIT", "dependencies": { - "@croct/plug": "^0.15.0", - "@croct/sdk": "^0.16.2" + "@croct/plug": "^0.16.0", + "@croct/sdk": "^0.17.2" }, "engines": { "node": ">=10" @@ -2126,9 +2126,9 @@ } }, "node_modules/@croct/sdk": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@croct/sdk/-/sdk-0.16.2.tgz", - "integrity": "sha512-jNGFqv0Yg9J+HWNXhdmyZRb/op4EscsF4w/ZxOzL8Wkcjmc1AZ1+H6M4JhhaXHlUjLWYpdFU7QGRpW5pgtOtPw==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@croct/sdk/-/sdk-0.17.2.tgz", + "integrity": "sha512-iww3cT9LyuZiE59oEXJQlu8vaGl5R1yf9gU+pjSFOPSBBtQ7kVs1hJCTXCtT8vw31D91RANriUOlR8m3lmFdwA==", "license": "MIT", "dependencies": { "@croct/json": "^2.0.1", @@ -4018,9 +4018,9 @@ "license": "MIT" }, "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true, "license": "MIT" }, @@ -13455,9 +13455,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/tsutils": { diff --git a/package.json b/package.json index 82b1d88..23cf292 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,9 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "dependencies": { - "@croct/plug": "^0.15.0", - "@croct/plug-react": "^0.7.2", - "@croct/sdk": "^0.16.2", + "@croct/plug": "^0.16.0", + "@croct/plug-react": "^0.8.0", + "@croct/sdk": "^0.17.2", "cookie": "^0.6.0", "uuid": "^10.0.0" }, @@ -57,7 +57,7 @@ "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", "@types/set-cookie-parser": "^2.4.7", - "@types/uuid": "^9.0.5", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "babel-loader": "^9.1.0", diff --git a/src/CroctProvider.test.tsx b/src/CroctProvider.test.tsx index 6969a79..1a8099b 100644 --- a/src/CroctProvider.test.tsx +++ b/src/CroctProvider.test.tsx @@ -28,6 +28,8 @@ describe('', () => { delete process.env.NEXT_PUBLIC_CROCT_APP_ID; delete process.env.NEXT_PUBLIC_CROCT_DEBUG; delete process.env.NEXT_PUBLIC_CROCT_BASE_ENDPOINT_URL; + delete process.env.NEXT_PUBLIC_CROCT_DEFAULT_FETCH_TIMEOUT; + delete process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE; }); afterEach(() => { @@ -67,11 +69,15 @@ describe('', () => { process.env.NEXT_PUBLIC_CROCT_APP_ID = '00000000-0000-0000-0000-000000000000'; process.env.NEXT_PUBLIC_CROCT_DEBUG = 'true'; process.env.NEXT_PUBLIC_CROCT_BASE_ENDPOINT_URL = 'https://example.com'; + process.env.NEXT_PUBLIC_CROCT_DEFAULT_FETCH_TIMEOUT = '3000'; + process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE = 'es'; const config = { appId: '11111111-1111-1111-1111-111111111111', debug: false, baseEndpointUrl: 'https://override.com', + defaultFetchTimeout: 2000, + defaultPreferredLocale: 'en', cookie: { clientId: { name: 'custom-client-id', @@ -96,6 +102,8 @@ describe('', () => { debug: config.debug, cookie: config.cookie, baseEndpointUrl: config.baseEndpointUrl, + defaultFetchTimeout: config.defaultFetchTimeout, + defaultPreferredLocale: config.defaultPreferredLocale, }, expect.anything(), ); @@ -141,4 +149,32 @@ describe('', () => { expect.anything(), ); }); + + it('should detect the default fetch timeout from the environment', () => { + process.env.NEXT_PUBLIC_CROCT_APP_ID = '00000000-0000-0000-0000-000000000000'; + process.env.NEXT_PUBLIC_CROCT_DEFAULT_FETCH_TIMEOUT = '3000'; + + render(); + + expect(UnderlyingProvider).toHaveBeenCalledWith<[ResolvedProviderProps, any]>( + expect.objectContaining({ + defaultFetchTimeout: 3000, + }), + expect.anything(), + ); + }); + + it('should detect the default preferred locale from the environment', () => { + process.env.NEXT_PUBLIC_CROCT_APP_ID = '00000000-0000-0000-0000-000000000000'; + process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE = 'es'; + + render(); + + expect(UnderlyingProvider).toHaveBeenCalledWith<[ResolvedProviderProps, any]>( + expect.objectContaining({ + defaultPreferredLocale: process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE, + }), + expect.anything(), + ); + }); }); diff --git a/src/CroctProvider.tsx b/src/CroctProvider.tsx index e6c7f16..7103daf 100644 --- a/src/CroctProvider.tsx +++ b/src/CroctProvider.tsx @@ -8,6 +8,7 @@ import {FunctionComponent} from 'react'; import {getClientIdCookieOptions, getPreviewCookieOptions, getUserTokenCookieOptions} from '@/config/cookie'; import {getAppId} from '@/config/appId'; import {getEnvEntry, getEnvEntryFlag} from '@/config/env'; +import {getDefaultFetchTimeout} from '@/config/timeout'; type OmittedProps = 'appId' | 'disableCidMirroring' | 'cidAssignerEndpointUrl'; @@ -16,12 +17,15 @@ export type CroctProviderProps = Omit export const CroctProvider: FunctionComponent = props => { const {appId = getAppId(), ...rest} = props; + const defaultTimeout = getDefaultFetchTimeout(); return ( { const appId = '00000000-0000-0000-0000-000000000000'; + beforeEach(() => { + jest.clearAllMocks(); + delete process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE; + }); + it('should throw an error when the client ID is missing', () => { expect(() => getRequestContext(new Headers(), createCookieJar())).toThrow( 'Croct\'s Client ID is missing. Did you forget to configure Croct\'s middleware? ' @@ -66,7 +71,7 @@ describe('getRequestContext', () => { headers.set(Header.CLIENT_IP, request.clientIp); headers.set(Header.PREVIEW_TOKEN, request.previewToken); headers.set(Header.USER_TOKEN, token.toString()); - headers.set(Header.LOCALE, request.preferredLocale); + headers.set(Header.PREFERRED_LOCALE, request.preferredLocale); expect(getRequestContext(headers, createCookieJar())).toEqual(request); }); @@ -147,6 +152,18 @@ describe('getRequestContext', () => { expect(context.userToken).toEqual(newToken.toString()); }); + + it('should return the preferred locale from the environment', () => { + process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE = 'en'; + + const headers = new Headers(); + + headers.set(Header.CLIENT_ID, '00000000-0000-0000-0000-000000000000'); + + const context = getRequestContext(headers, createCookieJar()); + + expect(context.preferredLocale).toEqual('en'); + }); }); describe('resolveRequestContext', () => { @@ -166,6 +183,7 @@ describe('resolveRequestContext', () => { referrer: 'http://referrer.com', clientIp: '192.0.0.1', previewToken: 'ct.preview_token', + preferredLocale: 'en', } satisfies RequestContext; headers.set(Header.CLIENT_ID, request.clientId); @@ -174,6 +192,7 @@ describe('resolveRequestContext', () => { headers.set(Header.REFERRER, request.referrer); headers.set(Header.CLIENT_IP, request.clientIp); headers.set(Header.PREVIEW_TOKEN, request.previewToken); + headers.set(Header.PREFERRED_LOCALE, request.preferredLocale); jest.mocked(getHeaders).mockReturnValue(headers); jest.mocked(getCookies).mockReturnValue(cookies); diff --git a/src/config/context.ts b/src/config/context.ts index 8cd9638..3ac9880 100644 --- a/src/config/context.ts +++ b/src/config/context.ts @@ -2,6 +2,7 @@ import {Token} from '@croct/sdk/token'; import {Header} from '@/config/http'; import {getUserTokenCookieOptions} from '@/config/cookie'; import {CookieReader, getCookies, getHeaders, HeaderReader, RouteContext} from '@/headers'; +import {getEnvValue} from '@/config/env'; export type RequestContext = { clientId: string, @@ -32,7 +33,9 @@ export function getRequestContext(headers: HeaderReader, cookies: CookieReader): clientId: clientId, }; - const locale = headers.get(Header.LOCALE); + const locale = headers.get(Header.PREFERRED_LOCALE) + ?? getEnvValue(process.env.NEXT_PUBLIC_CROCT_DEFAULT_PREFERRED_LOCALE) + ?? null; if (locale !== null) { context.preferredLocale = locale; diff --git a/src/config/http.ts b/src/config/http.ts index 5716282..7374c00 100644 --- a/src/config/http.ts +++ b/src/config/http.ts @@ -10,5 +10,5 @@ export enum Header { USER_TOKEN = 'x-user-token', PREVIEW_TOKEN = 'x-preview-token', REQUEST_URI = 'x-request-uri', - LOCALE = 'x-locale', + PREFERRED_LOCALE = 'x-preferred-locale', } diff --git a/src/middleware.test.ts b/src/middleware.test.ts index 869143b..61064e7 100644 --- a/src/middleware.test.ts +++ b/src/middleware.test.ts @@ -261,7 +261,7 @@ describe('middleware', () => { expect(nextMiddleware).toHaveBeenCalledWith(request, fetchEvent); - expect(request.headers.get(Header.LOCALE)).toBe(locale); + expect(request.headers.get(Header.PREFERRED_LOCALE)).toBe(locale); }); it('should not forward the locale through the request headers if it is empty', async () => { @@ -282,7 +282,7 @@ describe('middleware', () => { expect(nextMiddleware).toHaveBeenCalledWith(request, fetchEvent); - expect(request.headers.get(Header.LOCALE)).toBeNull(); + expect(request.headers.get(Header.PREFERRED_LOCALE)).toBeNull(); }); it('should forward the URL through the request headers', async () => { diff --git a/src/middleware.ts b/src/middleware.ts index 8c11719..6fd0714 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -72,7 +72,7 @@ export function withCroct(...args: CroctMiddlewareParams): NextMiddleware { headers.set(Header.CLIENT_ID, clientId); if (locale !== '') { - headers.set(Header.LOCALE, locale); + headers.set(Header.PREFERRED_LOCALE, locale); } if (request.ip !== undefined) {