ember-metrics
Advanced tools
Comparing version 1.3.1 to 1.4.0
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" | ||
} | ||
} |
175
README.md
@@ -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
77140
34
1272
66
480
+ Addedember-cli-typescript@^4.2.1
+ Addedansi-to-html@0.6.15(transitive)
+ Addedat-least-node@1.0.0(transitive)
+ Addedbroccoli-plugin@2.1.0(transitive)
+ Addedbroccoli-stew@3.0.0(transitive)
+ Addedcross-spawn@7.0.3(transitive)
+ Addedember-cli-typescript@4.2.1(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedentities@2.2.0(transitive)
+ Addedexeca@4.1.0(transitive)
+ Addedfs-extra@9.1.0(transitive)
+ Addedget-stream@5.2.0(transitive)
+ Addedhuman-signals@1.1.1(transitive)
+ Addedis-stream@2.0.1(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjsonfile@6.1.0(transitive)
+ Addedmerge-stream@2.0.0(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addednpm-run-path@4.0.1(transitive)
+ Addedonetime@5.1.2(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpump@3.0.0(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstagehand@1.0.1(transitive)
+ Addedstrip-final-newline@2.0.0(transitive)
+ Addeduniversalify@2.0.1(transitive)
+ Addedwhich@2.0.2(transitive)
- Removedember-classic-decorator@^2.0.0
- Removed@embroider/core@0.29.0(transitive)
- Removed@embroider/macros@0.29.0(transitive)
- Removed@glimmer/encoder@0.42.2(transitive)
- Removed@glimmer/interfaces@0.42.2(transitive)
- Removed@glimmer/low-level@0.42.2(transitive)
- Removed@glimmer/program@0.42.2(transitive)
- Removed@glimmer/reference@0.42.2(transitive)
- Removed@glimmer/runtime@0.42.2(transitive)
- Removed@glimmer/syntax@0.42.2(transitive)
- Removed@glimmer/util@0.42.2(transitive)
- Removed@glimmer/vm@0.42.2(transitive)
- Removed@glimmer/wire-format@0.42.2(transitive)
- Removed@simple-dom/interface@1.4.0(transitive)
- Removed@tootallnate/once@1.1.2(transitive)
- Removedabab@2.0.6(transitive)
- Removedacorn@7.4.18.11.3(transitive)
- Removedacorn-globals@6.0.0(transitive)
- Removedacorn-walk@7.2.0(transitive)
- Removedagent-base@6.0.2(transitive)
- Removedamdefine@1.0.1(transitive)
- Removedassert-never@1.2.1(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedbabel-plugin-filter-imports@3.0.0(transitive)
- Removedbabel-plugin-syntax-dynamic-import@6.18.0(transitive)
- Removedbroccoli-output-wrapper@2.0.0(transitive)
- Removedbroccoli-plugin@3.1.0(transitive)
- Removedbroccoli-source@1.1.0(transitive)
- Removedbrowser-process-hrtime@1.0.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removedcssom@0.3.80.4.4(transitive)
- Removedcssstyle@2.3.0(transitive)
- Removeddata-urls@2.0.0(transitive)
- Removeddebug@3.2.7(transitive)
- Removeddecimal.js@10.4.3(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removeddomexception@2.0.1(transitive)
- Removedember-classic-decorator@2.0.1(transitive)
- Removedescodegen@2.1.0(transitive)
- Removedesprima@4.0.1(transitive)
- Removedestraverse@5.3.0(transitive)
- Removedfast-sourcemap-concat@1.4.0(transitive)
- Removedfilesize@4.2.1(transitive)
- Removedform-data@3.0.1(transitive)
- Removedfs-extra@5.0.0(transitive)
- Removedhandlebars@4.7.8(transitive)
- Removedhtml-encoding-sniffer@2.0.1(transitive)
- Removedhttp-proxy-agent@4.0.1(transitive)
- Removedhttps-proxy-agent@5.0.1(transitive)
- Removediconv-lite@0.4.24(transitive)
- Removedis-potential-custom-element-name@1.0.1(transitive)
- Removedisarray@0.0.1(transitive)
- Removedjs-string-escape@1.0.1(transitive)
- Removedjsdom@16.7.0(transitive)
- Removedjsesc@0.3.0(transitive)
- Removedlodash._reinterpolate@3.0.0(transitive)
- Removedlodash.foreach@4.5.0(transitive)
- Removedlodash.template@4.5.0(transitive)
- Removedlodash.templatesettings@4.2.0(transitive)
- Removedmemory-streams@0.1.3(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedneo-async@2.6.2(transitive)
- Removednwsapi@2.2.10(transitive)
- Removedparse5@6.0.1(transitive)
- Removedpsl@1.9.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedquerystringify@2.2.0(transitive)
- Removedreadable-stream@1.0.34(transitive)
- Removedrequires-port@1.0.0(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsaxes@5.0.1(transitive)
- Removedsimple-html-tokenizer@0.5.11(transitive)
- Removedsource-map@0.1.430.4.40.6.1(transitive)
- Removedsource-map-url@0.3.0(transitive)
- Removedsourcemap-validator@1.1.1(transitive)
- Removedstring_decoder@0.10.31(transitive)
- Removedstrip-bom@3.0.0(transitive)
- Removedsymbol-tree@3.2.4(transitive)
- Removedtough-cookie@4.1.4(transitive)
- Removedtr46@2.1.0(transitive)
- Removedtypescript-memoize@1.1.1(transitive)
- Removeduglify-js@3.17.4(transitive)
- Removeduniversalify@0.2.0(transitive)
- Removedurl-parse@1.5.10(transitive)
- Removedw3c-hr-time@1.0.2(transitive)
- Removedw3c-xmlserializer@2.0.0(transitive)
- Removedwebidl-conversions@5.0.06.1.0(transitive)
- Removedwhatwg-encoding@1.0.5(transitive)
- Removedwhatwg-mimetype@2.3.0(transitive)
- Removedwhatwg-url@8.7.0(transitive)
- Removedwordwrap@1.0.0(transitive)
- Removedwrap-legacy-hbs-plugin-if-needed@1.0.1(transitive)
- Removedws@7.5.9(transitive)
- Removedxml-name-validator@3.0.0(transitive)
- Removedxmlchars@2.2.0(transitive)