Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add error handling to all public apis #1907

Merged
merged 14 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const LOAD_CONFIGURATION = 'LoadConfiguration';
const EVENT_REPOSITORY = 'EventRepository';
const EXTERNAL_SRC_LOADER = 'ExternalSrcLoader';
const HTTP_CLIENT = 'HttpClient';
const RS_APP = 'RudderStackApplication';
const RSA = 'RudderStackAnalytics';
const ANALYTICS_CORE = 'AnalyticsCore';

export {
Expand All @@ -28,6 +28,6 @@ export {
EVENT_REPOSITORY,
EXTERNAL_SRC_LOADER,
HTTP_CLIENT,
RS_APP,
RSA,
ANALYTICS_CORE,
};
2 changes: 1 addition & 1 deletion packages/analytics-js-common/src/types/ApiObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export type ApiObject = {
| ApiObject
| null
| Date
| (string | number | boolean | null | Date | ApiObject)[]
| (string | number | boolean | null | Date | ApiObject | undefined)[]
| undefined;
};
4 changes: 2 additions & 2 deletions packages/analytics-js-common/src/types/IRudderAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export interface IRudderAnalytics<T = any> {
/**
* Get the instance of Analytics that is set as default
*/
getAnalyticsInstance(writeKey?: string): T;
getAnalyticsInstance(writeKey?: string): T | undefined;

/**
* Trigger load event in buffer queue if exists
Expand Down Expand Up @@ -188,7 +188,7 @@ export interface IRudderAnalytics<T = any> {
/**
* To fetch the current sessionId
*/
getSessionId(): Nullable<number>;
getSessionId(): Nullable<number> | undefined;

/**
* To provide consent
Expand Down
201 changes: 114 additions & 87 deletions packages/analytics-js-common/src/utilities/eventMethodOverloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { isObjectLiteralAndNotNull, mergeDeepRight } from './object';
import { isDefined, isDefinedAndNotNull, isFunction, isNull, isString } from './checks';
import { tryStringify } from './string';
import type { IdentifyTraits } from '../types/traits';
import { getSanitizedValue } from './json';

export type PageCallOptions = {
category?: string;
Expand Down Expand Up @@ -56,74 +57,80 @@ const pageArgumentsToCallOptions = (
options?: Nullable<ApiOptions> | ApiCallback,
callback?: ApiCallback,
): PageCallOptions => {
const sanitizedCategory = getSanitizedValue(category);
const sanitizedName = getSanitizedValue(name);
const sanitizedProperties = getSanitizedValue(properties);
const sanitizedOptions = getSanitizedValue(options);
const sanitizedCallback = getSanitizedValue(callback);

const payload: PageCallOptions = {
category: category as string,
name: name as string,
properties: properties as Nullable<ApiObject>,
options: options as Nullable<ApiOptions>,
category: sanitizedCategory as string,
name: sanitizedName as string,
properties: sanitizedProperties as Nullable<ApiObject>,
options: sanitizedOptions as Nullable<ApiOptions>,
callback: undefined,
};

if (isFunction(callback)) {
payload.callback = callback;
if (isFunction(sanitizedCallback)) {
payload.callback = sanitizedCallback;
}

if (isFunction(options)) {
payload.category = category as string;
payload.name = name as string;
payload.properties = properties as Nullable<ApiObject>;
if (isFunction(sanitizedOptions)) {
payload.category = sanitizedCategory as string;
payload.name = sanitizedName as string;
payload.properties = sanitizedProperties as Nullable<ApiObject>;
payload.options = undefined;
payload.callback = options;
payload.callback = sanitizedOptions;
}

if (isFunction(properties)) {
payload.category = category as string;
payload.name = name as string;
if (isFunction(sanitizedProperties)) {
payload.category = sanitizedCategory as string;
payload.name = sanitizedName as string;
payload.properties = undefined;
payload.options = undefined;
payload.callback = properties;
payload.callback = sanitizedProperties;
}

if (isFunction(name)) {
payload.category = category as string;
if (isFunction(sanitizedName)) {
payload.category = sanitizedCategory as string;
payload.name = undefined;
payload.properties = undefined;
payload.options = undefined;
payload.callback = name;
payload.callback = sanitizedName;
}

if (isFunction(category)) {
if (isFunction(sanitizedCategory)) {
payload.category = undefined;
payload.name = undefined;
payload.properties = undefined;
payload.options = undefined;
payload.callback = category;
payload.callback = sanitizedCategory;
}

if (isObjectLiteralAndNotNull(category)) {
if (isObjectLiteralAndNotNull(sanitizedCategory)) {
payload.name = undefined;
payload.category = undefined;
payload.properties = category as Nullable<ApiObject>;
if (!isFunction(name)) {
payload.options = name as Nullable<ApiOptions>;
payload.properties = sanitizedCategory as Nullable<ApiObject>;
if (!isFunction(sanitizedName)) {
payload.options = sanitizedName as Nullable<ApiOptions>;
} else {
payload.options = undefined;
}
} else if (isObjectLiteralAndNotNull(name)) {
} else if (isObjectLiteralAndNotNull(sanitizedName)) {
payload.name = undefined;
payload.properties = name as Nullable<ApiObject>;
if (!isFunction(properties)) {
payload.options = properties as Nullable<ApiOptions>;
payload.properties = sanitizedName as Nullable<ApiObject>;
if (!isFunction(sanitizedProperties)) {
payload.options = sanitizedProperties as Nullable<ApiOptions>;
} else {
payload.options = undefined;
}
}

// if the category argument alone is provided b/w category and name,
// use it as name and set category to undefined
if (isString(category) && !isString(name)) {
if (isString(sanitizedCategory) && !isString(sanitizedName)) {
payload.category = undefined;
payload.name = category;
payload.name = sanitizedCategory;
}

// Rest of the code is just to clean up undefined values
Expand Down Expand Up @@ -171,27 +178,32 @@ const trackArgumentsToCallOptions = (
options?: Nullable<ApiOptions> | ApiCallback,
callback?: ApiCallback,
): TrackCallOptions => {
const sanitizedEvent = getSanitizedValue(event);
const sanitizedProperties = getSanitizedValue(properties);
const sanitizedOptions = getSanitizedValue(options);
const sanitizedCallback = getSanitizedValue(callback);

const payload: TrackCallOptions = {
name: event,
properties: properties as Nullable<ApiObject>,
options: options as Nullable<ApiOptions>,
name: sanitizedEvent,
properties: sanitizedProperties as Nullable<ApiObject>,
options: sanitizedOptions as Nullable<ApiOptions>,
callback: undefined,
};

if (isFunction(callback)) {
payload.callback = callback;
if (isFunction(sanitizedCallback)) {
payload.callback = sanitizedCallback;
}

if (isFunction(options)) {
payload.properties = properties as Nullable<ApiObject>;
if (isFunction(sanitizedOptions)) {
payload.properties = sanitizedProperties as Nullable<ApiObject>;
payload.options = undefined;
payload.callback = options;
payload.callback = sanitizedOptions;
}

if (isFunction(properties)) {
if (isFunction(sanitizedProperties)) {
payload.properties = undefined;
payload.options = undefined;
payload.callback = properties;
payload.callback = sanitizedProperties;
}

// Rest of the code is just to clean up undefined values
Expand All @@ -217,38 +229,43 @@ const identifyArgumentsToCallOptions = (
options?: Nullable<ApiOptions> | ApiCallback,
callback?: ApiCallback,
): IdentifyCallOptions => {
const sanitizedUserId = getSanitizedValue(userId);
const sanitizedTraits = getSanitizedValue(traits);
const sanitizedOptions = getSanitizedValue(options);
const sanitizedCallback = getSanitizedValue(callback);

const payload: IdentifyCallOptions = {
userId: userId as string,
traits: traits as Nullable<IdentifyTraits>,
options: options as Nullable<ApiOptions>,
userId: sanitizedUserId as string,
traits: sanitizedTraits as Nullable<IdentifyTraits>,
options: sanitizedOptions as Nullable<ApiOptions>,
callback: undefined,
};

if (isFunction(callback)) {
payload.callback = callback;
if (isFunction(sanitizedCallback)) {
payload.callback = sanitizedCallback;
}

if (isFunction(options)) {
payload.userId = userId as string;
payload.traits = traits as Nullable<IdentifyTraits>;
if (isFunction(sanitizedOptions)) {
payload.userId = sanitizedUserId as string;
payload.traits = sanitizedTraits as Nullable<IdentifyTraits>;
payload.options = undefined;
payload.callback = options;
payload.callback = sanitizedOptions;
}

if (isFunction(traits)) {
payload.userId = userId as string;
if (isFunction(sanitizedTraits)) {
payload.userId = sanitizedUserId as string;
payload.traits = undefined;
payload.options = undefined;
payload.callback = traits;
payload.callback = sanitizedTraits;
}

if (isObjectLiteralAndNotNull(userId) || isNull(userId)) {
if (isObjectLiteralAndNotNull(sanitizedUserId) || isNull(sanitizedUserId)) {
// Explicitly set null to prevent resetting the existing value
// in the Analytics class
payload.userId = null;
payload.traits = userId as Nullable<IdentifyTraits>;
if (!isFunction(traits)) {
payload.options = traits as Nullable<ApiOptions>;
payload.traits = sanitizedUserId as Nullable<IdentifyTraits>;
if (!isFunction(sanitizedTraits)) {
payload.options = sanitizedTraits as Nullable<ApiOptions>;
} else {
payload.options = undefined;
}
Expand Down Expand Up @@ -283,33 +300,38 @@ const aliasArgumentsToCallOptions = (
options?: Nullable<ApiOptions> | ApiCallback,
callback?: ApiCallback,
): AliasCallOptions => {
const sanitizedTo = getSanitizedValue(to);
const sanitizedFrom = getSanitizedValue(from);
const sanitizedOptions = getSanitizedValue(options);
const sanitizedCallback = getSanitizedValue(callback);

const payload: AliasCallOptions = {
to,
from: from as string,
options: options as Nullable<ApiOptions>,
to: sanitizedTo,
from: sanitizedFrom as string,
options: sanitizedOptions as Nullable<ApiOptions>,
callback: undefined,
};

if (isFunction(callback)) {
payload.callback = callback;
if (isFunction(sanitizedCallback)) {
payload.callback = sanitizedCallback;
}

if (isFunction(options)) {
payload.to = to;
payload.from = from as string;
if (isFunction(sanitizedOptions)) {
payload.to = sanitizedTo;
payload.from = sanitizedFrom as string;
payload.options = undefined;
payload.callback = options;
payload.callback = sanitizedOptions;
}

if (isFunction(from)) {
payload.to = to;
if (isFunction(sanitizedFrom)) {
payload.to = sanitizedTo;
payload.from = undefined;
payload.options = undefined;
payload.callback = from;
} else if (isObjectLiteralAndNotNull(from) || isNull(from)) {
payload.to = to;
payload.callback = sanitizedFrom;
} else if (isObjectLiteralAndNotNull(sanitizedFrom) || isNull(sanitizedFrom)) {
payload.to = sanitizedTo;
payload.from = undefined;
payload.options = from as Nullable<ApiOptions>;
payload.options = sanitizedFrom as Nullable<ApiOptions>;
}

// Rest of the code is just to clean up undefined values
Expand Down Expand Up @@ -343,38 +365,43 @@ const groupArgumentsToCallOptions = (
options?: Nullable<ApiOptions> | ApiCallback,
callback?: ApiCallback,
): GroupCallOptions => {
const sanitizedGroupId = getSanitizedValue(groupId);
const sanitizedTraits = getSanitizedValue(traits);
const sanitizedOptions = getSanitizedValue(options);
const sanitizedCallback = getSanitizedValue(callback);

const payload: GroupCallOptions = {
groupId: groupId as string,
traits: traits as Nullable<ApiObject>,
options: options as Nullable<ApiOptions>,
groupId: sanitizedGroupId as string,
traits: sanitizedTraits as Nullable<ApiObject>,
options: sanitizedOptions as Nullable<ApiOptions>,
callback: undefined,
};

if (isFunction(callback)) {
payload.callback = callback;
if (isFunction(sanitizedCallback)) {
payload.callback = sanitizedCallback;
}

if (isFunction(options)) {
payload.groupId = groupId as string;
payload.traits = traits as Nullable<ApiObject>;
if (isFunction(sanitizedOptions)) {
payload.groupId = sanitizedGroupId as string;
payload.traits = sanitizedTraits as Nullable<ApiObject>;
payload.options = undefined;
payload.callback = options;
payload.callback = sanitizedOptions;
}

if (isFunction(traits)) {
payload.groupId = groupId as string;
if (isFunction(sanitizedTraits)) {
payload.groupId = sanitizedGroupId as string;
payload.traits = undefined;
payload.options = undefined;
payload.callback = traits;
payload.callback = sanitizedTraits;
}

if (isObjectLiteralAndNotNull(groupId) || isNull(groupId)) {
if (isObjectLiteralAndNotNull(sanitizedGroupId) || isNull(sanitizedGroupId)) {
// Explicitly set null to prevent resetting the existing value
// in the Analytics class
payload.groupId = null;
payload.traits = groupId as Nullable<ApiObject>;
if (!isFunction(traits)) {
payload.options = traits as Nullable<ApiOptions>;
payload.traits = sanitizedGroupId as Nullable<ApiObject>;
if (!isFunction(sanitizedTraits)) {
payload.options = sanitizedTraits as Nullable<ApiOptions>;
} else {
payload.options = undefined;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/analytics-js/.size-limit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default [
{
name: 'Core - Legacy - CDN',
path: 'dist/cdn/legacy/iife/rsa.min.js',
limit: '48.5 KiB',
limit: '49 KiB',
},
{
name: 'Core - Modern - NPM (ESM)',
Expand Down Expand Up @@ -95,7 +95,7 @@ export default [
name: 'Core (Content Script) - Legacy - NPM (CJS)',
path: 'dist/npm/legacy/content-script/cjs/index.cjs',
import: '*',
limit: '48 KiB',
limit: '48.5 KiB',
},
{
name: 'Core (Content Script) - Legacy - NPM (UMD)',
Expand Down
Loading
Loading