Last active
May 28, 2018 21:01
-
-
Save vitch/591d022359bd392535c15c715a59e81a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Script to report the services in an ember app as requested on: | |
// https://github.com/emberjs/ember.js/issues/16134 | |
function findEmberApplication() { | |
let found = findMetaTag('name', /environment$/); | |
if (!found) { | |
throw new Error(`Couldn't find config`); | |
} | |
let config = JSON.parse(unescape(found.getAttribute('content'))); | |
let appName = config.modulePrefix; | |
let application = Ember.Namespace.NAMESPACES_BY_ID[appName]; | |
let owner = application.__deprecatedInstance__; // TODO: Make work with all ember versions | |
return { | |
application, | |
appName, | |
owner, | |
}; | |
} | |
function findServices() { | |
let { appName, owner } = findEmberApplication(); | |
let servicesPath = `${appName}/services/`; | |
return Object.keys(requirejs._eak_seen) | |
.filter((key) => key.startsWith(servicesPath)) | |
.map((key) => key.substr(servicesPath.length)) | |
.map((serviceName) => { | |
let service; | |
try { | |
service = owner.lookup(`service:${serviceName}`); | |
} catch (e) { | |
return; | |
} | |
return { | |
serviceName, | |
service, | |
}; | |
}) | |
.filter((s) => s && s.service); | |
} | |
function eachProp(obj, check) { | |
return keysInObject(obj) | |
.map((key) => { | |
try { | |
let prop = obj[key]; | |
if (check(prop)) { | |
return prop; | |
} | |
} catch (e) { | |
return; | |
} | |
}) | |
.filter((prop) => prop); | |
} | |
function getComputedProperties(obj) { | |
return eachProp(obj, (prop) => prop instanceof Ember.ComputedProperty); | |
} | |
function getAliasedProperties(obj) { | |
return eachProp(obj, (prop) => prop.isDescriptor && prop.altKey); | |
} | |
function getInjectedServices(obj) { | |
return eachProp(obj, (prop) => prop.isDescriptor && prop.type === 'service'); | |
} | |
function getObservers(obj) { | |
return eachProp(obj, (prop) => prop.__ember_observes__); | |
} | |
function getServicesInfo() { | |
let services = findServices(); | |
let servicesInfo = services | |
.map(({ serviceName, service}) => { | |
let computedProperties = getComputedProperties(service); | |
let aliasedProperties = getAliasedProperties(service); | |
let injectedServices = getInjectedServices(service); | |
let observers = getObservers(service); | |
let concatenatedProperties = service.get('concatenatedProperties'); | |
let mergedProperties = service.get('mergedProperties'); | |
let readOnlyComputedProperties = computedProperties.filter((prop) => prop._readOnly); | |
let involatileComputedProperties = computedProperties.reject((prop) => prop._volatile); | |
let volatileComputedProperties = computedProperties.filter((prop) => prop._volatile); | |
return { | |
counts: { | |
aliasedProperties: aliasedProperties.length, | |
computedProperties: computedProperties.length, | |
concatenatedProperties: concatenatedProperties.length, | |
injectedServices: injectedServices.length, | |
involatileComputedProperties: involatileComputedProperties.length, | |
mergedProperties: mergedProperties.length, | |
observers: observers.length, | |
readOnlyComputedProperties: readOnlyComputedProperties.length, | |
volatileComputedProperties: volatileComputedProperties.length, | |
}, | |
hasActions: !!service.actions, | |
isObjectProxy: service instanceof Ember.ObjectProxy, | |
props: { | |
aliasedProperties, | |
computedProperties, | |
concatenatedProperties, | |
injectedServices, | |
involatileComputedProperties, | |
mergedProperties, | |
readOnlyComputedProperties, | |
volatileComputedProperties, | |
}, | |
serviceName, | |
service, | |
}; | |
}); | |
let servicesWhichObjectProxy = servicesInfo.filter((service) => service.isObjectProxy); | |
let servicesWhichHaveActions = servicesInfo.filter((service) => service.hasActions); | |
let counts = ['aliasedProperties', 'concatenatedProperties', 'computedProperties', 'injectedServices', 'mergedProperties', 'observers', 'involatileComputedProperties', 'readOnlyComputedProperties', 'volatileComputedProperties'] | |
.reduce((acc, prop) => { | |
let servicesWithCount = servicesInfo.filter((service) => service.counts[prop]); | |
let totalCount = servicesWithCount | |
.reduce((acc, service) => { | |
acc += service.counts[prop]; | |
return acc; | |
}, 0); | |
acc[prop] = { | |
numServicesWithCount: servicesWithCount.length, | |
servicesWithCount, | |
totalCount, | |
}; | |
return acc; | |
}, {}); | |
console.log(` | |
Total services: ${servicesInfo.length} | |
is an object proxy: ${servicesWhichObjectProxy.length} | |
injects another service: ${counts.injectedServices.totalCount} properties in ${counts.injectedServices.numServicesWithCount} services | |
computed properties: ${counts.computedProperties.totalCount} properties in ${counts.computedProperties.numServicesWithCount} services | |
alias: ${counts.aliasedProperties.totalCount} properties in ${counts.aliasedProperties.numServicesWithCount} services | |
readonly: ${counts.readOnlyComputedProperties.totalCount} properties in ${counts.readOnlyComputedProperties.numServicesWithCount} services | |
involatile computed properties: ${counts.involatileComputedProperties.totalCount} properties in ${counts.involatileComputedProperties.numServicesWithCount} services | |
volatile computed properties: ${counts.volatileComputedProperties.totalCount} properties in ${counts.volatileComputedProperties.numServicesWithCount} services | |
observers: ${counts.observers.totalCount} properties in ${counts.observers.numServicesWithCount} services | |
concatenated properties: ${counts.concatenatedProperties.totalCount} properties in ${counts.concatenatedProperties.numServicesWithCount} services | |
merged properties: ${counts.mergedProperties.totalCount} properties in ${counts.mergedProperties.numServicesWithCount} services | |
actions: ${servicesWhichHaveActions.length} | |
`); | |
return { counts, servicesInfo }; | |
} | |
function keysInObject(obj) { | |
let props = []; | |
for (let prop in obj) { | |
props.push(prop); | |
} | |
return props; | |
} | |
// From ember-inspector/ember_debug/general-debug.js | |
function findMetaTag(attribute, regExp = /.*/) { | |
let metas = document.querySelectorAll(`meta[${attribute}]`); | |
for (let i = 0; i < metas.length; i++) { | |
let match = metas[i].getAttribute(attribute).match(regExp); | |
if (match) { | |
return metas[i]; | |
} | |
} | |
return null; | |
} | |
// Let's do it: | |
getServicesInfo(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment