Skip to content

Commit

Permalink
feat(clerk-js): Send FAPI version through URLSearchParams (#4457)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacekradko authored Nov 7, 2024
1 parent 886e294 commit e91a2bd
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/wild-guests-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': minor
---

Now sending the Frontend API version through query string params
25 changes: 15 additions & 10 deletions packages/clerk-js/src/core/__tests__/fapiClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Clerk } from '@clerk/types';

import { SUPPORTED_FAPI_VERSION } from '../constants';
import { createFapiClient } from '../fapiClient';

const mockedClerkInstance = {
Expand Down Expand Up @@ -73,38 +74,40 @@ afterAll(() => {
describe('buildUrl(options)', () => {
it('returns the full frontend API URL', () => {
expect(fapiClient.buildUrl({ path: '/foo' }).href).toBe(
'https://clerk.example.com/v1/foo?_clerk_js_version=42.0.0',
`https://clerk.example.com/v1/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

it('returns the full frontend API URL using proxy url', () => {
expect(fapiClientWithProxy.buildUrl({ path: '/foo' }).href).toBe(`${proxyUrl}/v1/foo?_clerk_js_version=42.0.0`);
expect(fapiClientWithProxy.buildUrl({ path: '/foo' }).href).toBe(
`${proxyUrl}/v1/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

it('adds _clerk_session_id as a query parameter if provided and path does not start with client', () => {
expect(fapiClient.buildUrl({ path: '/foo', sessionId: 'sess_42' }).href).toBe(
'https://clerk.example.com/v1/foo?_clerk_js_version=42.0.0&_clerk_session_id=sess_42',
`https://clerk.example.com/v1/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0&_clerk_session_id=sess_42`,
);
expect(fapiClient.buildUrl({ path: '/client/foo', sessionId: 'sess_42' }).href).toBe(
'https://clerk.example.com/v1/client/foo?_clerk_js_version=42.0.0',
`https://clerk.example.com/v1/client/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

it('parses search params is an object with string values', () => {
expect(fapiClient.buildUrl({ path: '/foo', search: { test: '1' } }).href).toBe(
'https://clerk.example.com/v1/foo?test=1&_clerk_js_version=42.0.0',
`https://clerk.example.com/v1/foo?test=1&__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

it('parses string search params ', () => {
expect(fapiClient.buildUrl({ path: '/foo', search: 'test=2' }).href).toBe(
'https://clerk.example.com/v1/foo?test=2&_clerk_js_version=42.0.0',
`https://clerk.example.com/v1/foo?test=2&__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

it('parses search params when value contains invalid url symbols', () => {
expect(fapiClient.buildUrl({ path: '/foo', search: { bar: 'test=2' } }).href).toBe(
'https://clerk.example.com/v1/foo?bar=test%3D2&_clerk_js_version=42.0.0',
`https://clerk.example.com/v1/foo?bar=test%3D2&__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

Expand All @@ -116,7 +119,9 @@ describe('buildUrl(options)', () => {
array: ['item1', 'item2'],
},
}).href,
).toBe('https://clerk.example.com/v1/foo?array=item1&array=item2&_clerk_js_version=42.0.0');
).toBe(
`https://clerk.example.com/v1/foo?array=item1&array=item2&__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0`,
);
});

// The return value isn't as expected.
Expand Down Expand Up @@ -152,7 +157,7 @@ describe('request', () => {
});

expect(fetch).toHaveBeenCalledWith(
'https://clerk.example.com/v1/foo?_clerk_js_version=42.0.0&_clerk_session_id=deadbeef',
`https://clerk.example.com/v1/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0&_clerk_session_id=deadbeef`,
expect.objectContaining({
credentials: 'include',
method: 'GET',
Expand All @@ -167,7 +172,7 @@ describe('request', () => {
});

expect(fetch).toHaveBeenCalledWith(
`${proxyUrl}/v1/foo?_clerk_js_version=42.0.0&_clerk_session_id=deadbeef`,
`${proxyUrl}/v1/foo?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=42.0.0&_clerk_session_id=deadbeef`,
expect.objectContaining({
credentials: 'include',
method: 'GET',
Expand Down
3 changes: 3 additions & 0 deletions packages/clerk-js/src/core/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ export const SIGN_UP_MODES: Record<string, SignUpModes> = {
RESTRICTED: 'restricted',
WAITLIST: 'waitlist',
};

// This is the currently supported version of the Frontend API
export const SUPPORTED_FAPI_VERSION = '2021-02-05';
4 changes: 4 additions & 0 deletions packages/clerk-js/src/core/fapiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { runWithExponentialBackOff } from '@clerk/shared/utils';
import type { Clerk, ClerkAPIErrorJSON, ClientJSON } from '@clerk/types';

import { buildEmailAddress as buildEmailAddressUtil, buildURL as buildUrlUtil, stringifyQueryParams } from '../utils';
import { SUPPORTED_FAPI_VERSION } from './constants';
import { clerkNetworkError } from './errors';

export type HTTPMethod = 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE';
Expand Down Expand Up @@ -93,6 +94,9 @@ export function createFapiClient(clerkInstance: Clerk): FapiClient {
const searchParams = new URLSearchParams(search as any);
// the above will parse {key: ['val1','val2']} as key: 'val1,val2' and we need to recreate the array bellow

// Append supported FAPI version to the query string
searchParams.append('__clerk_api_version', SUPPORTED_FAPI_VERSION);

if (clerkInstance.version) {
searchParams.append('_clerk_js_version', clerkInstance.version);
}
Expand Down
14 changes: 7 additions & 7 deletions packages/clerk-js/src/core/resources/__tests__/Token.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SUPPORTED_FAPI_VERSION } from '../../constants';
import { createFapiClient } from '../../fapiClient';
import { mockDevClerkInstance, mockFetch, mockNetworkFailedFetch } from '../../test/fixtures';
import { BaseResource } from '../internal';
Expand All @@ -20,7 +21,7 @@ describe('Token', () => {
});

expect(global.fetch).toHaveBeenCalledWith(
'https://clerk.example.com/v1/path/to/tokens?_clerk_js_version=test-0.0.0',
`https://clerk.example.com/v1/path/to/tokens?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=test-0.0.0`,
// TODO(dimkl): omit extra params from fetch request (eg path, url) - remove expect.objectContaining
expect.objectContaining({
method: 'POST',
Expand Down Expand Up @@ -57,7 +58,7 @@ describe('Token', () => {
const token = await Token.create('/path/to/tokens');

expect(global.fetch).toHaveBeenCalledWith(
'https://clerk.example.com/v1/path/to/tokens?_clerk_js_version=test-0.0.0',
`https://clerk.example.com/v1/path/to/tokens?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=test-0.0.0`,
// TODO(dimkl): omit extra params from fetch request (eg path, url) - remove expect.objectContaining
expect.objectContaining({
method: 'POST',
Expand All @@ -77,13 +78,12 @@ describe('Token', () => {
mockNetworkFailedFetch();
BaseResource.clerk = { getFapiClient: () => createFapiClient(mockDevClerkInstance) } as any;

await expect(Token.create('/path/to/tokens')).rejects.toMatchObject({
message:
'ClerkJS: Network error at "https://clerk.example.com/v1/path/to/tokens?_clerk_js_version=test-0.0.0" - TypeError: Failed to fetch. Please try again.',
});
await expect(Token.create('/path/to/tokens')).rejects.toThrow(
`ClerkJS: Network error at "https://clerk.example.com/v1/path/to/tokens?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=test-0.0.0" - TypeError: Failed to fetch. Please try again.`,
);

expect(global.fetch).toHaveBeenCalledWith(
'https://clerk.example.com/v1/path/to/tokens?_clerk_js_version=test-0.0.0',
`https://clerk.example.com/v1/path/to/tokens?__clerk_api_version=${SUPPORTED_FAPI_VERSION}&_clerk_js_version=test-0.0.0`,
// TODO(dimkl): omit extra params from fetch request (eg path, url) - remove expect.objectContaining
expect.objectContaining({
method: 'POST',
Expand Down

0 comments on commit e91a2bd

Please sign in to comment.