Skip to content

Commit e0dd097

Browse files
Merge branch 'master' into farhan-anjum/FSSDK-11073-GHA-publish-to-GPR
2 parents e694f39 + aaf83d7 commit e0dd097

19 files changed

+2287
-760
lines changed

lib/core/decision_service/index.spec.ts

Lines changed: 1740 additions & 0 deletions
Large diffs are not rendered by default.

lib/core/decision_service/index.tests.js

Lines changed: 26 additions & 694 deletions
Large diffs are not rendered by default.

lib/core/decision_service/index.ts

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2017-2022, 2024, Optimizely
2+
* Copyright 2017-2022, 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -110,7 +110,7 @@ export interface DecisionObj {
110110
}
111111

112112
interface DecisionServiceOptions {
113-
userProfileService: UserProfileService | null;
113+
userProfileService?: UserProfileService;
114114
logger?: LoggerFacade;
115115
UNSTABLE_conditionEvaluators: unknown;
116116
}
@@ -143,13 +143,13 @@ export class DecisionService {
143143
private logger?: LoggerFacade;
144144
private audienceEvaluator: AudienceEvaluator;
145145
private forcedVariationMap: { [key: string]: { [id: string]: string } };
146-
private userProfileService: UserProfileService | null;
146+
private userProfileService?: UserProfileService;
147147

148148
constructor(options: DecisionServiceOptions) {
149149
this.logger = options.logger;
150150
this.audienceEvaluator = createAudienceEvaluator(options.UNSTABLE_conditionEvaluators, this.logger);
151151
this.forcedVariationMap = {};
152-
this.userProfileService = options.userProfileService || null;
152+
this.userProfileService = options.userProfileService;
153153
}
154154

155155
/**
@@ -170,18 +170,22 @@ export class DecisionService {
170170
): DecisionResponse<string | null> {
171171
const userId = user.getUserId();
172172
const attributes = user.getAttributes();
173+
173174
// by default, the bucketing ID should be the user ID
174175
const bucketingId = this.getBucketingId(userId, attributes);
175-
const decideReasons: (string | number)[][] = [];
176176
const experimentKey = experiment.key;
177-
if (!this.checkIfExperimentIsActive(configObj, experimentKey)) {
177+
178+
const decideReasons: (string | number)[][] = [];
179+
180+
if (!isActive(configObj, experimentKey)) {
178181
this.logger?.info(EXPERIMENT_NOT_RUNNING, experimentKey);
179182
decideReasons.push([EXPERIMENT_NOT_RUNNING, experimentKey]);
180183
return {
181184
result: null,
182185
reasons: decideReasons,
183186
};
184187
}
188+
185189
const decisionForcedVariation = this.getForcedVariation(configObj, experimentKey, userId);
186190
decideReasons.push(...decisionForcedVariation.reasons);
187191
const forcedVariationKey = decisionForcedVariation.result;
@@ -192,6 +196,7 @@ export class DecisionService {
192196
reasons: decideReasons,
193197
};
194198
}
199+
195200
const decisionWhitelistedVariation = this.getWhitelistedVariation(experiment, userId);
196201
decideReasons.push(...decisionWhitelistedVariation.reasons);
197202
let variation = decisionWhitelistedVariation.result;
@@ -202,7 +207,6 @@ export class DecisionService {
202207
};
203208
}
204209

205-
206210
// check for sticky bucketing if decide options do not include shouldIgnoreUPS
207211
if (!shouldIgnoreUPS) {
208212
variation = this.getStoredVariation(configObj, experiment, userId, userProfileTracker.userProfile);
@@ -349,16 +353,6 @@ export class DecisionService {
349353
return { ...userProfile.experiment_bucket_map, ...attributeExperimentBucketMap as any };
350354
}
351355

352-
/**
353-
* Checks whether the experiment is running
354-
* @param {ProjectConfig} configObj The parsed project configuration object
355-
* @param {string} experimentKey Key of experiment being validated
356-
* @return {boolean} True if experiment is running
357-
*/
358-
private checkIfExperimentIsActive(configObj: ProjectConfig, experimentKey: string): boolean {
359-
return isActive(configObj, experimentKey);
360-
}
361-
362356
/**
363357
* Checks if user is whitelisted into any variation and return that variation if so
364358
* @param {Experiment} experiment
@@ -621,7 +615,7 @@ export class DecisionService {
621615
isProfileUpdated: false,
622616
userProfile: null,
623617
}
624-
const shouldIgnoreUPS = options[OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE];
618+
const shouldIgnoreUPS = !!options[OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE];
625619

626620
if(!shouldIgnoreUPS) {
627621
userProfileTracker.userProfile = this.resolveExperimentBucketMap(userId, attributes);
@@ -661,10 +655,10 @@ export class DecisionService {
661655
}
662656

663657
if(!shouldIgnoreUPS) {
664-
this.saveUserProfile(userId, userProfileTracker)
658+
this.saveUserProfile(userId, userProfileTracker);
665659
}
666660

667-
return decisions
661+
return decisions;
668662

669663
}
670664

@@ -968,7 +962,7 @@ export class DecisionService {
968962
* @param {string} experimentKey Key representing the experiment id
969963
* @throws If the user id is not valid or not in the forced variation map
970964
*/
971-
removeForcedVariation(userId: string, experimentId: string, experimentKey: string): void {
965+
private removeForcedVariation(userId: string, experimentId: string, experimentKey: string): void {
972966
if (!userId) {
973967
throw new OptimizelyError(INVALID_USER_ID);
974968
}
@@ -1176,7 +1170,7 @@ export class DecisionService {
11761170
}
11771171
}
11781172

1179-
getVariationFromExperimentRule(
1173+
private getVariationFromExperimentRule(
11801174
configObj: ProjectConfig,
11811175
flagKey: string,
11821176
rule: Experiment,
@@ -1207,7 +1201,7 @@ export class DecisionService {
12071201
};
12081202
}
12091203

1210-
getVariationFromDeliveryRule(
1204+
private getVariationFromDeliveryRule(
12111205
configObj: ProjectConfig,
12121206
flagKey: string,
12131207
rules: Experiment[],

lib/entrypoint.test-d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ export type Entrypoint = {
6868
eventDispatcher: EventDispatcher;
6969
getSendBeaconEventDispatcher: () => EventDispatcher;
7070
createForwardingEventProcessor: (eventDispatcher?: EventDispatcher) => OpaqueEventProcessor;
71-
createBatchEventProcessor: (options: BatchEventProcessorOptions) => OpaqueEventProcessor;
71+
createBatchEventProcessor: (options?: BatchEventProcessorOptions) => OpaqueEventProcessor;
7272

7373
// odp manager related exports
74-
createOdpManager: (options: OdpManagerOptions) => OpaqueOdpManager;
74+
createOdpManager: (options?: OdpManagerOptions) => OpaqueOdpManager;
7575

7676
// vuid manager related exports
77-
createVuidManager: (options: VuidManagerOptions) => OpaqueVuidManager;
77+
createVuidManager: (options?: VuidManagerOptions) => OpaqueVuidManager;
7878

7979
// logger related exports
8080
LogLevel: typeof LogLevel;

lib/error/optimizly_error.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export class OptimizelyError extends Error {
2525
this.name = 'OptimizelyError';
2626
this.baseMessage = baseMessage;
2727
this.params = params;
28+
29+
// this is needed cause instanceof doesn't work for
30+
// custom Errors when TS is compiled to es5
31+
Object.setPrototypeOf(this, OptimizelyError.prototype);
2832
}
2933

3034
getMessage(resolver?: MessageResolver): string {

lib/event_processor/event_processor_factory.browser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024, Optimizely
2+
* Copyright 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ export const createForwardingEventProcessor = (
3939
const identity = <T>(v: T): T => v;
4040

4141
export const createBatchEventProcessor = (
42-
options: BatchEventProcessorOptions
42+
options: BatchEventProcessorOptions = {}
4343
): OpaqueEventProcessor => {
4444
const localStorageCache = new LocalStorageCache<EventWithId>();
4545
const eventStore = new SyncPrefixCache<EventWithId, EventWithId>(

lib/event_processor/event_processor_factory.node.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024, Optimizely
2+
* Copyright 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@ export const createForwardingEventProcessor = (
3232
};
3333

3434
export const createBatchEventProcessor = (
35-
options: BatchEventProcessorOptions
35+
options: BatchEventProcessorOptions = {}
3636
): OpaqueEventProcessor => {
3737
const eventStore = options.eventStore ? getPrefixEventStore(options.eventStore) : undefined;
3838

lib/event_processor/event_processor_factory.react_native.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024, Optimizely
2+
* Copyright 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ const getDefaultEventStore = () => {
5353
}
5454

5555
export const createBatchEventProcessor = (
56-
options: BatchEventProcessorOptions
56+
options: BatchEventProcessorOptions = {}
5757
): OpaqueEventProcessor => {
5858
const eventStore = options.eventStore ? getPrefixEventStore(options.eventStore) : getDefaultEventStore();
5959

lib/odp/odp_manager_factory.browser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024, Optimizely
2+
* Copyright 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import { getOpaqueOdpManager, OdpManagerOptions, OpaqueOdpManager } from './odp_
2121

2222
export const BROWSER_DEFAULT_API_TIMEOUT = 10_000;
2323

24-
export const createOdpManager = (options: OdpManagerOptions): OpaqueOdpManager => {
24+
export const createOdpManager = (options: OdpManagerOptions = {}): OpaqueOdpManager => {
2525
const segmentRequestHandler = new BrowserRequestHandler({
2626
timeout: options.segmentsApiTimeout || BROWSER_DEFAULT_API_TIMEOUT,
2727
});

lib/odp/odp_manager_factory.node.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024, Optimizely
2+
* Copyright 2024-2025, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ export const NODE_DEFAULT_API_TIMEOUT = 10_000;
2323
export const NODE_DEFAULT_BATCH_SIZE = 10;
2424
export const NODE_DEFAULT_FLUSH_INTERVAL = 1000;
2525

26-
export const createOdpManager = (options: OdpManagerOptions): OpaqueOdpManager => {
26+
export const createOdpManager = (options: OdpManagerOptions = {}): OpaqueOdpManager => {
2727
const segmentRequestHandler = new NodeRequestHandler({
2828
timeout: options.segmentsApiTimeout || NODE_DEFAULT_API_TIMEOUT,
2929
});

0 commit comments

Comments
 (0)