New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@twilio/flex-ui-telemetry

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@twilio/flex-ui-telemetry - npm Package Compare versions

Comparing version 1.0.1 to 1.1.0

4

dist/constants.d.ts
export declare const PRODUCT = "Flex";
export declare const SOURCE = "flexui";
export declare const ANALYTICS_EVENT = "analytics";
export declare const ANALYTICS_CALLBACK_EVENT = "analytics-callback";
export declare const READY_EVENT = "ready";
export declare const IFRAME_LOADED = "iframe-loaded";
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SOURCE = exports.PRODUCT = void 0;
exports.IFRAME_LOADED = exports.READY_EVENT = exports.ANALYTICS_CALLBACK_EVENT = exports.ANALYTICS_EVENT = exports.SOURCE = exports.PRODUCT = void 0;
exports.PRODUCT = 'Flex';
exports.SOURCE = 'flexui';
exports.ANALYTICS_EVENT = 'analytics';
exports.ANALYTICS_CALLBACK_EVENT = 'analytics-callback';
exports.READY_EVENT = 'ready';
exports.IFRAME_LOADED = 'iframe-loaded';
//# sourceMappingURL=constants.js.map

@@ -1,2 +0,2 @@

import { CommonProperties, SegmentOptions } from './types/telemetry';
import { CommonProperties, SegmentOptions, FunctionType } from './types/telemetry';
/**

@@ -7,2 +7,3 @@ * A Telemetry class that exposes methods to capture different type of events in the Flex UI

private commonProperties;
private callbacks;
/**

@@ -157,4 +158,18 @@ * Creates an analytics instance

group(groupId: string, callback?: () => void): void;
/**
* Invokes the callback method once analytics is initialised and all the enabled destinations have loaded
* @param callback A function to be executed after the initialisation
*/
ready(callback: FunctionType): void;
/**
* Attaches a listener in the parent window that listens to invocation of Segment Analytics callback method.
*/
private _attachCallbackListener;
/**
* Posts a message to the Segment Analytics iframe element
* @param method Method name
* @param params Parameters to be passed to the Segment Analytics API
*/
private _post;
}
export default FlexTelemetry;

@@ -26,2 +26,4 @@ "use strict";

}
this.callbacks = {};
this._attachCallbackListener();
}

@@ -41,3 +43,3 @@ get segment() {

page(...args) {
const [category, name, properties = {}, options = {}, callback] = (0, resolver_1.resolvePageArguments)(args);
const [category, name, properties = {}, options = {}, callback, callbackId] = (0, resolver_1.resolvePageArguments)(args);
const commonParameters = [

@@ -47,2 +49,3 @@ Object.assign(Object.assign(Object.assign({}, properties), this.commonProperties), this._pageProperties),

callback,
callbackId,
];

@@ -59,20 +62,61 @@ let parameters;

track(...args) {
const [event, properties = {}, options = {}, callback] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.TRACK, event, Object.assign(Object.assign({}, properties), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { groupId: this.commonProperties.accountSid, page: Object.assign({}, this._pageProperties) }) }), callback);
const [event, properties = {}, options = {}, callback, callbackId] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.TRACK, event, Object.assign(Object.assign({}, properties), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { groupId: this.commonProperties.accountSid, page: Object.assign({}, this._pageProperties) }) }), callback, callbackId);
}
identify(...args) {
const [userId, traits = {}, options = {}, callback] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.IDENTIFY, userId || this.commonProperties.workerSid, Object.assign(Object.assign({}, traits), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { groupId: this.commonProperties.accountSid, page: Object.assign({}, this._pageProperties) }) }), callback);
const [userId, traits = {}, options = {}, callback, callbackId] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.IDENTIFY, userId || this.commonProperties.workerSid, Object.assign(Object.assign({}, traits), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { groupId: this.commonProperties.accountSid, page: Object.assign({}, this._pageProperties) }) }), callback, callbackId);
}
group(...args) {
const [groupId, traits = {}, options = {}, callback] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.GROUP, groupId, Object.assign(Object.assign({}, traits), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { page: Object.assign({}, this._pageProperties) }) }), callback);
const [groupId, traits = {}, options = {}, callback, callbackId] = (0, resolver_1.resolveArguments)(args);
this._post(telemetry_1.Method.GROUP, groupId, Object.assign(Object.assign({}, traits), this.commonProperties), Object.assign(Object.assign({}, options), { context: Object.assign(Object.assign({}, options.context), { page: Object.assign({}, this._pageProperties) }) }), callback, callbackId);
}
/**
* Invokes the callback method once analytics is initialised and all the enabled destinations have loaded
* @param callback A function to be executed after the initialisation
*/
ready(callback) {
if (this.segment) {
this._post(telemetry_1.Method.READY, callback, constants_1.READY_EVENT);
}
else {
this.callbacks = {
[constants_1.READY_EVENT]: callback,
};
}
}
/**
* Attaches a listener in the parent window that listens to invocation of Segment Analytics callback method.
*/
_attachCallbackListener() {
window.onmessage = (event) => {
const { type, payload: id } = event.data;
if (type === constants_1.ANALYTICS_CALLBACK_EVENT && this.callbacks[id]) {
this.callbacks[id]();
delete this.callbacks[id];
}
else if (type === constants_1.IFRAME_LOADED && this.callbacks[constants_1.READY_EVENT]) {
const callbackFn = this.callbacks[constants_1.READY_EVENT];
this._post(telemetry_1.Method.READY, callbackFn, constants_1.READY_EVENT);
}
};
}
/**
* Posts a message to the Segment Analytics iframe element
* @param method Method name
* @param params Parameters to be passed to the Segment Analytics API
*/
_post(method, ...params) {
if (this.segment && this.segment.contentWindow) {
const callbackId = params.pop();
const callback = params.pop();
if (callback && callbackId) {
this.callbacks[callbackId] = callback;
}
this.segment.contentWindow.postMessage({
type: 'analytics',
type: constants_1.ANALYTICS_EVENT,
method,
params,
}, '*');
callbackId,
}, window.origin);
}

