From b7df5e6687b47d2a5a8ffe9d97560c760830f6e1 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Mon, 28 Oct 2019 20:46:01 -0400 Subject: [PATCH 1/6] add Modifier support --- lib/gather/analyze-ember-object.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gather/analyze-ember-object.js b/lib/gather/analyze-ember-object.js index 7d76270..86af7ca 100644 --- a/lib/gather/analyze-ember-object.js +++ b/lib/gather/analyze-ember-object.js @@ -148,6 +148,7 @@ module.exports = function analyzeEmberObject(possibleEmberObject) { 'Route', 'Component', 'Service', + 'Modifier', 'Helper', 'Router', 'Engine', From 46f4fc65453362b3761e7c304268cb12f0aaa689 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sat, 2 Nov 2019 08:13:14 -0400 Subject: [PATCH 2/6] actually acquire modifiers --- README.md | 14 ++++++++++- lib/gather/analyze-ember-object.js | 38 +++++++++++++++++++++++------- lib/gather/gather-telemetry.js | 13 ++++++++-- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 73af91f..04fda89 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ After `0.5.0`, a few breaking changes occured. ```javascript gatherTelemetryForUrl(url, gatherFunction, puppeteerArgs); ``` - + ## Caveats If the gather function references functions defined outside of the the gather function body, all of those functions must be exported as well. It is strongly suggested that the gather function be self contained, and if functions must be used (code maintainability/readability), that they be defined within the function. If this is not possible, the `gatherTelemetryForUrl` has been enhanced to accept all functions that must go along with the gather function: @@ -90,6 +90,18 @@ gatherTelemetryForUrl(appLocation, gatherFunction, suppportFn1, suppportFn2, ... * `yarn test` +### Debugging + +Debugging telemetry collection will require an app to collect telemetry from. + +For example, in the no-implicit-this codemod, one may add a `debugger;` in `analyzeEmberObject`, which runs inside of puppeteer, and have the `debugger;` / breakpoint triggered after booting an app and running a script like the following defined in the codemod: + +``` +"debug:telemetry": "DEBUG=true node --inspect-brk ./bin/telemetry.js", +``` + +`DEBUG=true` will pass the puppeteer options: `{ headless; false, devtools: true }`, allowing you to inspect telemetry gathering. Without `DEBUG=true`, it is only possible to debug the script that wraps the launching of puppeteer. + ## More info See "Gathering runtime data" section of diff --git a/lib/gather/analyze-ember-object.js b/lib/gather/analyze-ember-object.js index 86af7ca..16db318 100644 --- a/lib/gather/analyze-ember-object.js +++ b/lib/gather/analyze-ember-object.js @@ -1,24 +1,37 @@ -module.exports = function analyzeEmberObject(possibleEmberObject) { +const MODIFIERS_TOKEN = '/modifiers/'; + +module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { if (typeof possibleEmberObject !== 'object' || possibleEmberObject === null) { return undefined; } let eObjDefault = possibleEmberObject.default; + let meta; if (eObjDefault) { if (eObjDefault.isHelperFactory) { return { type: 'Helper', }; - } else if (typeof eObjDefault.proto !== 'function') { + } + + // Potential for eObjDefault to be a native class + // with no superclass, such as a modifier + if (modulePath.includes(MODIFIERS_TOKEN)) { + meta = Ember.meta(eObjDefault); + } + + if (!meta && typeof eObjDefault.proto !== 'function') { return undefined; } } - let proto = possibleEmberObject.default.proto(); + let proto = (eObjDefault.proto || eObjDefault.__proto__)(); // Ember here is assumed to be global when ran within the context of the browser /* globals Ember */ - let meta = Ember.meta(proto); + if (!meta) { + meta = Ember.meta(proto); + } /** * Parses the ember meta with passed key @@ -120,7 +133,7 @@ module.exports = function analyzeEmberObject(possibleEmberObject) { return {}; } const { source } = meta; - const type = getType(source); + const type = getType(source, modulePath); const ownProperties = Object.keys(source).filter(key => !['_super', 'actions'].includes(key)); @@ -141,20 +154,29 @@ module.exports = function analyzeEmberObject(possibleEmberObject) { } }); - function getType(object) { + function getType(object, modulePath) { const types = [ 'Application', 'Controller', 'Route', 'Component', 'Service', - 'Modifier', 'Helper', 'Router', 'Engine', ]; // eslint-disable-next-line no-undef - return types.find(type => Ember[type] && object instanceof Ember[type]) || 'EmberObject'; + let finiteType = types.find(type => Ember[type] && object instanceof Ember[type]); + + if (finiteType) { + return finiteType; + } + + if (modulePath.includes(MODIFIERS_TOKEN)) { + return 'Modifier'; + } + + return 'EmberObject'; } /** diff --git a/lib/gather/gather-telemetry.js b/lib/gather/gather-telemetry.js index 9c65c43..7552580 100644 --- a/lib/gather/gather-telemetry.js +++ b/lib/gather/gather-telemetry.js @@ -1,7 +1,15 @@ const puppeteer = require('puppeteer'); const { setTelemetry } = require('../utils/telemetry'); -const DEFAULT_PUPPETEER_ARGS = { ignoreHTTPSErrors: true }; +const DEFAULT_PUPPETEER_ARGS = Object.assign( + { ignoreHTTPSErrors: true }, + process.env.DEBUG + ? { + headless: false, + devtools: true, + } + : {} +); module.exports = async function gatherTelemetry(url, gatherFn, ...args) { let puppeteerArgs = [...args].pop(); @@ -12,6 +20,7 @@ module.exports = async function gatherTelemetry(url, gatherFn, ...args) { } else { puppeteerArgs = {}; } + Object.assign(puppeteerArgs, DEFAULT_PUPPETEER_ARGS); const browser = await puppeteer.launch(puppeteerArgs); @@ -42,7 +51,7 @@ module.exports = async function gatherTelemetry(url, gatherFn, ...args) { try { let module = require(modulePath); - telemetry[modulePath] = await gFn(module); + telemetry[modulePath] = await gFn(module, modulePath); } catch (error) { // log the error, but continue window.logErrorInNodeProcess(`error evaluating \`${modulePath}\`: ${error.message}`); From cebc51ff38bfd370859e98a101b69b8868b36cfc Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sat, 2 Nov 2019 08:17:12 -0400 Subject: [PATCH 3/6] const needs to be in the analyze function --- lib/gather/analyze-ember-object.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gather/analyze-ember-object.js b/lib/gather/analyze-ember-object.js index 16db318..bb9083a 100644 --- a/lib/gather/analyze-ember-object.js +++ b/lib/gather/analyze-ember-object.js @@ -1,6 +1,6 @@ -const MODIFIERS_TOKEN = '/modifiers/'; - module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { + const MODIFIERS_TOKEN = '/modifiers/'; + if (typeof possibleEmberObject !== 'object' || possibleEmberObject === null) { return undefined; } From 39b19cdb6f22a68dd613332091de88bc5f564852 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sat, 2 Nov 2019 08:29:47 -0400 Subject: [PATCH 4/6] success --- lib/gather/analyze-ember-object.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/gather/analyze-ember-object.js b/lib/gather/analyze-ember-object.js index bb9083a..2019a5e 100644 --- a/lib/gather/analyze-ember-object.js +++ b/lib/gather/analyze-ember-object.js @@ -1,5 +1,6 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { const MODIFIERS_TOKEN = '/modifiers/'; + let isModifier = modulePath.includes(MODIFIERS_TOKEN); if (typeof possibleEmberObject !== 'object' || possibleEmberObject === null) { return undefined; @@ -16,7 +17,7 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { // Potential for eObjDefault to be a native class // with no superclass, such as a modifier - if (modulePath.includes(MODIFIERS_TOKEN)) { + if (isModifier) { meta = Ember.meta(eObjDefault); } @@ -25,7 +26,9 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { } } - let proto = (eObjDefault.proto || eObjDefault.__proto__)(); + let proto = isModifier + ? possibleEmberObject.default.__proto__() + : possibleEmberObject.default.proto(); // Ember here is assumed to be global when ran within the context of the browser /* globals Ember */ @@ -154,7 +157,11 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { } }); - function getType(object, modulePath) { + function getType(object /* , modulePath */) { + if (isModifier) { + return 'Modifier'; + } + const types = [ 'Application', 'Controller', @@ -172,10 +179,6 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { return finiteType; } - if (modulePath.includes(MODIFIERS_TOKEN)) { - return 'Modifier'; - } - return 'EmberObject'; } From e2e4da668707ad837a92c990f28342c0cdb479bc Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sat, 2 Nov 2019 08:45:07 -0400 Subject: [PATCH 5/6] detecting modifiers from packages work. but if a modifier in your app happens to have an EmberObject as its ancestor, that is not detected. It seems only native classes are detected right now --- lib/gather/gather-telemetry.test.js | 49 ++++++++++- .../classic-app/app/modifiers/logger.js | 7 ++ test/fixtures/classic-app/package.json | 2 + test/fixtures/classic-app/yarn.lock | 83 ++++++++++++++++++- 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/classic-app/app/modifiers/logger.js diff --git a/lib/gather/gather-telemetry.test.js b/lib/gather/gather-telemetry.test.js index d46820f..a9ddbfe 100644 --- a/lib/gather/gather-telemetry.test.js +++ b/lib/gather/gather-telemetry.test.js @@ -49,7 +49,54 @@ describe('Provide a personalized `Gathering Function`', () => { test('can determine most Ember types with a robust function', async () => { await gatherTelemetry('http://localhost:4200', analyzeEmberObject); let telemetry = getTelemetry(); - expect(Object.values(telemetry).filter(Boolean).length).toEqual(34); + + let expected = [ + '@ember/render-modifiers/modifiers/did-insert', + '@ember/render-modifiers/modifiers/did-update', + '@ember/render-modifiers/modifiers/will-destroy', + 'ember-ajax/ajax-request', + 'ember-ajax/services/ajax', + 'ember-class-based-modifier/-private/modifier-classic', + 'ember-class-based-modifier/classic', + 'ember-data/adapter', + 'ember-data/adapters/json-api', + 'ember-data/adapters/rest', + 'ember-data/model', + 'ember-data/serializer', + 'ember-data/serializers/json-api', + 'ember-data/serializers/json', + 'ember-data/serializers/rest', + 'ember-data/store', + 'ember-data/transform', + 'ember-data/transforms/boolean', + 'ember-data/transforms/date', + 'ember-data/transforms/number', + 'ember-data/transforms/string', + 'ember-data/transforms/transform', + 'ember-inflector/lib/helpers/pluralize', + 'ember-inflector/lib/helpers/singularize', + 'ember-resolver/index', + 'ember-resolver/resolver', + 'ember-resolver/resolvers/classic/container-debug-adapter', + 'ember-resolver/resolvers/classic/index', + 'ember-welcome-page/components/welcome-page', + 'special-sauce/components/fire-sauce', + 'input/app', + 'input/components/test-component', + 'input/components/welcome-page', + 'input/helpers/app-version', + 'input/helpers/pluralize', + 'input/helpers/singularize', + 'input/modifiers/did-insert', + 'input/modifiers/did-update', + `input/modifiers/logger`, + 'input/modifiers/will-destroy', + 'input/resolver', + 'input/router', + 'input/services/ajax', + ]; + + expect(Object.keys(telemetry)).toEqual(expected); }); test('can handle external functions', async () => { diff --git a/test/fixtures/classic-app/app/modifiers/logger.js b/test/fixtures/classic-app/app/modifiers/logger.js new file mode 100644 index 0000000..89ec0b2 --- /dev/null +++ b/test/fixtures/classic-app/app/modifiers/logger.js @@ -0,0 +1,7 @@ +import Modifier from 'ember-class-based-modifier'; + +export default class LoggerModifier extends Modifier { + didInstall() { + console.log(this.element) + } +} diff --git a/test/fixtures/classic-app/package.json b/test/fixtures/classic-app/package.json index c44c0a1..0f7d480 100644 --- a/test/fixtures/classic-app/package.json +++ b/test/fixtures/classic-app/package.json @@ -20,8 +20,10 @@ "devDependencies": { "@ember/jquery": "^0.6.0", "@ember/optional-features": "^0.7.0", + "@ember/render-modifiers": "^1.0.2", "broccoli-asset-rev": "^3.0.0", "ember-ajax": "^5.0.0", + "ember-class-based-modifier": "^0.10.0", "ember-cli": "~3.10.1", "ember-cli-app-version": "^3.2.0", "ember-cli-babel": "^7.7.3", diff --git a/test/fixtures/classic-app/yarn.lock b/test/fixtures/classic-app/yarn.lock index d3e6f4b..b12360e 100644 --- a/test/fixtures/classic-app/yarn.lock +++ b/test/fixtures/classic-app/yarn.lock @@ -736,6 +736,14 @@ ember-cli-babel "^6.16.0" ember-compatibility-helpers "^1.1.1" +"@ember/render-modifiers@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444" + integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ== + dependencies: + ember-cli-babel "^7.10.0" + ember-modifier-manager-polyfill "^1.1.0" + "@ember/test-helpers@^1.5.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.6.0.tgz#e928c0190a19c312bf40dc8a6f4159735af48a7f" @@ -1341,6 +1349,13 @@ babel-plugin-debug-macros@^0.3.0: dependencies: semver "^5.3.0" +babel-plugin-ember-modules-api-polyfill@^2.12.0: + version "2.12.0" + resolved "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.12.0.tgz#a5e703205ba4e625a7fab9bb1aea64ef3222cf75" + integrity sha512-ZQU4quX0TJ1yYyosPy5PFigKdCFEVHJ6H0b3hwjxekIP9CDwzk0OhQuKhCOPti+d52VWjjCjxu2BrXEih29mFw== + dependencies: + ember-rfc176-data "^0.3.12" + babel-plugin-ember-modules-api-polyfill@^2.6.0, babel-plugin-ember-modules-api-polyfill@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.9.0.tgz#8503e7b4192aeb336b00265e6235258ff6b754aa" @@ -1932,6 +1947,23 @@ broccoli-babel-transpiler@^7.1.2, broccoli-babel-transpiler@^7.2.0: rsvp "^4.8.4" workerpool "^3.1.1" +broccoli-babel-transpiler@^7.3.0: + version "7.3.0" + resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-7.3.0.tgz#a0ad3a37dbf74469664bbca403d652070c2c1317" + integrity sha512-tsXNvDf3gp6g8rGkz234AhbaIRUsCdd6CM3ikfkJVB0EpC8ZAczGsFKTjENLy1etx4s7FkruW/QjI7Wfdhx6Ng== + dependencies: + "@babel/core" "^7.3.3" + "@babel/polyfill" "^7.0.0" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + broccoli-persistent-filter "^2.2.1" + clone "^2.1.2" + hash-for-dep "^1.4.7" + heimdalljs-logger "^0.1.9" + json-stable-stringify "^1.0.1" + rsvp "^4.8.4" + workerpool "^3.1.1" + broccoli-builder@^0.18.14: version "0.18.14" resolved "https://registry.yarnpkg.com/broccoli-builder/-/broccoli-builder-0.18.14.tgz#4b79e2f844de11a4e1b816c3f49c6df4776c312d" @@ -3046,6 +3078,14 @@ ember-assign-polyfill@^2.6.0: ember-cli-babel "^6.16.0" ember-cli-version-checker "^2.0.0" +ember-class-based-modifier@^0.10.0: + version "0.10.0" + resolved "https://registry.npmjs.org/ember-class-based-modifier/-/ember-class-based-modifier-0.10.0.tgz#bb40c05440a959d84e9e2f5038e3894773686d19" + integrity sha512-GPPOCYmRibGBUfiuq7oHQAGXgM6X8LK2I2crvQadqwbft5PjXDbR6x1xnOQ8TDWeOE0EluahXXOgWgdUVcmaMQ== + dependencies: + ember-cli-babel "^7.10.0" + ember-modifier-manager-polyfill "^1.2.0" + ember-cli-app-version@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ember-cli-app-version/-/ember-cli-app-version-3.2.0.tgz#7b9ad0e1b63ae0518648356ee24c703e922bc26e" @@ -3105,6 +3145,33 @@ ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.2, ember-cli-babel@^7.4.1, ember-cl ensure-posix-path "^1.0.2" semver "^5.5.0" +ember-cli-babel@^7.10.0: + version "7.12.0" + resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-7.12.0.tgz#064997d199384be8c88d251f30ef67953d3bddc5" + integrity sha512-+EGQsbPvh19nNXHCm6rVBx2CdlxQlzxMyhey5hsGViDPriDI4PFYXYaFWdGizDrmZoDcG/Ywpeph3hl0NxGQTg== + dependencies: + "@babel/core" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.3.4" + "@babel/plugin-proposal-decorators" "^7.3.0" + "@babel/plugin-transform-modules-amd" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.2.0" + "@babel/polyfill" "^7.0.0" + "@babel/preset-env" "^7.0.0" + "@babel/runtime" "^7.2.0" + amd-name-resolver "^1.2.1" + babel-plugin-debug-macros "^0.3.0" + babel-plugin-ember-modules-api-polyfill "^2.12.0" + babel-plugin-module-resolver "^3.1.1" + broccoli-babel-transpiler "^7.3.0" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.1" + broccoli-source "^1.1.0" + clone "^2.1.2" + ember-cli-babel-plugin-helpers "^1.1.0" + ember-cli-version-checker "^2.1.2" + ensure-posix-path "^1.0.2" + semver "^5.5.0" + ember-cli-broccoli-sane-watcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ember-cli-broccoli-sane-watcher/-/ember-cli-broccoli-sane-watcher-3.0.0.tgz#dc1812c047e1ceec4413d3c41b51a9ffc61b4cfe" @@ -3385,7 +3452,7 @@ ember-cli@~3.10.1: watch-detector "^0.1.0" yam "^1.0.0" -ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2: +ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.0.tgz#feee16c5e9ef1b1f1e53903b241740ad4b01097e" integrity sha512-pUW4MzJdcaQtwGsErYmitFRs0rlCYBAnunVzlFFUBr4xhjlCjgHJo0b53gFnhTgenNM3d3/NqLarzRhDTjXRTg== @@ -3457,6 +3524,15 @@ ember-maybe-import-regenerator@^0.1.6: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" +ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda" + integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA== + dependencies: + ember-cli-babel "^7.10.0" + ember-cli-version-checker "^2.1.2" + ember-compatibility-helpers "^1.2.0" + ember-qunit@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-4.4.1.tgz#3654cadf9fa7e2287fe7b61fc7f19c3eb06222b5" @@ -3483,6 +3559,11 @@ ember-resolver@^5.0.1: ember-cli-version-checker "^3.0.0" resolve "^1.10.0" +ember-rfc176-data@^0.3.12: + version "0.3.12" + resolved "https://registry.npmjs.org/ember-rfc176-data/-/ember-rfc176-data-0.3.12.tgz#90d82878e69e2ac9a5438e8ce14d12c6031c5bd2" + integrity sha512-g9HeZj/gU5bfIIrGXkP7MhS2b3Vu5DfNUrYr14hy99TgIvtZETO+96QF4WOEUXGjIJdfTRjerVnQlqngPQSv1g== + ember-rfc176-data@^0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.9.tgz#44b6e051ead6c044ea87bd551f402e2cf89a7e3d" From 7aeecc7fe5c0211fc515c1a779ba8066bd48a7c6 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sat, 2 Nov 2019 09:00:45 -0400 Subject: [PATCH 6/6] it works! --- lib/gather/analyze-ember-object.js | 6 ++---- package.json | 1 + scripts/debug.js | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100755 scripts/debug.js diff --git a/lib/gather/analyze-ember-object.js b/lib/gather/analyze-ember-object.js index 2019a5e..d9ed93f 100644 --- a/lib/gather/analyze-ember-object.js +++ b/lib/gather/analyze-ember-object.js @@ -26,13 +26,11 @@ module.exports = function analyzeEmberObject(possibleEmberObject, modulePath) { } } - let proto = isModifier - ? possibleEmberObject.default.__proto__() - : possibleEmberObject.default.proto(); - // Ember here is assumed to be global when ran within the context of the browser /* globals Ember */ if (!meta) { + let proto = possibleEmberObject.default.proto(); + meta = Ember.meta(proto); } diff --git a/package.json b/package.json index d232d43..35ed5c4 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ ], "main": "lib/index.js", "scripts": { + "debug": "DEBUG=true node scripts/debug.js", "lint:js": "eslint .", "test": "jest . --verbose --no-watchman --runInBand --forceExit" }, diff --git a/scripts/debug.js b/scripts/debug.js new file mode 100755 index 0000000..37f7950 --- /dev/null +++ b/scripts/debug.js @@ -0,0 +1,5 @@ +'use strict'; + +const { gatherTelemetryForUrl, analyzeEmberObject } = require('../lib'); + +gatherTelemetryForUrl(process.argv[2], analyzeEmberObject);