Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@eppo/js-client-sdk-common",
"version": "4.11.0",
"version": "4.12.0",
"description": "Common library for Eppo JavaScript SDKs (web, react native, and node)",
"main": "dist/index.js",
"files": [
Expand Down
5 changes: 5 additions & 0 deletions src/api-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
UFC_ENDPOINT,
BANDIT_ENDPOINT,
PRECOMPUTED_FLAGS_ENDPOINT,
FLAG_OVERRIDES_KEY_VALIDATION_URL,
} from './constants';
import { IQueryParams, IQueryParamsWithSubject } from './http-client';

Expand Down Expand Up @@ -36,4 +37,8 @@ export default class ApiEndpoints {
precomputedFlagsEndpoint(): URL {
return this.endpoint(PRECOMPUTED_FLAGS_ENDPOINT);
}

flagOverridesKeyValidationEndpoint(): URL {
return this.endpoint(FLAG_OVERRIDES_KEY_VALIDATION_URL);
}
}
5 changes: 3 additions & 2 deletions src/client/eppo-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ export default class EppoClient {
return undefined;
}
const payload: OverridePayload = this.overrideValidator.parseOverridePayload(overridePayload);
await this.overrideValidator.validateKey(payload.browserExtensionKey);
const baseUrl = this.configurationRequestParameters?.baseUrl;
await this.overrideValidator.validateKey(payload.browserExtensionKey, baseUrl);
return payload.overrides;
}

Expand All @@ -222,7 +223,7 @@ export default class EppoClient {
* to it without affecting the original EppoClient singleton. Useful for
* applying overrides in a shared Node instance, such as a web server.
*/
withOverrides(overrides: Record<FlagKey, Variation>): EppoClient {
withOverrides(overrides: Record<FlagKey, Variation> | undefined): EppoClient {
if (overrides && Object.keys(overrides).length) {
const copy = shallowClone(this);
copy.overrideStore = new MemoryOnlyConfigurationStore<Variation>();
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const DEFAULT_POLL_CONFIG_REQUEST_RETRIES = 7;
export const BASE_URL = 'https://fscdn.eppo.cloud/api';
export const UFC_ENDPOINT = '/flag-config/v1/config';
export const BANDIT_ENDPOINT = '/flag-config/v1/bandits';
export const FLAG_OVERRIDES_KEY_VALIDATION_URL = '/flag-overrides/v1/validate-key';
export const PRECOMPUTED_BASE_URL = 'https://fs-edge-assignment.eppo.cloud';
export const PRECOMPUTED_FLAGS_ENDPOINT = '/assignments';
export const SESSION_ASSIGNMENT_CONFIG_LOADED = 'eppo-session-assignment-config-loaded';
Expand Down
14 changes: 9 additions & 5 deletions src/override-validator.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import ApiEndpoints from './api-endpoints';
import { TLRUCache } from './cache/tlru-cache';
import { Variation } from './interfaces';
import { FlagKey } from './types';

const FIVE_MINUTES_IN_MS = 5 * 3600 * 1000;
const KEY_VALIDATION_URL = 'https://eppo.cloud/api/flag-overrides/v1/validate-key';

export interface OverridePayload {
browserExtensionKey: string;
overrides: Record<FlagKey, Variation>;
}

export const sendValidationRequest = async (browserExtensionKey: string) => {
const response = await fetch(KEY_VALIDATION_URL, {
export const sendValidationRequest = async (
browserExtensionKey: string,
validationEndpoint: string,
) => {
const response = await fetch(validationEndpoint, {
method: 'POST',
body: JSON.stringify({
key: browserExtensionKey,
Expand Down Expand Up @@ -63,11 +66,12 @@ export class OverrideValidator {
}
}

async validateKey(browserExtensionKey: string) {
async validateKey(browserExtensionKey: string, baseUrl: string | undefined) {
if (this.validKeyCache.get(browserExtensionKey) === 'true') {
return true;
}
await sendValidationRequest(browserExtensionKey);
const endpoint = new ApiEndpoints({ baseUrl }).flagOverridesKeyValidationEndpoint().toString();
await sendValidationRequest(browserExtensionKey, endpoint);
this.validKeyCache.set(browserExtensionKey, 'true');
}
}
Loading