@@ -79,0 +123,0 @@ }

11

dist/types/telemetry.d.ts

@@ -19,2 +19,3 @@ export interface SegmentOptions {

}
export type FunctionType = () => void;
export type Parameters = [

@@ -24,3 +25,4 @@ string | undefined,

SegmentOptions | undefined,
(() => void) | undefined
FunctionType | undefined,
string | undefined
];

@@ -32,4 +34,6 @@ export type PageParameters = [

SegmentOptions | undefined,
(() => void) | undefined
FunctionType | undefined,
string | undefined
];
export type ReadyParameters = [FunctionType | undefined, string | undefined];
export declare enum Method {

@@ -39,4 +43,5 @@ PAGE = "page",

IDENTIFY = "identify",
GROUP = "group"
GROUP = "group",
READY = "ready"
}
export declare const PRODUCT = "Flex";

@@ -10,4 +10,5 @@ "use strict";

Method["GROUP"] = "group";
Method["READY"] = "ready";
})(Method || (exports.Method = Method = {}));
exports.PRODUCT = 'Flex';
//# sourceMappingURL=telemetry.js.map

@@ -5,1 +5,2 @@ export declare const isObject: (value: unknown) => boolean;

export declare const isSegmentOptions: (value: unknown) => boolean;
export declare const generateUID: () => string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSegmentOptions = exports.isString = exports.isFunction = exports.isObject = void 0;
exports.generateUID = exports.isSegmentOptions = exports.isString = exports.isFunction = exports.isObject = void 0;
const isObject = (value) => {

@@ -25,2 +25,6 @@ return Boolean(value) && !Array.isArray(value) && typeof value === 'object';

exports.isSegmentOptions = isSegmentOptions;
const generateUID = () => {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};
exports.generateUID = generateUID;
//# sourceMappingURL=helper.js.map

@@ -10,2 +10,3 @@ "use strict";

let callback;
let callbackId;
const [arg1, arg2, arg3, arg4] = args;

@@ -43,3 +44,6 @@ if ((0, helper_1.isString)(arg1)) {

}
return [event, properties, options, callback];
if (Boolean(callback)) {
callbackId = (0, helper_1.generateUID)();
}
return [event, properties, options, callback, callbackId];
};

@@ -46,0 +50,0 @@ exports.resolveArguments = resolveArguments;

{
"name": "@twilio/flex-ui-telemetry",
"version": "1.0.1",
"version": "1.1.0",
"description": "Flex UI Telemetry SDK",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

import './manager.mock';
import FlexTelemetry from '../FlexTelemetry';
import { Method, SegmentOptions } from '../types/telemetry';
import { ANALYTICS_CALLBACK_EVENT, IFRAME_LOADED, READY_EVENT } from '../constants';
const callbackId = '1234';
jest.mock('../utils/helper', () => ({
__esModule: true,
...jest.requireActual('../utils/helper'),
generateUID: () => callbackId,
}));
const waitFor = async (fn: () => void, timeout: number) => {
await new Promise((resolve, reject) => {
setTimeout(() => {
try {
fn();
resolve(true);
} catch (e) {
reject(e);
}
}, timeout);
});
};
describe('Analytics', () => {

@@ -49,4 +71,17 @@ const mockCommonProperties = {

const implementPostMessage = (type: string, payload: string) => {
postMessageFn.mockImplementationOnce(() => {
window.self.postMessage(
{
type,
payload,
},
window.origin,
);
});
};
afterEach(() => {
jest.clearAllMocks();
postMessageFn.mockReset();
});

@@ -85,2 +120,3 @@

callbackFn,
callbackId,
);

@@ -105,2 +141,3 @@ });

callbackFn,
callbackId,
);

@@ -129,2 +166,3 @@ });

callbackFn,
callbackId,
);

@@ -149,2 +187,3 @@ });

undefined,
undefined,
);

@@ -168,4 +207,60 @@ });

callbackFn,
callbackId,
);
});
it('should execute callback', async () => {
implementPostMessage(ANALYTICS_CALLBACK_EVENT, callbackId);
analytics.track(mockEvent, mockEventProperties, callbackFn);
expect(postMessageFn).toBeCalled();
await waitFor(() => {
expect(callbackFn).toBeCalled();
}, 100);
});
it('should not execute callback for other message events', async () => {
implementPostMessage('random-event', 'random-id');
analytics.track(mockEvent, mockEventProperties, callbackFn);
expect(postMessageFn).toBeCalled();
await waitFor(() => {
expect(callbackFn).toBeCalledTimes(0);
}, 100);
});
it('should post ready event when analytics.ready event is called and execute the callback', async () => {
implementPostMessage(ANALYTICS_CALLBACK_EVENT, READY_EVENT);
analytics.ready(callbackFn);
expect(postSpy).toBeCalledWith(Method.READY, callbackFn, READY_EVENT);
expect(postMessageFn).toBeCalled();
await waitFor(() => {
expect(callbackFn).toBeCalled();
}, 100);
});
it('should not post ready event if iframe element is not loaded', () => {
segmentSpy.mockReturnValueOnce(null);
analytics.ready(callbackFn);
expect(postSpy).not.toBeCalled();
});
it('should invoke callback when iframe is loaded', async () => {
segmentSpy.mockReturnValueOnce(null);
implementPostMessage(ANALYTICS_CALLBACK_EVENT, READY_EVENT);
analytics.ready(callbackFn);
window.self.postMessage(
{
type: IFRAME_LOADED,
},
window.origin,
);
await waitFor(() => {
expect(postSpy).toBeCalledWith(Method.READY, callbackFn, READY_EVENT);
expect(callbackFn).toBeCalled();
}, 100);
});
});

@@ -1,2 +0,2 @@

import { isFunction, isObject, isSegmentOptions, isString } from '../../utils/helper';
import { generateUID, isFunction, isObject, isSegmentOptions, isString } from '../../utils/helper';

@@ -167,2 +167,14 @@ describe('Helper methods', () => {

});
describe('generateUID', () => {
it('should generate unique id', () => {
const uid1 = generateUID();
const uid2 = generateUID();
expect(uid1).not.toEqual(uid2);
});
it('should be alphanumeric characters', () => {
const uid1 = generateUID();
expect(/^[a-z0-9]+$/i.test(uid1)).toBe(true);
});
});
});
import { resolveArguments, resolvePageArguments } from '../../utils/resolver';
const callbackId = '1234';
jest.mock('../../utils/helper', () => ({
__esModule: true,
...jest.requireActual('../../utils/helper'),
generateUID: () => callbackId,
}));
describe('resolvers', () => {

@@ -23,9 +31,9 @@ it('resolveArguments', () => {

expect(resolved).toStrictEqual([name, undefined, undefined, undefined]);
expect(resolved1).toStrictEqual([name, properties, undefined, undefined]);
expect(resolved2).toStrictEqual([name, properties, options, undefined]);
expect(resolved3).toStrictEqual([name, properties, options, fn]);
expect(resolved4).toStrictEqual([name, properties, undefined, fn]);
expect(resolved5).toStrictEqual([name, undefined, undefined, fn]);
expect(resolved6).toStrictEqual([undefined, undefined, undefined, undefined]);
expect(resolved).toStrictEqual([name, undefined, undefined, undefined, undefined]);
expect(resolved1).toStrictEqual([name, properties, undefined, undefined, undefined]);
expect(resolved2).toStrictEqual([name, properties, options, undefined, undefined]);
expect(resolved3).toStrictEqual([name, properties, options, fn, callbackId]);
expect(resolved4).toStrictEqual([name, properties, undefined, fn, callbackId]);
expect(resolved5).toStrictEqual([name, undefined, undefined, fn, callbackId]);
expect(resolved6).toStrictEqual([undefined, undefined, undefined, undefined, undefined]);
});

@@ -61,18 +69,18 @@

expect(resolved).toStrictEqual([undefined, undefined, undefined, undefined, undefined]);
expect(resolved1).toStrictEqual([category, name, undefined, undefined, undefined]);
expect(resolved2).toStrictEqual([category, name, properties, undefined, undefined]);
expect(resolved3).toStrictEqual([category, name, properties, options, undefined]);
expect(resolved4).toStrictEqual([category, name, properties, options, fn]);
expect(resolved5).toStrictEqual([undefined, name, undefined, undefined, undefined]);
expect(resolved6).toStrictEqual([undefined, name, properties, undefined, undefined]);
expect(resolved7).toStrictEqual([undefined, name, properties, options, undefined]);
expect(resolved8).toStrictEqual([undefined, name, properties, options, fn]);
expect(resolved9).toStrictEqual([undefined, name, properties, undefined, fn]);
expect(resolved10).toStrictEqual([undefined, name, undefined, undefined, fn]);
expect(resolved11).toStrictEqual([undefined, undefined, properties, undefined, undefined]);
expect(resolved12).toStrictEqual([undefined, undefined, properties, options, undefined]);
expect(resolved13).toStrictEqual([undefined, undefined, properties, options, fn]);
expect(resolved14).toStrictEqual([undefined, undefined, undefined, undefined, fn]);
expect(resolved).toStrictEqual([undefined, undefined, undefined, undefined, undefined, undefined]);
expect(resolved1).toStrictEqual([category, name, undefined, undefined, undefined, undefined]);
expect(resolved2).toStrictEqual([category, name, properties, undefined, undefined, undefined]);
expect(resolved3).toStrictEqual([category, name, properties, options, undefined, undefined]);
expect(resolved4).toStrictEqual([category, name, properties, options, fn, callbackId]);
expect(resolved5).toStrictEqual([undefined, name, undefined, undefined, undefined, undefined]);
expect(resolved6).toStrictEqual([undefined, name, properties, undefined, undefined, undefined]);
expect(resolved7).toStrictEqual([undefined, name, properties, options, undefined, undefined]);
expect(resolved8).toStrictEqual([undefined, name, properties, options, fn, callbackId]);
expect(resolved9).toStrictEqual([undefined, name, properties, undefined, fn, callbackId]);
expect(resolved10).toStrictEqual([undefined, name, undefined, undefined, fn, callbackId]);
expect(resolved11).toStrictEqual([undefined, undefined, properties, undefined, undefined, undefined]);
expect(resolved12).toStrictEqual([undefined, undefined, properties, options, undefined, undefined]);
expect(resolved13).toStrictEqual([undefined, undefined, properties, options, fn, callbackId]);
expect(resolved14).toStrictEqual([undefined, undefined, undefined, undefined, fn, callbackId]);
});
});
export const PRODUCT = 'Flex';
export const SOURCE = 'flexui';
export const ANALYTICS_EVENT = 'analytics';
export const ANALYTICS_CALLBACK_EVENT = 'analytics-callback';
export const READY_EVENT = 'ready';
export const IFRAME_LOADED = 'iframe-loaded';

@@ -10,4 +10,6 @@ import * as semver from 'semver';

PageParameters,
FunctionType,
ReadyParameters,
} from './types/telemetry';
import { PRODUCT, SOURCE } from './constants';
import { ANALYTICS_CALLBACK_EVENT, ANALYTICS_EVENT, IFRAME_LOADED, PRODUCT, READY_EVENT, SOURCE } from './constants';
import { resolveArguments, resolvePageArguments } from './utils/resolver';

@@ -21,2 +23,4 @@

