Skip to content

Commit

Permalink
Do not mutate endpoints, rename to baseUrl
Browse files Browse the repository at this point in the history
  • Loading branch information
rmi22186 committed Nov 8, 2023
1 parent e939379 commit 88a9b33
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 70 deletions.
6 changes: 3 additions & 3 deletions src/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export default function APIClient(
const self = this;
this.queueEventForBatchUpload = function(event: SDKEvent) {
if (!this.uploader) {
const millis: string = mpInstance._Helpers.getFeatureFlag(
const millis: number = parseNumber(mpInstance._Helpers.getFeatureFlag(
Constants.FeatureFlags.EventBatchingIntervalMillis
);
this.uploader = new BatchUploader(mpInstance, parseNumber(millis));
));
this.uploader = new BatchUploader(mpInstance, millis);
}
this.uploader.queueEvent(event);

Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const Constants = {
integrationDelayTimeout: 5000, // Milliseconds for forcing the integration delay to un-suspend event queueing due to integration partner errors
maxCookieSize: 3000, // Number of bytes for cookie size to not exceed
aliasMaxWindow: 90, // Max age of Alias request startTime, in days
uploadInterval: '0', // Maximum milliseconds in between batch uploads, below 500 will mean immediate upload
uploadInterval: '0', // Maximum milliseconds in between batch uploads, below 500 will mean immediate upload. This is a string because that is how the server returns it
},
DefaultUrls: {
v1SecureServiceUrl: 'jssdks.mparticle.com/v1/JS/',
Expand Down
1 change: 0 additions & 1 deletion src/mockBatchCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export default class _BatchValidator {
createServiceUrl: mockFunction,
parseNumber: mockFunction,
isObject: mockFunction,
getFeatureFlag: mockFunction,
returnConvertedBoolean: mockFunction,
Validators: null,
},
Expand Down
2 changes: 1 addition & 1 deletion src/sdkRuntimeModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export interface SDKHelpersApi {
parseNumber?(value: string | number): number;
generateUniqueId();
generateHash?(value: string): string;
getFeatureFlag(feature: string); // TODO: Feature Constants should be converted to enum
getFeatureFlag?(feature: string); // TODO: Feature Constants should be converted to enum
isDelayedByIntegration?(
delayedIntegrations: Dictionary<boolean>,
timeoutStart: number,
Expand Down
133 changes: 78 additions & 55 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ interface WrapperSDKInfo {
isInfoSet: boolean;
}

export interface IFeatureFlags {
reportBatching?: string;
eventBatchingIntervalMillis?: string;
offlineStorage?: string;
directURLRouting?: boolean;
}

// Temporary Interface until Store can be refactored as a class
export interface IStore {
isEnabled: boolean;
Expand Down Expand Up @@ -161,7 +168,7 @@ export default function Store(
this: IStore,
config: SDKInitConfig,
mpInstance: MParticleWebSDK,
apiKey: string,
apiKey: string
) {
const defaultStore: Partial<IStore> = {
isEnabled: true,
Expand Down Expand Up @@ -242,7 +249,7 @@ export default function Store(
this.SDKConfig.flags,
apiKey
);
console.log(endpoints);

for (const endpointKey in endpoints) {
this.SDKConfig[endpointKey] = endpoints[endpointKey];
}
Expand All @@ -255,7 +262,8 @@ export default function Store(

this.SDKConfig.kits = config.kits || {};

this.SDKConfig.sideloadedKits = config.sideloadedKits || [];
this.SDKConfig.sideloadedKits =
config.sideloadedKits || [];

if (config.hasOwnProperty('isIOS')) {
this.SDKConfig.isIOS = config.isIOS;
Expand All @@ -267,15 +275,17 @@ export default function Store(
}

if (config.hasOwnProperty('useCookieStorage')) {
this.SDKConfig.useCookieStorage = config.useCookieStorage;
this.SDKConfig.useCookieStorage =
config.useCookieStorage;
} else {
this.SDKConfig.useCookieStorage = false;
}

if (config.hasOwnProperty('maxProducts')) {
this.SDKConfig.maxProducts = config.maxProducts;
} else {
this.SDKConfig.maxProducts = Constants.DefaultConfig.maxProducts;
this.SDKConfig.maxProducts =
Constants.DefaultConfig.maxProducts;
}

if (config.hasOwnProperty('maxCookieSize')) {
Expand All @@ -302,13 +312,19 @@ export default function Store(
}

if (config.hasOwnProperty('identifyRequest')) {
this.SDKConfig.identifyRequest = config.identifyRequest;
this.SDKConfig.identifyRequest =
config.identifyRequest;
}

if (config.hasOwnProperty('identityCallback')) {
var callback = config.identityCallback;
if (mpInstance._Helpers.Validators.isFunction(callback)) {
this.SDKConfig.identityCallback = config.identityCallback;
if (
mpInstance._Helpers.Validators.isFunction(
callback
)
) {
this.SDKConfig.identityCallback =
config.identityCallback;
} else {
mpInstance.Logger.warning(
'The optional callback must be a function. You tried entering a(n) ' +
Expand All @@ -327,7 +343,8 @@ export default function Store(
}

if (config.hasOwnProperty('sessionTimeout')) {
this.SDKConfig.sessionTimeout = config.sessionTimeout;
this.SDKConfig.sessionTimeout =
config.sessionTimeout;
}

if (config.hasOwnProperty('dataPlan')) {
Expand All @@ -339,7 +356,8 @@ export default function Store(
const dataPlan = config.dataPlan as DataPlanConfig;
if (dataPlan.planId) {
if (isDataPlanSlug(dataPlan.planId)) {
this.SDKConfig.dataPlan.PlanId = dataPlan.planId;
this.SDKConfig.dataPlan.PlanId =
dataPlan.planId;
} else {
mpInstance.Logger.error(
'Your data plan id must be a string and match the data plan slug format (i.e. under_case_slug)'
Expand All @@ -349,7 +367,8 @@ export default function Store(

if (dataPlan.planVersion) {
if (isNumber(dataPlan.planVersion)) {
this.SDKConfig.dataPlan.PlanVersion = dataPlan.planVersion;
this.SDKConfig.dataPlan.PlanVersion =
dataPlan.planVersion;
} else {
mpInstance.Logger.error(
'Your data plan version must be a number'
Expand Down Expand Up @@ -377,7 +396,8 @@ export default function Store(
}

if (config.hasOwnProperty('aliasMaxWindow')) {
this.SDKConfig.aliasMaxWindow = config.aliasMaxWindow;
this.SDKConfig.aliasMaxWindow =
config.aliasMaxWindow;
} else {
this.SDKConfig.aliasMaxWindow =
Constants.DefaultConfig.aliasMaxWindow;
Expand All @@ -386,11 +406,19 @@ export default function Store(
if (config.hasOwnProperty('dataPlanOptions')) {
const dataPlanOptions = config.dataPlanOptions;
if (
!dataPlanOptions.hasOwnProperty('dataPlanVersion') ||
!dataPlanOptions.hasOwnProperty('blockUserAttributes') ||
!dataPlanOptions.hasOwnProperty('blockEventAttributes') ||
!dataPlanOptions.hasOwnProperty(
'dataPlanVersion'
) ||
!dataPlanOptions.hasOwnProperty(
'blockUserAttributes'
) ||
!dataPlanOptions.hasOwnProperty(
'blockEventAttributes'
) ||
!dataPlanOptions.hasOwnProperty('blockEvents') ||
!dataPlanOptions.hasOwnProperty('blockUserIdentities')
!dataPlanOptions.hasOwnProperty(
'blockUserIdentities'
)
) {
mpInstance.Logger.error(
'Ensure your config.dataPlanOptions object has the following keys: a "dataPlanVersion" object, and "blockUserAttributes", "blockEventAttributes", "blockEvents", "blockUserIdentities" booleans'
Expand All @@ -400,7 +428,8 @@ export default function Store(

if (config.hasOwnProperty('onCreateBatch')) {
if (typeof config.onCreateBatch === 'function') {
this.SDKConfig.onCreateBatch = config.onCreateBatch;
this.SDKConfig.onCreateBatch =
config.onCreateBatch;
} else {
mpInstance.Logger.error(
'config.onCreateBatch must be a function'
Expand All @@ -412,13 +441,6 @@ export default function Store(
}
}

export interface IFeatureFlags {
reportBatching?: string;
eventBatchingIntervalMillis?: string;
offlineStorage?: string;
directURLRouting?: boolean;
}

export function processFlags(
config: SDKInitConfig,
SDKConfig: SDKConfig
Expand Down Expand Up @@ -449,75 +471,76 @@ export function processFlags(
export function processEndpoints(
config: SDKInitConfig,
flags: IFeatureFlags,
apiKey: string
apiKey?: string
): Dictionary<string> {
// an API key is not present in a webview only mode. In this case, no endpoints are needed
if (!apiKey) {
return {};
}

// Set default endpoints
let endpoints: Dictionary = JSON.parse(
JSON.stringify(Constants.DefaultUrls)
);
let endpoints: Dictionary<string>;

// When direct URL routing is false, update endpoints based custom urls
// passed to the config
if (!flags.directURLRouting) {
return processNonDirectEndpoints(endpoints, config);
if (flags.directURLRouting) {
return processDirectUrlEndpoints(config, apiKey);
} else {
return processDirectUrlEndpoints(endpoints, config, apiKey);
return processNonDirectEndpoints(config);
}
}

function processNonDirectEndpoints(
endpoints: Dictionary,
config: SDKInitConfig
): Dictionary {
for (let endpoint in endpoints) {
if (config.hasOwnProperty(endpoint)) {
endpoints[endpoint] = config[endpoint];
}
function processNonDirectEndpoints(config: SDKInitConfig): Dictionary<string> {
let defaultBaseUrls: Dictionary<string> = Constants.DefaultUrls;
let newBaseUrls: Dictionary<string> = {};

for (let baseUrlKey in defaultBaseUrls) {
newBaseUrls[baseUrlKey] = config[baseUrlKey] || defaultBaseUrls[baseUrlKey];
}
return endpoints;

return newBaseUrls;
}

function processDirectUrlEndpoints(
endpoints: Dictionary,
config: SDKInitConfig,
apiKey: string
): Dictionary {
let defaultBaseUrls = Constants.DefaultUrls;
let directBaseUrls: Dictionary<string> = {};
// When Direct URL Routing is true, we create a new set of endpoints that
// include the silo in the urls. mParticle API keys are prefixed with the
// silo and a hyphen (ex. "us1-", "us2-", "eu1-"). us1 was the first silo,
// and before other silos existed, there were no prefixes and all apiKeys
// were us1. As such, if we split on a '-' and the resulting array length
// is 1, then it is an older APIkey that should route to us1.
const splitKey: Array<string> = apiKey.split('-');
let routingPrefix: string;

// when splitKey.length is greater than 1, then splitKey[0] will be
// When splitKey.length is greater than 1, then splitKey[0] will be
// us1, us2, eu1, au1, or st1, etc as new silos are added
routingPrefix = splitKey.length <= 1 ? 'us1' : splitKey[0];
const DEFAULT_SILO = 'us1';
const splitKey: Array<string> = apiKey.split('-');
const routingPrefix: string =
splitKey.length <= 1 ? DEFAULT_SILO : splitKey[0];

for (let endpointKey in endpoints) {
for (let baseUrlKey in defaultBaseUrls) {
// Any custom endpoints passed to config will take priority over direct
// mapping to the silo
if (config.hasOwnProperty(endpointKey)) {
endpoints[endpointKey] = config[endpointKey];
if (baseUrlKey === 'configUrl') {
directBaseUrls[baseUrlKey] =
config[baseUrlKey] || defaultBaseUrls[baseUrlKey];
continue;
}

if (config.hasOwnProperty(baseUrlKey)) {
directBaseUrls[baseUrlKey] = config[baseUrlKey];
} else {
if (endpointKey === 'configUrl') {
continue;
}
const urlparts = endpoints[endpointKey].split('.');
const urlparts = defaultBaseUrls[baseUrlKey].split('.');

endpoints[endpointKey] = [
directBaseUrls[baseUrlKey] = [
urlparts[0],
routingPrefix,
...urlparts.slice(1),
].join('.');
}
}

return endpoints;
return directBaseUrls;
}
9 changes: 5 additions & 4 deletions test/src/tests-core-sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,6 @@ describe('core SDK', function() {

mockServer.requests = [];
mParticle.init(apiKey, window.mParticle.config);

window.mParticle.logEvent('Test Event');

fetchMock.lastOptions().body.should.be.ok()
Expand Down Expand Up @@ -1136,7 +1135,7 @@ describe('core SDK', function() {
});

describe('pod feature flag', function() {
const endpoints = JSON.parse(JSON.stringify(Constants.DefaultUrls));
const endpoints = Constants.DefaultUrls;
// set up URLs object for each silo
let URLs = {
us1: {},
Expand All @@ -1149,11 +1148,13 @@ describe('core SDK', function() {
// The below function builds out the above URLs object to have silo-specific urls, ie:
// URLs.us1.aliasUrl = 'jssdks.us1.mparticle.com/v1/identity/';
// URLs.us2.aliasUrl = 'jssdks.us2.mparticle.com/v1/identity/';
// URLs.us1.configUrl = 'jssdkcdns.us1.mparticle.com/JS/v2/';
// URLs.us2.configUrl = 'jssdkcdns.us2.mparticle.com/JS/v2/';
// etc, etc for each silo, and each endpoint
Object.keys(URLs).forEach((key) => {
for (let endpointKey in endpoints) {
if (endpointKey === 'configUrl') {
// Do not route config url to silo, use the default instead
URLs[key][endpointKey] = endpoints[endpointKey];
}
const endpointParts = endpoints[endpointKey].split('.');
URLs[key][endpointKey] = [endpointParts[0], key, ...endpointParts.slice(1)].join('.')
}
Expand Down
6 changes: 1 addition & 5 deletions test/src/tests-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,7 @@ describe('Store', () => {
const featureFlags = { directURLRouting: false };

it('should return default endpoints if no endpoints are passed', () => {
const endpoints: Dictionary = JSON.parse(
JSON.stringify(Constants.DefaultUrls)
);

const endpoints: Dictionary = Constants.DefaultUrls;
const result = processEndpoints(
{} as unknown as SDKInitConfig,
featureFlags as unknown as IFeatureFlags,
Expand Down Expand Up @@ -270,7 +267,6 @@ describe('Store', () => {
v1SecureServiceUrl: "jssdks.mparticle.com/v1/JS/",
v2SecureServiceUrl: "jssdks.mparticle.com/v2/JS/",
}
debugger

expect(result).to.deep.equal(expectedResult)
});
Expand Down

0 comments on commit 88a9b33

Please sign in to comment.