Socket
Socket
Sign inDemoInstall

ember-metrics

Package Overview
Dependencies
319
Maintainers
9
Versions
46
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.3.1 to 1.4.0

-private/utils/object-transforms.d.ts

33

addon/metrics-adapters/amplitude.js
import BaseAdapter from 'ember-metrics/metrics-adapters/base';
import objectTransforms from 'ember-metrics/utils/object-transforms';
import removeFromDOM from 'ember-metrics/utils/remove-from-dom';
import { assert } from '@ember/debug';
import { assign } from '@ember/polyfills';
import classic from 'ember-classic-decorator';
import {
without,
compact,
hasOwnProperties,
} from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import { assert, deprecate } from '@ember/debug';
const { without, compact, isPresent } = objectTransforms;
@classic
export default class AmplitudeMetricsAdapter extends BaseAdapter {

@@ -16,6 +15,6 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {
const { config } = this;
const { apiKey, options } = config;
assert(

@@ -85,2 +84,14 @@ `[ember-metrics] You must pass a valid \`apiKey\` to the ${this.toString()} adapter`,

window.amplitude.getInstance().identify(this._identity);
deprecate(
'Future versions of the AmplitudeAdapter will no longer issue an "Identify" event upon identifying. If you wish to retain this behaviour you will need to track this event yourself.',
false,
{
id: 'ember-metrics.issue-278',
for: 'ember-metrics',
since: '1.3.2',
until: '2.0.0',
}
);
window.amplitude.getInstance().logEvent('Identify');

@@ -94,3 +105,3 @@ }

if (isPresent(props)) {
if (hasOwnProperties(props)) {
window.amplitude.getInstance().logEvent(event, props);

@@ -104,3 +115,3 @@ } else {

const eventOpt = { event: 'Page View' };
const withEvent = assign(eventOpt, options);
const withEvent = { ...eventOpt, ...options };

@@ -107,0 +118,0 @@ this.trackEvent(withEvent);

import { assert } from '@ember/debug';
import BaseAdapter from './base';
import removeFromDOM from '../utils/remove-from-dom';
import classic from 'ember-classic-decorator';
import removeFromDOM from '../-private/utils/remove-from-dom';
@classic
export default class AzureAppInsightsAdapter extends BaseAdapter {

@@ -12,2 +10,3 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -14,0 +13,0 @@ assert(

import emberObject from '@ember/object';
import { assert } from '@ember/debug';
import { assert, deprecate } from '@ember/debug';
import { guidFor } from '@ember/object/internals';
import { typeOf } from '@ember/utils';
import classic from 'ember-classic-decorator';
import { setOwner } from '@ember/application';

@@ -11,3 +11,2 @@ function makeToString(ret) {

@classic
export default class BaseAdapter extends emberObject {

@@ -20,2 +19,10 @@ static supportsFastBoot = false;

constructor(config, owner) {
super(...arguments);
setOwner(this, owner);
this.config = config;
this.init();
}
// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -31,2 +38,32 @@ assert(`[ember-metrics] ${this.toString()} must implement the init hook!`);

get() {
deprecate(
'Metrics Adapters must not use EmberObject methods as they will be implemented as native classes in the next major release',
false,
{
id: 'ember-metrics-issue-287',
for: 'ember-metrics',
url: 'https://github.com/adopted-ember-addons/ember-metrics/issues/287',
since: '1.4.0',
until: '2.0.0',
}
);
super.get(...arguments);
}
set() {
deprecate(
'Metrics Adapters must not use EmberObject methods as they will be implemented as native classes in the next major release',
false,
{
id: 'ember-metrics.issue-287',
for: 'ember-metrics',
url: 'https://github.com/adopted-ember-addons/ember-metrics/issues/287',
since: '1.4.0',
until: '2.0.0',
}
);
super.set(...arguments);
}
toString() {

@@ -33,0 +70,0 @@ const hasToStringExtension = typeOf(this.toStringExtension) === 'function';

@@ -1,8 +0,6 @@

import { compact } from '../utils/object-transforms';
import removeFromDOM from '../utils/remove-from-dom';
import { compact } from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import BaseAdapter from './base';
import { assert } from '@ember/debug';
import classic from 'ember-classic-decorator';
@classic
export default class FacebookPixel extends BaseAdapter {

@@ -13,2 +11,3 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -66,11 +65,15 @@ const { id, dataProcessingOptions } = this.config;

trackPage(options = {}) {
window.fbq('track', 'PageView', options);
if (window.fbq) {
window.fbq('track', 'PageView', options);
}
}
willDestroy() {
removeFromDOM('script[src*="fbevents.js"]');
if (window.fbq) {
removeFromDOM('script[src*="fbevents.js"]');
delete window.fbq;
delete window._fbq;
delete window.fbq;
delete window._fbq;
}
}
}

@@ -1,13 +0,11 @@

import { assign } from '@ember/polyfills';
import { isPresent } from '@ember/utils';
import { assert } from '@ember/debug';
import { set } from '@ember/object';
import { capitalize } from '@ember/string';
import { compact } from '../utils/object-transforms';
import removeFromDOM from '../utils/remove-from-dom';
import { compact } from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class GoogleAnalytics extends BaseAdapter {
gaSendKey = 'send';
toStringExtension() {

@@ -17,7 +15,11 @@ return 'GoogleAnalytics';

// eslint-disable-next-line ember/classic-decorator-hooks
init() {
const config = assign({}, this.config);
const config = { ...this.config };
const { id, sendHitTask, trace, require, debug, trackerName } = config;
set(this, 'gaSendKey', trackerName ? trackerName + '.send' : 'send');
if (trackerName) {
this.gaSendKey = `${trackerName}.send`;
}
assert(

@@ -93,4 +95,5 @@ `[ember-metrics] You must pass a valid \`id\` to the ${this.toString()} adapter`,

const event = assign(sendEvent, gaEvent);
const event = { ...sendEvent, ...gaEvent };
const gaSendKey = this.gaSendKey;
window.ga(gaSendKey, event);

@@ -104,3 +107,3 @@

const sendEvent = { hitType: 'pageview' };
const event = assign(sendEvent, compactedOptions);
const event = { ...sendEvent, ...compactedOptions };

@@ -107,0 +110,0 @@ for (let key in compactedOptions) {

@@ -1,11 +0,7 @@

import { assign } from '@ember/polyfills';
import { assert } from '@ember/debug';
import { set } from '@ember/object';
import { capitalize } from '@ember/string';
import { compact } from '../utils/object-transforms';
import removeFromDOM from '../utils/remove-from-dom';
import { compact } from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class GoogleTagManager extends BaseAdapter {

@@ -18,2 +14,3 @@ dataLayer = 'dataLayer';

// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -28,3 +25,3 @@ const { id, dataLayer, envParams } = this.config;

set(this, 'dataLayer', dataLayer || 'dataLayer');
this.dataLayer = dataLayer || 'dataLayer';

@@ -75,3 +72,3 @@ this._injectScript(id, envParamsString);

const pageEvent = assign(sendEvent, compactedOptions);
const pageEvent = { ...sendEvent, ...compactedOptions };

@@ -78,0 +75,0 @@ window[dataLayer].push(pageEvent);

@@ -1,9 +0,9 @@

import { assign } from '@ember/polyfills';
import { assert } from '@ember/debug';
import { compact, without } from '../utils/object-transforms';
import removeFromDOM from '../utils/remove-from-dom';
import {
compact,
without,
} from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class Intercom extends BaseAdapter {

@@ -16,2 +16,3 @@ booted = false;

// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -54,2 +55,3 @@ const { appId } = this.config;

const method = this.booted ? 'update' : 'boot';
window.Intercom(method, props);

@@ -69,3 +71,3 @@ this.booted = true;

const event = { event: 'page viewed' };
const mergedOptions = assign(event, options);
const mergedOptions = { ...event, ...options };

@@ -72,0 +74,0 @@ this.trackEvent(mergedOptions);

@@ -1,9 +0,10 @@

import { assign } from '@ember/polyfills';
import { assert } from '@ember/debug';
import { without, compact, isPresent } from '../utils/object-transforms';
import removeFromDOM from '../utils/remove-from-dom';
import {
without,
compact,
hasOwnProperties,
} from 'ember-metrics/-private/utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class Mixpanel extends BaseAdapter {

@@ -14,4 +15,5 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {
const config = assign({ batch_requests: true }, this.config);
const config = { ...{ batch_requests: true }, ...this.config };
const { token } = config;

@@ -26,3 +28,2 @@ delete config.token;

this._injectScript();
window.mixpanel.init(token, config);

@@ -46,3 +47,3 @@ }

if (isPresent(props)) {
if (hasOwnProperties(props)) {
window.mixpanel.identify(distinctId);

@@ -60,3 +61,3 @@ window.mixpanel.people.set(props);

if (isPresent(props)) {
if (hasOwnProperties(props)) {
window.mixpanel.track(event, props);

@@ -70,3 +71,3 @@ } else {

const event = { event: 'page viewed' };
const mergedOptions = assign(event, options);
const mergedOptions = { ...event, ...options };

@@ -73,0 +74,0 @@ this.trackEvent(mergedOptions);

import { assert } from '@ember/debug';
import removeFromDOM from '../utils/remove-from-dom';
import removeFromDOM from '../-private/utils/remove-from-dom';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class Piwik extends BaseAdapter {

@@ -12,2 +10,3 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {

@@ -14,0 +13,0 @@ const { piwikUrl, siteId } = this.config;

import { assert } from '@ember/debug';
import { assign } from '@ember/polyfills';
import removeFromDOM from '../utils/remove-from-dom';
import { compact } from '../utils/object-transforms';
import removeFromDOM from 'ember-metrics/-private/utils/remove-from-dom';
import { compact } from 'ember-metrics/-private/utils/object-transforms';
import BaseAdapter from './base';
import classic from 'ember-classic-decorator';
@classic
export default class Segment extends BaseAdapter {

@@ -14,4 +11,5 @@ toStringExtension() {

// eslint-disable-next-line ember/classic-decorator-hooks
init() {
const config = assign({}, this.config);
const config = { ...this.config };
const segmentKey = config.key;

@@ -18,0 +16,0 @@

import Service from '@ember/service';
import { assign } from '@ember/polyfills';
import { assert } from '@ember/debug';
import { set } from '@ember/object';
import { A as emberArray, makeArray } from '@ember/array';
import { assert, deprecate } from '@ember/debug';
import { dasherize } from '@ember/string';
import { getOwner } from '@ember/application';
const { keys } = Object;
import classic from 'ember-classic-decorator';
@classic
export default class Metrics extends Service {

@@ -36,17 +30,28 @@ /**

/**
* Indicates whether calls to the service will be forwarded to the adapters
* Indicates whether calls to the service will be forwarded to the adapters.
* This is determined by investigating the user's doNotTrack settings.
*
* Note that the doNotTrack specification is deprecated, and could stop
* working at any minute. As such should this feature not be detected we
* presume tracking is permitted.
*
* @property enabled
* @type Boolean
* @default true
*/
enabled = true;
enabled = typeof navigator !== 'undefined' && navigator.doNotTrack !== '1';
get options() {
deprecate('Access to Metrics#options will be removed', {
id: 'ember-metrics:issue-298',
url: 'https://github.com/adopted-ember-addons/ember-metrics/issues/298',
until: '2.0.0',
});
return this._options;
}
/**
* Information about the active adapters from environment.js
*
* I think this could have been isolated to the init method only, but since
* was public before, would have been a breaking change
* Environment the host application is running in (e.g. development or production).
*/
options;
appEnvironment = null;

@@ -57,15 +62,8 @@ /**

* `options`.
*
* @method init
* @param {Void}
* @return {Void}
*/
init() {
constructor() {
super(...arguments);
const owner = getOwner(this);
const config = owner.factoryFor('config:environment').class;
const { metricsAdapters = [] } = config;
const { environment = 'development' } = config;
this.options = { metricsAdapters, environment };
const adapters = this.options.metricsAdapters || emberArray();
owner.registerOptionsForType('ember-metrics@metrics-adapter', {

@@ -76,28 +74,13 @@ instantiate: false,

set(this, 'appEnvironment', this.options.environment || 'development');
const config = owner.factoryFor('config:environment').class;
const { metricsAdapters = [] } = config;
const { environment = 'development' } = config;
this.activateAdapters(adapters);
super.init(...arguments);
this._options = { metricsAdapters, environment };
this.appEnvironment = environment;
this.activateAdapters(metricsAdapters);
}
identify(...args) {
this.invoke('identify', ...args);
}
alias(...args) {
this.invoke('alias', ...args);
}
trackEvent(...args) {
this.invoke('trackEvent', ...args);
}
trackPage(...args) {
this.invoke('trackPage', ...args);
}
/**
* Instantiates the adapters specified in the configuration and caches them
* for future retrieval.
* Instantiates adapters from passed adapter options and caches them for future retrieval.
*

@@ -109,34 +92,2 @@ * @method activateAdapters

activateAdapters(adapterOptions = []) {
const appEnvironment = this.appEnvironment;
const cachedAdapters = this._adapters;
const activatedAdapters = {};
adapterOptions
.filter((adapterOption) =>
this._filterEnvironments(adapterOption, appEnvironment)
)
.forEach((adapterOption) => {
const { name, config } = adapterOption;
const adapterClass = this._lookupAdapter(name);
if (typeof FastBoot === 'undefined' || adapterClass.supportsFastBoot) {
const adapter =
cachedAdapters[name] ||
this._activateAdapter({ adapterClass, config });
set(activatedAdapters, name, adapter);
}
});
return set(this, '_adapters', activatedAdapters);
}
/**
* Invokes a method on the passed adapter, or across all activated adapters if not passed.
*
* @method invoke
* @param {String} methodName
* @param {Rest} args
* @return {Void}
*/
invoke(methodName, ...args) {
if (!this.enabled) {

@@ -146,43 +97,33 @@ return;

const cachedAdapters = this._adapters;
const allAdapterNames = keys(cachedAdapters);
const [selectedAdapterNames, options] =
args.length > 1
? [makeArray(args[0]), args[1]]
: [allAdapterNames, args[0]];
const context = assign({}, this.context);
const mergedOptions = assign(context, options);
const adaptersForEnv = this._adaptersForEnv(adapterOptions);
const activeAdapters = {};
selectedAdapterNames
.map((adapterName) => cachedAdapters[adapterName])
.forEach((adapter) => adapter && adapter[methodName](mergedOptions));
}
for (let { name, config } of adaptersForEnv) {
let adapterClass = this._lookupAdapter(name);
if (typeof FastBoot === 'undefined' || adapterClass.supportsFastBoot) {
activeAdapters[name] =
this._adapters[name] ||
this._activateAdapter({ adapterClass, config });
}
}
this._adapters = activeAdapters;
/**
* On teardown, destroy cached adapters together with the Service.
*
* @method willDestroy
* @param {Void}
* @return {Void}
*/
willDestroy() {
const cachedAdapters = this._adapters;
for (let adapterName in cachedAdapters) {
cachedAdapters[adapterName].destroy();
}
return this._adapters;
}
/**
* Instantiates an adapter.
* Returns all adapterOptions that should be activated in the current application environment.
* Defaults to all environments if the option is `all` or undefined.
*
* @method _activateAdapter
* @param {Object}
* @method adaptersForEnv
* @param {Array} adapterOptions
* @private
* @return {Adapter}
* @return {Array} - adapter options in the current environment
*/
_activateAdapter({ adapterClass, config }) {
return adapterClass.create(getOwner(this).ownerInjection(), {
this: this,
config,
_adaptersForEnv(adapterOptions = []) {
return adapterOptions.filter(({ environments = ['all'] }) => {
return (
environments.includes('all') ||
environments.includes(this.appEnvironment)
);
});

@@ -206,8 +147,7 @@ }

const dasherizedAdapterName = dasherize(adapterName);
const availableAdapter = getOwner(this).lookup(
`ember-metrics@metrics-adapter:${dasherizedAdapterName}`
`ember-metrics@metrics-adapter:${dasherize(adapterName)}`
);
const localAdapter = getOwner(this).lookup(
`metrics-adapter:${dasherizedAdapterName}`
`metrics-adapter:${dasherize(adapterName)}`
);

@@ -225,22 +165,79 @@

/**
* Predicate that Filters out adapters that should not be activated in the
* current application environment. Defaults to all environments if the option
* is `all` or undefined.
* Instantiates an adapter.
*
* @method _filterEnvironments
* @param {Object} adapterOption
* @param {String} appEnvironment
* @method _activateAdapter
* @param {Object}
* @private
* @return {Boolean} should an adapter be activated
* @return {Adapter}
*/
_filterEnvironments(adapterOption, appEnvironment) {
let { environments } = adapterOption;
environments = environments || ['all'];
const wrappedEnvironments = emberArray(environments);
_activateAdapter({ adapterClass, config }) {
const decoratedClass = class extends adapterClass {
identify = this.identify;
alias = this.alias;
trackEvent = this.trackEvent;
trackPage = this.trackPage;
};
return new decoratedClass(config, getOwner(this));
}
return (
wrappedEnvironments.indexOf('all') > -1 ||
wrappedEnvironments.indexOf(appEnvironment) > -1
);
identify() {
this.invoke('identify', arguments);
}
alias() {
this.invoke('alias', arguments);
}
trackEvent() {
this.invoke('trackEvent', arguments);
}
trackPage() {
this.invoke('trackPage', arguments);
}
/**
* Invokes a method on the passed adapter, or across all activated adapters if not passed.
*
* @method invoke
* @param {String} methodName
* @param {Rest} args
* @return {Void}
*/
invoke(methodName, ...args) {
if (!this.enabled) {
return;
}
let selectedAdapterNames, options;
if (args.length > 1) {
selectedAdapterNames = makeArray(args[0]);
options = args[1];
} else {
selectedAdapterNames = Object.keys(this._adapters);
options = args[0];
}
for (let adapterName of selectedAdapterNames) {
let adapter = this._adapters[adapterName];
adapter && adapter[methodName]({ ...this.context, ...options });
}
}
/**
* On teardown, destroy cached adapters together with the Service.
*
* @method willDestroy
* @return {Void}
*/
willDestroy() {
for (let adapter of this._adapters) {
adapter.destroy();
}
}
}
function makeArray(maybeArray) {
return Array.isArray(maybeArray) ? Array.from(maybeArray) : Array(maybeArray);
}

@@ -1,12 +0,15 @@

import { moduleFor, test } from 'ember-qunit';
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import <%= classifiedModuleName %> from '<%= dasherizedPackageName %>/metrics-adapters/<%= dasherizedModuleName %>';
moduleFor('metrics-adapter:<%= dasherizedModuleName %>', '<%= friendlyTestDescription %>', {
// Specify the other units that are required for this test.
// needs: ['serializer:foo']
});
module('<%= friendlyTestDescription %>', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.subject();
assert.ok(adapter);
// TODO: Replace this with your real tests.
test('it exists', function(assert) {
let adapter = new <%= classifiedModuleName %>({
// TODO: Add adapter config
});
assert.ok(adapter);
});
});
/* eslint-env node */
module.exports = {
description: 'Generates an metrics-adapter unit test',
description: 'Generates a metrics-adapter unit test',
locals: function (options) {
return {
friendlyTestDescription: options.entity.name + ' adapter',
friendlyTestDescription: [
'Unit',
'MetricsAdapter',
options.entity.name,
].join(' | '),
};
},
};

@@ -8,2 +8,3 @@ <%= importStatement %>

// eslint-disable-next-line ember/classic-decorator-hooks
init() {}

@@ -10,0 +11,0 @@

# v1.1.0
## v1.4.0 (2021-11-21)
This will be the last release in the v1 series. See below for notes on the
forthcoming v2 release.
### Changes
- Numerous dependency updates
- Modernized tests using qunit-sinon-assertions
- Add deprecations for adapters extending EmberObject
- Deprecate an automatic identify event with Amplitude adapter (see https://github.com/adopted-ember-addons/ember-metrics/issues/278)
- Type numerous object transformation tools (https://github.com/adopted-ember-addons/ember-metrics/pull/343)
- Documentation updated
- Add the Pendo adapter
### Upcoming v2 release
- An upgrade guide will be made available as soon as possible
- This should resolve the embroider-optimized scenario failures
### Closing remarks
A hearty thank you to all contributors. The following people contributed to this release:
* @GreatWizard
* @jfdnc
* @Windvis
## v1.3.1 (2021-09-26)

@@ -4,0 +33,0 @@

@@ -1,11 +0,1 @@

{
"compilerOptions": { "target": "es6", "experimentalDecorators": true },
"exclude": [
"node_modules",
"bower_components",
"tmp",
"vendor",
".git",
"dist"
]
}
{"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}
{
"name": "ember-metrics",
"version": "1.3.1",
"version": "1.4.0",
"description": "Send data to multiple analytics integrations without re-implementing new API",

@@ -16,3 +16,6 @@ "keywords": [

"intercom",
"facebook-pixel"
"facebook pixel",
"amplitude",
"azure application insights",
"pendo"
],

@@ -25,3 +28,3 @@ "homepage": "https://github.com/adopted-ember-addons/ember-metrics",

"directories": {
"doc": "doc",
"doc": "./doc",
"test": "tests"

@@ -31,2 +34,3 @@ },

"build": "ember build --environment=production",
"doc": "typedoc",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"",

@@ -42,8 +46,11 @@ "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",

"test:all": "ember try:each",
"contributors": "npx contributor-faces -e \"(*-bot|*\\[bot\\]|*-tomster|homu|bors)\""
"contributors": "npx contributor-faces -e \"(*-bot|*\\[bot\\]|*-tomster|homu|bors)\"",
"prepack": "ember ts:precompile",
"postpack": "ember ts:clean",
"prepare": "husky install"
},
"dependencies": {
"broccoli-funnel": "^3.0.2",
"ember-classic-decorator": "^2.0.0",
"ember-cli-babel": "^7.26.6"
"ember-cli-babel": "^7.26.6",
"ember-cli-typescript": "^4.2.1"
},

@@ -53,21 +60,48 @@ "devDependencies": {

"@ember/test-helpers": "^2.4.2",
"@embroider/test-setup": "^0.44.1",
"@embroider/test-setup": "^0.47.0",
"@glimmer/tracking": "^1.0.4",
"@types/ember-qunit": "^3.4.14",
"@types/ember-resolver": "^5.0.10",
"@types/ember__application": "^3.16.3",
"@types/ember__array": "^3.16.4",
"@types/ember__component": "^3.16.6",
"@types/ember__controller": "^3.16.6",
"@types/ember__debug": "^3.16.5",
"@types/ember__engine": "^3.16.3",
"@types/ember__error": "^3.16.1",
"@types/ember__object": "^3.12.6",
"@types/ember__polyfills": "^3.12.1",
"@types/ember__routing": "^3.16.15",
"@types/ember__runloop": "^3.16.3",
"@types/ember__service": "^3.16.1",
"@types/ember__string": "^3.16.3",
"@types/ember__template": "^3.16.1",
"@types/ember__test": "^3.16.1",
"@types/ember__test-helpers": "^2.0.2",
"@types/ember__utils": "^3.16.2",
"@types/htmlbars-inline-precompile": "^1.0.1",
"@types/qunit": "^2.11.2",
"@types/rsvp": "^4.0.4",
"@typescript-eslint/eslint-plugin": "^4.32.0",
"@typescript-eslint/parser": "^4.32.0",
"babel-eslint": "^10.1.0",
"broccoli-asset-rev": "^3.0.0",
"ember-cli": "~3.28.0",
"ember-auto-import": "^2.2.0",
"ember-cli": "~3.28.1",
"ember-cli-dependency-checker": "^3.2.0",
"ember-cli-htmlbars": "^5.7.1",
"ember-cli-htmlbars": "^6.0.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-cli-typescript-blueprints": "^3.0.0",
"ember-disable-prototype-extensions": "^1.1.3",
"ember-export-application-global": "^2.0.1",
"ember-load-initializers": "^2.1.2",
"ember-page-title": "^6.2.2",
"ember-qunit": "^5.1.4",
"ember-resolver": "^8.0.3",
"ember-sinon": "^5.0.0",
"ember-sinon-qunit": "^6.0.0",
"ember-source": "~3.28.0",
"ember-source-channel-url": "^3.0.0",
"ember-try": "^1.4.0",
"ember-try": "^2.0.0",
"eslint": "^7.32.0",

@@ -78,3 +112,5 @@ "eslint-config-prettier": "^8.3.0",

"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-qunit": "^6.2.0",
"eslint-plugin-qunit": "^7.0.0",
"husky": ">=6",
"lint-staged": ">=10",
"loader.js": "^4.7.0",

@@ -84,4 +120,8 @@ "npm-run-all": "^4.1.5",

"qunit": "^2.16.0",
"qunit-sinon-assertions": "^1.0.0",
"release-it": "^14.2.1",
"release-it-lerna-changelog": "^3.1.0"
"release-it-lerna-changelog": "^4.0.0",
"typedoc": "^0.22.4",
"typescript": "^4.4.3",
"webpack": "5"
},

@@ -114,3 +154,6 @@ "engines": {

}
},
"lint-staged": {
"*.js": "eslint --cache --fix"
}
}

@@ -79,2 +79,6 @@ # ember-metrics

1. `Pendo`
- `apiKey`: [API Key](https://developers.pendo.io/docs/?bash#options)
#### Community adapters

@@ -186,2 +190,9 @@

{
name: 'Pendo',
environments: ['production'],
config: {
apiKey: '123456789',
},
},
{
name: 'LocalAdapter',

@@ -219,9 +230,9 @@ environments: ['all'], // default

// Example adapter
export default BaseAdapter.extend({
export default class ExampleAdapter extends BaseAdapter {
init() {
const { apiKey, options } = Ember.get(this, 'config');
const { apiKey, options } = this.config;
this.setupService(apiKey);
this.setOptions(options);
},
});
}
}
```

@@ -262,22 +273,19 @@

export default Route.extend({
metrics: service(),
router: service(),
export default class ApplicationRoute extends Route {
@service metrics;
@service router;
init() {
this._super(...arguments);
constructor() {
super(...arguments);
let router = this.router;
router.on('routeDidChange', () => {
const page = router.currentURL;
const title = router.currentRouteName || 'unknown';
this.router.on('routeDidChange', () => {
const page = this.router.currentURL;
const title = this.router.currentRouteName || 'unknown';
this.metrics.trackPage({ page, title });
});
},
});
}
}
```
[See this example with Native Classes](#native-class-usage)
If you wish to only call a single service, just specify it's name as the first argument:

@@ -287,3 +295,2 @@

// only invokes the `trackPage` method on the `GoogleAnalyticsAdapter`
metrics.trackPage('GoogleAnalytics', {

@@ -299,35 +306,6 @@ title: 'My Awesome App',

```js
import { set } from '@ember/object';
set(this, 'metrics.context.userName', 'Jimbo');
this.metrics.context.userName = 'Jimbo';
this.metrics.trackPage({ page: 'page/1' }); // { userName: 'Jimbo', page: 'page/1' }
```
## Native Class usage
If you are using an app built with the [Ember Octane Blueprint](https://github.com/ember-cli/ember-octane-blueprint) or otherwise implementing Native Class syntax in your routes, the following example can be used to report route transitions to ember-metrics:
```js
// app/routes/application.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
export default class ApplicationRoute extends Route {
@service metrics;
@service router;
constructor() {
super(...arguments);
let router = this.router;
router.on('routeDidChange', () => {
const page = router.currentURL;
const title = router.currentRouteName || 'unknown';
this.metrics.trackPage({ page, title });
});
}
}
```
### API

@@ -371,13 +349,13 @@

```js
import { Route } from '@ember/routing/route';
// app/routes/application.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
export default Route.extend({
metrics: service(),
export default class ApplicationRoute extends Route {
@service metrics;
afterModel(model) {
const metrics = this.metrics;
const id = model.googleAnalyticsKey;
metrics.activateAdapters([
this.metrics.activateAdapters([
{

@@ -391,4 +369,4 @@ name: 'GoogleAnalytics',

]);
},
});
}
}
```

@@ -457,19 +435,2 @@

## Testing
For unit tests using old QUnit testing API (prior to
[RFC 232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md)),
you will need to specify the adapters in use under `needs`, like so:
```js
moduleFor('route:foo', 'Unit | Route | foo', {
needs: [
'service:metrics',
'ember-metrics@metrics-adapter:google-analytics', // bundled adapter
'ember-metrics@metrics-adapter:mixpanel', // bundled adapter
'metrics-adapter:local-dummy-adapter', // local adapter
],
});
```
## Contributors

@@ -480,23 +441,30 @@

[//]: contributor-faces
<a href="https://github.com/poteto"><img src="https://avatars0.githubusercontent.com/u/1390709?v=4" title="poteto" width="80" height="80"></a>
<a href="https://github.com/jherdman"><img src="https://avatars3.githubusercontent.com/u/3300?v=4" title="jherdman" width="80" height="80"></a>
<a href="https://github.com/kellyselden"><img src="https://avatars1.githubusercontent.com/u/602423?v=4" title="kellyselden" width="80" height="80"></a>
<a href="https://github.com/chrismllr"><img src="https://avatars3.githubusercontent.com/u/9942917?v=4" title="chrismllr" width="80" height="80"></a>
<a href="https://github.com/josemarluedke"><img src="https://avatars0.githubusercontent.com/u/230476?v=4" title="josemarluedke" width="80" height="80"></a>
<a href="https://github.com/dcyriller"><img src="https://avatars2.githubusercontent.com/u/6677373?v=4" title="dcyriller" width="80" height="80"></a>
<a href="https://github.com/mike-north"><img src="https://avatars1.githubusercontent.com/u/558005?v=4" title="mike-north" width="80" height="80"></a>
<a href="https://github.com/jelhan"><img src="https://avatars3.githubusercontent.com/u/4965703?v=4" title="jelhan" width="80" height="80"></a>
<a href="https://github.com/denneralex"><img src="https://avatars1.githubusercontent.com/u/5065602?v=4" title="denneralex" width="80" height="80"></a>
<a href="https://github.com/CvX"><img src="https://avatars1.githubusercontent.com/u/66961?v=4" title="CvX" width="80" height="80"></a>
<a href="https://github.com/sly7-7"><img src="https://avatars1.githubusercontent.com/u/1826661?v=4" title="sly7-7" width="80" height="80"></a>
<a href="https://github.com/tyleryasaka"><img src="https://avatars1.githubusercontent.com/u/6504519?v=4" title="tyleryasaka" width="80" height="80"></a>
<a href="https://github.com/opsb"><img src="https://avatars2.githubusercontent.com/u/46232?v=4" title="opsb" width="80" height="80"></a>
<a href="https://github.com/jwlawrence"><img src="https://avatars3.githubusercontent.com/u/488888?v=4" title="jwlawrence" width="80" height="80"></a>
<a href="https://github.com/Artmann"><img src="https://avatars3.githubusercontent.com/u/91954?v=4" title="Artmann" width="80" height="80"></a>
<a href="https://github.com/colinhoernig"><img src="https://avatars1.githubusercontent.com/u/195992?v=4" title="colinhoernig" width="80" height="80"></a>
<a href="https://github.com/gmurphey"><img src="https://avatars3.githubusercontent.com/u/373721?v=4" title="gmurphey" width="80" height="80"></a>
<a href="https://github.com/jrjohnson"><img src="https://avatars2.githubusercontent.com/u/349624?v=4" title="jrjohnson" width="80" height="80"></a>
<a href="https://github.com/cibernox"><img src="https://avatars2.githubusercontent.com/u/265339?v=4" title="cibernox" width="80" height="80"></a>
<a href="https://github.com/nselikoff"><img src="https://avatars1.githubusercontent.com/u/1994207?v=4" title="nselikoff" width="80" height="80"></a>
<a href="https://github.com/poteto"><img src="https://avatars.githubusercontent.com/u/1390709?v=4" title="poteto" width="80" height="80"></a>
<a href="https://github.com/jherdman"><img src="https://avatars.githubusercontent.com/u/3300?v=4" title="jherdman" width="80" height="80"></a>
<a href="https://github.com/kellyselden"><img src="https://avatars.githubusercontent.com/u/602423?v=4" title="kellyselden" width="80" height="80"></a>
<a href="https://github.com/chrismllr"><img src="https://avatars.githubusercontent.com/u/9942917?v=4" title="chrismllr" width="80" height="80"></a>
<a href="https://github.com/josemarluedke"><img src="https://avatars.githubusercontent.com/u/230476?v=4" title="josemarluedke" width="80" height="80"></a>
<a href="https://github.com/lfrost"><img src="https://avatars.githubusercontent.com/u/5996000?v=4" title="lfrost" width="80" height="80"></a>
<a href="https://github.com/dcyriller"><img src="https://avatars.githubusercontent.com/u/6677373?v=4" title="dcyriller" width="80" height="80"></a>
<a href="https://github.com/mike-north"><img src="https://avatars.githubusercontent.com/u/558005?v=4" title="mike-north" width="80" height="80"></a>
<a href="https://github.com/jelhan"><img src="https://avatars.githubusercontent.com/u/4965703?v=4" title="jelhan" width="80" height="80"></a>
<a href="https://github.com/jwlawrence"><img src="https://avatars.githubusercontent.com/u/488888?v=4" title="jwlawrence" width="80" height="80"></a>
<a href="https://github.com/cah-briangantzler"><img src="https://avatars.githubusercontent.com/u/1529286?v=4" title="cah-briangantzler" width="80" height="80"></a>
<a href="https://github.com/denneralex"><img src="https://avatars.githubusercontent.com/u/5065602?v=4" title="denneralex" width="80" height="80"></a>
<a href="https://github.com/Turbo87"><img src="https://avatars.githubusercontent.com/u/141300?v=4" title="Turbo87" width="80" height="80"></a>
<a href="https://github.com/GreatWizard"><img src="https://avatars.githubusercontent.com/u/1322081?v=4" title="GreatWizard" width="80" height="80"></a>
<a href="https://github.com/CvX"><img src="https://avatars.githubusercontent.com/u/66961?v=4" title="CvX" width="80" height="80"></a>
<a href="https://github.com/sly7-7"><img src="https://avatars.githubusercontent.com/u/1826661?v=4" title="sly7-7" width="80" height="80"></a>
<a href="https://github.com/tyleryasaka"><img src="https://avatars.githubusercontent.com/u/6504519?v=4" title="tyleryasaka" width="80" height="80"></a>
<a href="https://github.com/opsb"><img src="https://avatars.githubusercontent.com/u/46232?v=4" title="opsb" width="80" height="80"></a>
<a href="https://github.com/charlesfries"><img src="https://avatars.githubusercontent.com/u/2275005?v=4" title="charlesfries" width="80" height="80"></a>
<a href="https://github.com/Artmann"><img src="https://avatars.githubusercontent.com/u/91954?v=4" title="Artmann" width="80" height="80"></a>
<a href="https://github.com/colinhoernig"><img src="https://avatars.githubusercontent.com/u/195992?v=4" title="colinhoernig" width="80" height="80"></a>
<a href="https://github.com/gmurphey"><img src="https://avatars.githubusercontent.com/u/373721?v=4" title="gmurphey" width="80" height="80"></a>
<a href="https://github.com/jfdnc"><img src="https://avatars.githubusercontent.com/u/15672873?v=4" title="jfdnc" width="80" height="80"></a>
<a href="https://github.com/bobisjan"><img src="https://avatars.githubusercontent.com/u/112557?v=4" title="bobisjan" width="80" height="80"></a>
<a href="https://github.com/JoepHeijnen"><img src="https://avatars.githubusercontent.com/u/23332441?v=4" title="JoepHeijnen" width="80" height="80"></a>
<a href="https://github.com/jrjohnson"><img src="https://avatars.githubusercontent.com/u/349624?v=4" title="jrjohnson" width="80" height="80"></a>
<a href="https://github.com/cibernox"><img src="https://avatars.githubusercontent.com/u/265339?v=4" title="cibernox" width="80" height="80"></a>
<a href="https://github.com/nselikoff"><img src="https://avatars.githubusercontent.com/u/1994207?v=4" title="nselikoff" width="80" height="80"></a>
<a href="https://github.com/reidab"><img src="https://avatars2.githubusercontent.com/u/13192?v=4" title="reidab" width="80" height="80"></a>

@@ -514,22 +482,9 @@ <a href="https://github.com/locks"><img src="https://avatars1.githubusercontent.com/u/32344?v=4" title="locks" width="80" height="80"></a>

## Installation
## Contributing
- `git clone` this repository
- `npm install`
- `bower install`
See the [Contributing](CONTRIBUTING.md) guide for details.
## Running
- `ember server`
- Visit your app at http://localhost:4200.
## License
## Running Tests
- `ember test`
- `ember test --server`
## Building
- `ember build`
For more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/).
This project is licensed under the [MIT License](LICENSE.md).

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc