Socket
Socket
Sign inDemoInstall

@segment/analytics.js-core

Package Overview
Dependencies
Maintainers
138
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@segment/analytics.js-core - npm Package Compare versions

Comparing version 3.9.0 to 3.10.0

173

lib/analytics.js

@@ -14,3 +14,5 @@ 'use strict';

var Identify = require('segmentio-facade').Identify;
var MiddlewareChain = require('./middleware').Chain;
var SourceMiddlewareChain = require('./middleware').SourceMiddlewareChain;
var IntegrationMiddlewareChain = require('./middleware')
.IntegrationMiddlewareChain;
var Page = require('segmentio-facade').Page;

@@ -51,3 +53,4 @@ var Track = require('segmentio-facade').Track;

this.Integrations = {};
this._integrationMiddlewares = new MiddlewareChain();
this._sourceMiddlewares = new SourceMiddlewareChain();
this._integrationMiddlewares = new IntegrationMiddlewareChain();
this._integrations = {};

@@ -101,2 +104,19 @@ this._readied = false;

/**
* Define a new `SourceMiddleware`
*
* @param {Function} Middleware
* @return {Analytics}
*/
Analytics.prototype.addSourceMiddleware = function(middleware) {
if (this.initialized)
throw new Error(
'attempted to add a source middleware after initialization'
);
this._sourceMiddlewares.add(middleware);
return this;
};
/**
* Define a new `IntegrationMiddleware`

@@ -110,3 +130,5 @@ *

if (this.initialized)
throw new Error('attempted to add middleware after initialization');
throw new Error(
'attempted to add an integration middleware after initialization'
);

@@ -695,65 +717,102 @@ this._integrationMiddlewares.add(middleware);

var self = this;
metrics.increment('analytics_js.invoke', {
method: method
});
this.emit('invoke', facade);
var failedInitializations = self.failedInitializations || [];
each(function(integration, name) {
var facadeCopy = extend(true, new Facade({}), facade);
try {
this._sourceMiddlewares.applyMiddlewares(
extend(true, new Facade({}), facade),
this._integrations,
function(result) {
// A nullified payload should not be sent.
if (result === null) {
self.log(
'Payload with method "%s" was null and dropped by source a middleware.',
method
);
return;
}
if (!facadeCopy.enabled(name)) return;
// Check if an integration failed to initialize.
// If so, do not process the message as the integration is in an unstable state.
if (failedInitializations.indexOf(name) >= 0) {
self.log(
'Skipping invocation of .%s method of %s integration. Integration failed to initialize properly.',
method,
name
);
} else {
try {
// Apply any integration middlewares that exist, then invoke the integration with the result.
self._integrationMiddlewares.applyMiddlewares(
facadeCopy,
integration.name,
function(result) {
// A nullified payload should not be sent to an integration.
if (result === null) {
self.log(
'Payload to integration "%s" was null and dropped.',
name
);
return;
}
// Check if the payload is still a Facade. If not, convert it to one.
if (!(result instanceof Facade)) {
result = new Facade(result);
}
// Check if the payload is still a Facade. If not, convert it to one.
if (!(result instanceof Facade)) {
result = new Facade(result);
}
self.emit('invoke', result);
metrics.increment('analytics_js.invoke', {
method: method
});
metrics.increment('analytics_js.integration.invoke', {
method: method,
integration_name: integration.name
});
applyIntegrationMiddlewares(result);
}
);
} catch (e) {
metrics.increment('analytics_js.invoke.error', {
method: method
});
self.log(
'Error invoking .%s method of %s integration: %o',
method,
name,
e
);
}
integration.invoke.call(integration, method, result);
}
);
} catch (e) {
metrics.increment('analytics_js.integration.invoke.error', {
method: method,
integration_name: integration.name
});
return this;
function applyIntegrationMiddlewares(facade) {
var failedInitializations = self.failedInitializations || [];
each(function(integration, name) {
var facadeCopy = extend(true, new Facade({}), facade);
if (!facadeCopy.enabled(name)) return;
// Check if an integration failed to initialize.
// If so, do not process the message as the integration is in an unstable state.
if (failedInitializations.indexOf(name) >= 0) {
self.log(
'Error invoking .%s method of %s integration: %o',
'Skipping invocation of .%s method of %s integration. Integration failed to initialize properly.',
method,
name,
e
name
);
} else {
try {
// Apply any integration middlewares that exist, then invoke the integration with the result.
self._integrationMiddlewares.applyMiddlewares(
facadeCopy,
integration.name,
function(result) {
// A nullified payload should not be sent to an integration.
if (result === null) {
self.log(
'Payload to integration "%s" was null and dropped by a middleware.',
name
);
return;
}
// Check if the payload is still a Facade. If not, convert it to one.
if (!(result instanceof Facade)) {
result = new Facade(result);
}
metrics.increment('analytics_js.integration.invoke', {
method: method,
integration_name: integration.name
});
integration.invoke.call(integration, method, result);
}
);
} catch (e) {
metrics.increment('analytics_js.integration.invoke.error', {
method: method,
integration_name: integration.name
});
self.log(
'Error invoking .%s method of %s integration: %o',
method,
name,
e
);
}
}
}
}, this._integrations);
return this;
}, self._integrations);
}
};

@@ -760,0 +819,0 @@

@@ -5,12 +5,44 @@ 'use strict';

module.exports.SourceMiddlewareChain = function SourceMiddlewareChain() {
var apply = middlewareChain(this);
this.applyMiddlewares = function(facade, integrations, callback) {
return apply(
function(mw, payload, next) {
mw({
integrations: integrations,
next: next,
payload: payload
});
},
facade,
callback
);
};
};
module.exports.IntegrationMiddlewareChain = function IntegrationMiddlewareChain() {
var apply = middlewareChain(this);
this.applyMiddlewares = function(facade, integration, callback) {
return apply(
function(mw, payload, next) {
mw(payload, integration, next);
},
facade,
callback
);
};
};
// Chain is essentially a linked list of middlewares to run in order.
function Chain() {
function middlewareChain(dest) {
var middlewares = [];
// Return a copy to prevent external mutations.
this.getMiddlewares = function() {
dest.getMiddlewares = function() {
return middlewares.slice();
};
this.add = function(middleware) {
dest.add = function(middleware) {
if (typeof middleware !== 'function')

@@ -26,6 +58,6 @@ throw new Error('attempted to add non-function middleware');

// fn is the callback to be run once all middlewares have been applied.
this.applyMiddlewares = function(facade, integration, fn) {
return function applyMiddlewares(run, facade, callback) {
if (typeof facade !== 'object')
throw new Error('applyMiddlewares requires a payload object');
if (typeof fn !== 'function')
if (typeof callback !== 'function')
throw new Error('applyMiddlewares requires a function callback');

@@ -35,4 +67,4 @@

var middlewaresToApply = middlewares.slice();
middlewaresToApply.push(fn);
executeChain(facade, integration, middlewaresToApply, 0);
middlewaresToApply.push(callback);
executeChain(run, facade, middlewaresToApply, 0);
};

@@ -42,3 +74,3 @@ }

// Go over all middlewares until all have been applied.
function executeChain(payload, integration, middlewares, index) {
function executeChain(run, payload, middlewares, index) {
// If the facade has been nullified, immediately skip to the final middleware.

@@ -59,4 +91,4 @@ if (payload === null) {

if (middlewares[index + 1]) {
mw(payload, integration, function(result) {
executeChain(result, integration, middlewares, ++index);
run(mw, payload, function(result) {
executeChain(run, result, middlewares, ++index);
});

@@ -69,2 +101,2 @@ } else {

module.exports.Chain = Chain;
module.exports.middlewareChain = middlewareChain;
{
"name": "@segment/analytics.js-core",
"author": "Segment <friends@segment.com>",
"version": "3.9.0",
"version": "3.10.0",
"description": "The hassle-free way to integrate analytics into any web application.",

@@ -6,0 +6,0 @@ "keywords": [

@@ -5,8 +5,11 @@ 'use strict';

var Facade = require('segmentio-facade');
var MiddlewareChain = require('../lib/middleware').Chain;
var SourceMiddlewareChain = require('../lib/middleware').SourceMiddlewareChain;
var IntegrationMiddlewareChain = require('../lib/middleware')
.IntegrationMiddlewareChain;
var middlewareChain = require('../lib/middleware').middlewareChain;
describe('middleware', function() {
describe('middlewareChain', function() {
var chain;
beforeEach(function() {
chain = new MiddlewareChain();
middlewareChain((chain = {}));
});

@@ -72,3 +75,10 @@

});
});
describe('IntegrationMiddlewareChain', function() {
var chain;
beforeEach(function() {
chain = new IntegrationMiddlewareChain();
});
describe('#applyMiddlewares', function() {

@@ -115,2 +125,15 @@ it('should require a function callback', function() {

it('should apply no middleware', function() {
var payload = new Facade({
testVal: 'success'
});
chain.applyMiddlewares(payload, 'Test', function(payload) {
assert(
payload.obj.testVal === 'success',
'payload value incorrectly set'
);
});
});
it('should apply a middleware', function() {

@@ -192,1 +215,138 @@ chain.add(function(payload, integration, next) {

});
describe('SourceMiddlewareChain', function() {
var chain;
beforeEach(function() {
chain = new SourceMiddlewareChain();
});
describe('#applyMiddlewares', function() {
it('should require a function callback', function() {
try {
chain.applyMiddlewares({});
} catch (e) {
assert(
e.message === 'applyMiddlewares requires a function callback',
'wrong error return'
);
}
try {
chain.applyMiddlewares({}, 'Test', ['this is not a function =(']);
} catch (e) {
assert(
e.message === 'applyMiddlewares requires a function callback',
'wrong error return'
);
}
});
});
it('should require a payload object', function() {
try {
chain.applyMiddlewares(7, 'Test', function() {
// This assert should not run.
assert(false, 'error was not thrown!');
});
} catch (e) {
assert(
e.message === 'applyMiddlewares requires a payload object',
'wrong error return'
);
}
chain.applyMiddlewares(null, 'Test', function(payload) {
// This assert SHOULD run.
assert(payload === null, 'payload should have been null');
});
});
it('should apply no middleware', function() {
var payload = new Facade({
testVal: 'success'
});
chain.applyMiddlewares(payload, 'Test', function(payload) {
assert(
payload.obj.testVal === 'success',
'payload value incorrectly set'
);
});
});
it('should apply a middleware', function() {
chain.add(function(chain) {
chain.payload.obj.testVal = 'success';
chain.next(chain.payload);
});
chain.applyMiddlewares({}, 'Test', function(payload) {
assert(
payload.obj.testVal === 'success',
'payload value incorrectly set'
);
});
});
it('should apply multiple middlewares in order', function() {
chain.add(function(chain) {
chain.payload.obj.test.push(1);
chain.next(chain.payload);
});
chain.add(function(chain) {
chain.payload.obj.test.push(2);
chain.next(chain.payload);
});
chain.add(function(chain) {
chain.payload.obj.test.push(3);
chain.next(chain.payload);
});
chain.applyMiddlewares({ test: [] }, 'Test', function(payload) {
assert.deepEqual(payload.obj.test, [1, 2, 3]);
});
});
it('should stop running middlewares if payload becomes null', function() {
chain.add(function(chain) {
chain.payload.obj.test.push(1);
chain.next(chain.payload);
});
chain.add(function(chain) {
chain.next(null);
});
chain.add(function() {
throw new Error('Middleware chain was not interrupted by null!');
});
chain.applyMiddlewares({ test: [] }, 'Test', function(payload) {
assert(payload === null, 'payload was not nullified');
});
});
it('should convert non-facade objects to facades', function() {
chain.add(function(chain) {
chain.next(chain.payload);
});
var payload = {};
assert(!(payload instanceof Facade), 'Payload should not be a facade yet.');
chain.applyMiddlewares(payload, 'Test', function(payload) {
assert(payload instanceof Facade, 'Payload should be a facade.');
});
});
it('should be able to handle facade objects as input', function() {
chain.add(function(chain) {
chain.next(chain.payload);
});
var payload = new Facade({});
assert(payload instanceof Facade, 'Payload should be a facade.');
chain.applyMiddlewares(payload, 'Test', function(payload) {
assert(payload instanceof Facade, 'Payload should still be a facade.');
});
});
});

Sorry, the diff of this file is too big to display

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