private callbacks: Record<string, FunctionType>;
/**

@@ -43,2 +47,5 @@ * Creates an analytics instance

}
this.callbacks = {};
this._attachCallbackListener();
}

@@ -121,3 +128,4 @@

public page(...args: unknown[]): void {
const [category, name, properties = {}, options = {}, callback] = resolvePageArguments(args);
const [category, name, properties = {}, options = {}, callback, callbackId] = resolvePageArguments(args);
const commonParameters = [

@@ -137,2 +145,3 @@ {

callback,
callbackId,
];

@@ -176,3 +185,4 @@ let parameters: Parameters | PageParameters;

public track(...args: unknown[]): void {
const [event, properties = {}, options = {}, callback] = resolveArguments(args);
const [event, properties = {}, options = {}, callback, callbackId] = resolveArguments(args);
this._post(

@@ -196,2 +206,3 @@ Method.TRACK,

callback,
callbackId,
);

@@ -252,3 +263,3 @@ }

public identify(...args: unknown[]): void {
const [userId, traits = {}, options = {}, callback] = resolveArguments(args);
const [userId, traits = {}, options = {}, callback, callbackId] = resolveArguments(args);

@@ -273,2 +284,3 @@ this._post(

callback,
callbackId,
);

@@ -305,3 +317,4 @@ }

public group(...args: unknown[]): void {
const [groupId, traits = {}, options = {}, callback] = resolveArguments(args);
const [groupId, traits = {}, options = {}, callback, callbackId] = resolveArguments(args);
this._post(

@@ -324,14 +337,58 @@ Method.GROUP,

callback,
callbackId,
);
}
private _post(method: Method, ...params: Parameters | PageParameters): void {
/**
* Invokes the callback method once analytics is initialised and all the enabled destinations have loaded
* @param callback A function to be executed after the initialisation
*/
public ready(callback: FunctionType): void {
if (this.segment) {
this._post(Method.READY, callback, READY_EVENT);
} else {
this.callbacks = {
[READY_EVENT]: callback,
};
}
}
/**
* Attaches a listener in the parent window that listens to invocation of Segment Analytics callback method.
*/
private _attachCallbackListener() {
window.onmessage = (event: MessageEvent<{ type: string; payload: string }>): void => {
const { type, payload: id } = event.data;
if (type === ANALYTICS_CALLBACK_EVENT && this.callbacks[id]) {
this.callbacks[id]();
delete this.callbacks[id];
} else if (type === IFRAME_LOADED && this.callbacks[READY_EVENT]) {
const callbackFn = this.callbacks[READY_EVENT];
this._post(Method.READY, callbackFn, READY_EVENT);
}
};
}
/**
* Posts a message to the Segment Analytics iframe element
* @param method Method name
* @param params Parameters to be passed to the Segment Analytics API
*/
private _post(method: Method, ...params: Parameters | PageParameters | ReadyParameters): void {
if (this.segment && this.segment.contentWindow) {
const callbackId = params.pop() as string | undefined;
const callback = params.pop() as FunctionType | undefined;
if (callback && callbackId) {
this.callbacks[callbackId] = callback;
}
this.segment.contentWindow.postMessage(
{
type: 'analytics',
type: ANALYTICS_EVENT,
method,
params,
callbackId,
},
'*',
window.origin,
);

@@ -338,0 +395,0 @@ }

@@ -22,2 +22,4 @@ export interface SegmentOptions {

export type FunctionType = () => void;
export type Parameters = [

@@ -27,3 +29,4 @@ string | undefined,

SegmentOptions | undefined,
(() => void) | undefined,
FunctionType | undefined,
string | undefined,
];

@@ -36,5 +39,8 @@

SegmentOptions | undefined,
(() => void) | undefined,
FunctionType | undefined,
string | undefined,
];
export type ReadyParameters = [FunctionType | undefined, string | undefined];
export enum Method {

@@ -45,4 +51,5 @@ PAGE = 'page',

GROUP = 'group',
READY = 'ready',
}
export const PRODUCT = 'Flex';

@@ -26,1 +26,5 @@ import { SegmentOptions } from '../types/telemetry';

};
export const generateUID = (): string => {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};

@@ -1,6 +0,4 @@

import { PageParameters, Parameters, SegmentOptions } from '../types/telemetry';
import { isFunction, isObject, isSegmentOptions, isString } from './helper';
import { PageParameters, Parameters, SegmentOptions, FunctionType } from '../types/telemetry';
import { generateUID, isFunction, isObject, isSegmentOptions, isString } from './helper';
type FunctionType = () => void;
export const resolveArguments = (args: unknown[]): Parameters => {

@@ -11,2 +9,3 @@ let event;

let callback;
let callbackId;

@@ -53,3 +52,7 @@ const [arg1, arg2, arg3, arg4] = args;

return [event, properties, options, callback];
if (Boolean(callback)) {
callbackId = generateUID();
}
return [event, properties, options, callback, callbackId];
};

@@ -56,0 +59,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc