Skip to content

Conversation

ozayr-zaviar
Copy link
Contributor

Summary

  • Converted packages\optimizely-sdk\lib\index.node.js to TS
  • Converted packages\optimizely-sdk\lib\index.browser.js to TS
  • Converted packages\optimizely-sdk\lib\index.react_native.js to TS

Test plan

  • All existing unit tests should pass
  • All existing test cases on FSC should pass

@coveralls
Copy link

coveralls commented Oct 6, 2020

Coverage Status

Coverage increased (+0.03%) to 96.662% when pulling e85f578 on uzair/entry_level_modules_to_ts into 0576e46 on master.

Copy link
Contributor

@msohailhussain msohailhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address and fix all issues.


import { LocalStoragePendingEventsDispatcher } from '@optimizely/js-sdk-event-processor';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why left blank line?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its probably a line break between module imports and internal imports


let hasRetriedEvents = false;

interface Config {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document it. we should export as well? not sure.

@@ -97,7 +104,7 @@ var createInstance = function(config) {
eventDispatcher = config.eventDispatcher;
}

config = assign(
const optimizelyConfig = assign(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why changed to optimizelyConfig. OptimizelyConfig is different than what is expected here.

@@ -110,29 +117,29 @@ var createInstance = function(config) {
logger: logger,
errorHandler: getErrorHandler(),
}
);
) as OptimizelyConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not correct.

*/
var createInstance = function(config) {
const createInstance = function (config: Config): Optimizely | null {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function(config: Config) should be without space.

const DEFAULT_EVENT_FLUSH_INTERVAL = 1000; // Unit is ms, default is 1s
const DEFAULT_EVENT_MAX_QUEUE_SIZE = 10000;

interface Config {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is being used in all index level files, we should move it to shared_types.

@@ -77,6 +79,26 @@ export interface OptimizelyVariable {
value: string;
}

export interface OptimizelyConfig {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it defined here.
Please use the right term. [OptimizelyConfig](https://github.com/optimizely/javascript-sdk/blob/master/packages/optimizely-sdk/lib/core/optimizely_config/index.js) is different.

Copy link
Contributor

@msohailhussain msohailhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please address.

@@ -149,7 +140,7 @@ var createInstance = function(config) {
}
};

var __internalResetRetryState = function() {
const __internalResetRetryState = function (): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have default indentation without space please fix at all places.

import * as enums from './utils/enums';
import { assign } from './utils/fns';
import Optimizely from './optimizely';
import configValidator from './utils/config_validator';
import * as configValidator from './utils/config_validator';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not modified in other files?

@@ -77,6 +79,39 @@ export interface OptimizelyVariable {
value: string;
}

export interface Config {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add documentation for both Config and ConfigObj

@msohailhussain msohailhussain marked this pull request as ready for review October 6, 2020 22:12
@msohailhussain msohailhussain requested a review from a team as a code owner October 6, 2020 22:12
Copy link
Contributor

@zashraf1985 zashraf1985 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. I have some concerns on the naming of certain variables and Interfaces. Secondly, as a general rule of typescript conversion. Please feel free to simplify some code to use latest javascript constructs. A lot of code can be modernized and simplified as now we are using typescript. For example: using spread operators instead of assign, using arrow functions where they make code look simpler etc.


import { LocalStoragePendingEventsDispatcher } from '@optimizely/js-sdk-event-processor';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its probably a line break between module imports and internal imports

@@ -97,7 +88,7 @@ var createInstance = function(config) {
eventDispatcher = config.eventDispatcher;
}

config = assign(
const internalConfig = assign(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are now in TS, you dont need to use assign. you can probably use spread syntax to override values.

@@ -97,7 +88,7 @@ var createInstance = function(config) {
eventDispatcher = config.eventDispatcher;
}

config = assign(
const internalConfig = assign(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variable name can be better. modifiedConfig or updatedConfig. You can try thinking of a better name but internalConfig kind of looks misleading.

@@ -110,29 +101,29 @@ var createInstance = function(config) {
logger: logger,
errorHandler: getErrorHandler(),
}
);
) as ConfigObj;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conversions as ConfigObj might not be needed. Are you sure its throwing error without this.?

@@ -83,7 +73,7 @@ var createInstance = function(config) {
config.isValidInstance = false;
}

config = assign(
const internalConfig = assign(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use spread operator here too instead of assign. Also rename internalConfig to something better

/**
* Config required to create optimizely object
*/
export interface ConfigObj {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see why you need two different configs/options but ConfigObj is not a good name. Two sets of feedback on this one.

  1. One can be inherited from the other because outer options are a subset of internal options.
  2. Names should be relevant. Config makes sense if its the only interface we use. ConfigObj does not make sense at all. And when we have two different objects with many similar properties, both Config and ConfigObj look like inappropriate choices. One choice could be SDKOptions for the outer interface and OptimizelyOptions for the internal . You can give it a thought and try to come up with better and more appropriate names.

* @param {string} config.sdkKey
* @return {Object} the Optimizely object
* @param {Config} config
* @return {Optimizely} the Optimizely object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doc comment should be updated to reflect that it can also return null.

errorHandler: getErrorHandler(),
};

const modifiedConfig = {...additionalEntities, ...config, ...optimizelyLoggers} as OptimizelyOptions;
Copy link
Contributor

@yavorona yavorona Oct 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid using as type cast here by updating isValidInstance in SDKOptions object to not be optional.

window.addEventListener(
unloadEvent,
function() {
function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend using arrow function here

errorHandler: getErrorHandler(),
};

const modifiedConfig = {...additionalEntities, ...config, ...optimizelyLoggers};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updatedConfig

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the names additionalEntities and optimizelyLoggers do not make much sense. Instead of building interim objects, you can add those directly when building the modifiedConfig or updatedConfig object. something like

const modifiedConfig = {
  clientEngine: enums.JAVASCRIPT_CLIENT_ENGINE,
  eventBatchSize: DEFAULT_EVENT_BATCH_SIZE,
  eventFlushInterval: DEFAULT_EVENT_FLUSH_INTERVAL,
  eventDispatcher: eventDispatcher,
  ...config,
  logger: logger,
  errorHandler: getErrorHandler(),
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you can probably name it optimizelyOptions instead of modifiedConfig

errorHandler: getErrorHandler(),
}
);
const additionalEntities = {
Copy link
Contributor

@msohailhussain msohailhussain Oct 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to put more appropriate name.

Copy link
Contributor

@zashraf1985 zashraf1985 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detailed comments provided in browser entry file also apply to the other two entry points. I have NOT duplicated comments to all three entry points.

errorHandler: getErrorHandler(),
};

const modifiedConfig = {...additionalEntities, ...config, ...optimizelyLoggers};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the names additionalEntities and optimizelyLoggers do not make much sense. Instead of building interim objects, you can add those directly when building the modifiedConfig or updatedConfig object. something like

const modifiedConfig = {
  clientEngine: enums.JAVASCRIPT_CLIENT_ENGINE,
  eventBatchSize: DEFAULT_EVENT_BATCH_SIZE,
  eventFlushInterval: DEFAULT_EVENT_FLUSH_INTERVAL,
  eventDispatcher: eventDispatcher,
  ...config,
  logger: logger,
  errorHandler: getErrorHandler(),
}


if (!eventProcessorConfigValidator.validateEventBatchSize(config.eventBatchSize)) {
logger.warn('Invalid eventBatchSize %s, defaulting to %s', config.eventBatchSize, DEFAULT_EVENT_BATCH_SIZE);
config.eventBatchSize = DEFAULT_EVENT_BATCH_SIZE;
modifiedConfig.eventBatchSize = DEFAULT_EVENT_BATCH_SIZE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

declaring this object above with such detail and then mutating some of the elements makes it confusing. more cleaner code could be to assign eventBatchSize to a local variable and then declare the optimizelyOptions once at the end.

}
if (!eventProcessorConfigValidator.validateEventFlushInterval(config.eventFlushInterval)) {
logger.warn(
'Invalid eventFlushInterval %s, defaulting to %s',
config.eventFlushInterval,
DEFAULT_EVENT_FLUSH_INTERVAL
);
config.eventFlushInterval = DEFAULT_EVENT_FLUSH_INTERVAL;
modifiedConfig.eventFlushInterval = DEFAULT_EVENT_FLUSH_INTERVAL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same comment about eventBatchSize applies here too


try {
if (typeof window.addEventListener === 'function') {
var unloadEvent = 'onpagehide' in window ? 'pagehide' : 'unload';
const unloadEvent = 'onpagehide' in window ? 'pagehide' : 'unload';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonblocking: Can we move these string values somewhere inside constants

Comment on lines +124 to 126
() => {
optimizely.close();
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
() => {
optimizely.close();
},
optimizely.close,

errorHandler: getErrorHandler(),
};

const modifiedConfig = {...additionalEntities, ...config, ...optimizelyLoggers};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you can probably name it optimizelyOptions instead of modifiedConfig

}

/**
* Config required to create optimizely object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably change it to Options required

Comment on lines 85 to 96
export interface SDKOptions {
datafile?: string;
errorHandler?: ErrorHandler;
eventDispatcher?: EventDispatcher;
logger?: LogHandler;
logLevel?: LogLevel;
userProfileService?: UserProfileService;
eventBatchSize?: number;
eventFlushInterval?: number;
sdkKey?: string;
isValidInstance: boolean;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should probably add one line documentation comment to each option here. This might help while autogenerating docs

Comment on lines 102 to 118
clientEngine: string;
clientVersion?: string;
errorHandler: ErrorHandler;
eventDispatcher: EventDispatcher;
isValidInstance: boolean;
datafile?: string;
// TODO[OASIS-6649]: Don't use object type
// eslint-disable-next-line @typescript-eslint/ban-types
jsonSchemaValidator?: object;
sdkKey?: string;
userProfileService?: UserProfileService | null;
UNSTABLE_conditionEvaluators?: unknown;
eventFlushInterval?: number;
eventBatchSize?: number;
datafileOptions?: DatafileOptions;
eventMaxQueueSize?: number;
logger: LogHandler;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Sort them alphabetically maybe?

Comment on lines 86 to 95
datafile?: string;
errorHandler?: ErrorHandler;
eventDispatcher?: EventDispatcher;
logger?: LogHandler;
logLevel?: LogLevel;
userProfileService?: UserProfileService;
eventBatchSize?: number;
eventFlushInterval?: number;
sdkKey?: string;
isValidInstance: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Sort them alphabetically maybe?

Copy link
Contributor

@mjc1283 mjc1283 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM, two small requests

function() {
optimizely.close();
},
optimizely.close,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this change? I think it won't work. close is not bound to optimizely, so when it is invoked it may not have the right this value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I asked uzair to change it this way to make it look simple and clean but it didn't occur to me that it will mess up with this. @ozayr-zaviar ! please change it back to what it was or an arrow function whatever makes sense.

Comment on lines 111 to 129
export interface OptimizelyOptions {
UNSTABLE_conditionEvaluators?: unknown;
clientEngine: string;
clientVersion?: string;
datafile?: string;
datafileOptions?: DatafileOptions;
errorHandler: ErrorHandler;
eventBatchSize?: number;
eventDispatcher: EventDispatcher;
eventFlushInterval?: number;
eventMaxQueueSize?: number;
isValidInstance: boolean;
// TODO[OASIS-6649]: Don't use object type
// eslint-disable-next-line @typescript-eslint/ban-types
jsonSchemaValidator?: object;
logger: LogHandler;
sdkKey?: string;
userProfileService?: UserProfileService | null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think OptimizelyOptions should be defined in lib/optimizely/index.ts.

Copy link
Contributor

@msohailhussain msohailhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Contributor

@zashraf1985 zashraf1985 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great Work @ozayr-zaviar

@mjc1283 mjc1283 merged commit 6c62080 into master Oct 19, 2020
@mjc1283 mjc1283 deleted the uzair/entry_level_modules_to_ts branch October 19, 2020 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants