diff --git a/package.json b/package.json index 579dc7e..313b1c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eppo/js-client-sdk-common", - "version": "4.15.0", + "version": "4.15.1", "description": "Common library for Eppo JavaScript SDKs (web, react native, and node)", "main": "dist/index.js", "files": [ diff --git a/src/client/eppo-precomputed-client.spec.ts b/src/client/eppo-precomputed-client.spec.ts index c512f0c..4316eb6 100644 --- a/src/client/eppo-precomputed-client.spec.ts +++ b/src/client/eppo-precomputed-client.spec.ts @@ -714,6 +714,84 @@ describe('EppoPrecomputedClient E2E test', () => { pollAfterFailedInitialization ? red : 'default', ); }); + + describe('Enhanced SDK Token with encoded subdomain', () => { + let urlsRequested: string[] = []; + const SDK_PARAM_SUFFIX = 'sdkName=js-client-sdk-common&sdkVersion=1.0.0'; + + beforeEach(() => { + urlsRequested = []; + global.fetch = jest.fn((url) => { + urlsRequested.push(url.toString()); + return Promise.resolve({ + ok: true, + status: 200, + json: () => Promise.resolve(precomputedResponse), + } as Response); + }); + }); + + it('should request from the encoded subdomain', async () => { + const client = new EppoPrecomputedClient({ + precomputedFlagStore: new MemoryOnlyConfigurationStore(), + subject, + requestParameters: { + apiKey: 'zCsQuoHJxVPp895.Y3M9ZXhwZXJpbWVudA==', // subdomain=experiment + sdkName: 'js-client-sdk-common', + sdkVersion: '1.0.0', + }, + }); + + await client.fetchPrecomputedFlags(); + + expect(urlsRequested).toHaveLength(1); + expect(urlsRequested[0]).toEqual( + 'https://experiment.fs-edge-assignment.eppo.cloud/assignments?apiKey=zCsQuoHJxVPp895.Y3M9ZXhwZXJpbWVudA%3D%3D&' + + SDK_PARAM_SUFFIX, + ); + }); + + it('should request from the default domain if the encoded subdomain is not present', async () => { + const client = new EppoPrecomputedClient({ + precomputedFlagStore: new MemoryOnlyConfigurationStore(), + subject, + requestParameters: { + apiKey: 'old style key', + sdkName: 'js-client-sdk-common', + sdkVersion: '1.0.0', + }, + }); + + await client.fetchPrecomputedFlags(); + + expect(urlsRequested).toHaveLength(1); + expect(urlsRequested[0]).toEqual( + 'https://fs-edge-assignment.eppo.cloud/assignments?apiKey=old+style+key&' + + SDK_PARAM_SUFFIX, + ); + }); + + it('should request from the provided baseUrl if present', async () => { + const client = new EppoPrecomputedClient({ + precomputedFlagStore: new MemoryOnlyConfigurationStore(), + subject, + requestParameters: { + apiKey: 'zCsQuoHJxVPp895.Y3M9ZXhwZXJpbWVudA==', // subdomain=experiment + sdkName: 'js-client-sdk-common', + sdkVersion: '1.0.0', + baseUrl: 'https://custom-base-url.com', + }, + }); + + await client.fetchPrecomputedFlags(); + + expect(urlsRequested).toHaveLength(1); + expect(urlsRequested[0]).toEqual( + 'https://custom-base-url.com/assignments?apiKey=zCsQuoHJxVPp895.Y3M9ZXhwZXJpbWVudA%3D%3D&' + + SDK_PARAM_SUFFIX, + ); + }); + }); }); describe('Obfuscated precomputed flags', () => { diff --git a/src/client/eppo-precomputed-client.ts b/src/client/eppo-precomputed-client.ts index 2c9192e..590ed87 100644 --- a/src/client/eppo-precomputed-client.ts +++ b/src/client/eppo-precomputed-client.ts @@ -32,6 +32,7 @@ import { import { getMD5Hash } from '../obfuscation'; import initPoller, { IPoller } from '../poller'; import PrecomputedRequestor from '../precomputed-requestor'; +import SdkTokenDecoder from '../sdk-token-decoder'; import { Attributes, ContextAttributes, FlagKey } from '../types'; import { validateNotBlank } from '../validation'; import { LIB_VERSION } from '../version'; @@ -164,6 +165,7 @@ export default class EppoPrecomputedClient { defaultUrl: PRECOMPUTED_BASE_URL, baseUrl, queryParams: { apiKey, sdkName, sdkVersion }, + sdkTokenDecoder: new SdkTokenDecoder(apiKey), }); const httpClient = new FetchHttpClient(apiEndpoints, requestTimeoutMs); const precomputedRequestor = new PrecomputedRequestor(