├── .editorconfig ├── .ember-cli ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .template-lintrc.js ├── .travis.yml ├── .watchmanconfig ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── addon └── index.js ├── config ├── ember-try.js └── environment.js ├── ember-cli-build.js ├── index.js ├── package.json ├── testem.js ├── tests ├── .eslintrc.js ├── dummy │ ├── app │ │ ├── app.js │ │ ├── components │ │ │ └── .gitkeep │ │ ├── controllers │ │ │ ├── .gitkeep │ │ │ ├── application.js │ │ │ └── index.js │ │ ├── helpers │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── models │ │ │ └── .gitkeep │ │ ├── resolver.js │ │ ├── router.js │ │ ├── routes │ │ │ ├── .gitkeep │ │ │ └── index.js │ │ ├── styles │ │ │ └── app.css │ │ └── templates │ │ │ ├── application.hbs │ │ │ ├── components │ │ │ └── .gitkeep │ │ │ └── index.hbs │ ├── config │ │ ├── environment.js │ │ ├── optional-features.json │ │ └── targets.js │ └── public │ │ ├── crossdomain.xml │ │ └── robots.txt ├── helpers │ └── .gitkeep ├── index.html ├── integration │ └── .gitkeep ├── test-helper.js └── unit │ ├── .gitkeep │ └── strict-resolver │ └── basic-test.js ├── vendor └── .gitkeep └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | ecmaVersion: 2018, 8 | sourceType: 'module', 9 | ecmaFeatures: { 10 | legacyDecorators: true 11 | } 12 | }, 13 | plugins: [ 14 | 'ember' 15 | ], 16 | extends: [ 17 | 'eslint:recommended', 18 | 'plugin:ember/recommended' 19 | ], 20 | env: { 21 | browser: true 22 | }, 23 | rules: { 24 | 'ember/no-jquery': 'error' 25 | }, 26 | overrides: [ 27 | // node files 28 | { 29 | files: [ 30 | '.eslintrc.js', 31 | '.template-lintrc.js', 32 | 'ember-cli-build.js', 33 | 'index.js', 34 | 'testem.js', 35 | 'blueprints/*/index.js', 36 | 'config/**/*.js', 37 | 'tests/dummy/config/**/*.js' 38 | ], 39 | excludedFiles: [ 40 | 'addon/**', 41 | 'addon-test-support/**', 42 | 'app/**', 43 | 'tests/dummy/app/**' 44 | ], 45 | parserOptions: { 46 | sourceType: 'script' 47 | }, 48 | env: { 49 | browser: false, 50 | node: true 51 | }, 52 | plugins: ['node'], 53 | rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { 54 | // add your custom rules and overrides for node files here 55 | }) 56 | } 57 | ] 58 | }; 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist/ 5 | /tmp/ 6 | 7 | # dependencies 8 | /bower_components/ 9 | /node_modules/ 10 | 11 | # misc 12 | /.env* 13 | /.pnp* 14 | /.sass-cache 15 | /connect.lock 16 | /coverage/ 17 | /libpeerconnection.log 18 | /npm-debug.log* 19 | /testem.log 20 | /yarn-error.log 21 | 22 | # ember-try 23 | /.node_modules.ember-try/ 24 | /bower.json.ember-try 25 | /package.json.ember-try 26 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /bower_components 2 | /config/ember-try.js 3 | /dist 4 | /tests 5 | /tmp 6 | **/.gitkeep 7 | .bowerrc 8 | .editorconfig 9 | .ember-cli 10 | .gitignore 11 | .eslintrc.js 12 | .watchmanconfig 13 | .travis.yml 14 | bower.json 15 | ember-cli-build.js 16 | testem.js 17 | -------------------------------------------------------------------------------- /.template-lintrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | extends: 'recommended' 5 | }; 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | language: node_js 4 | node_js: 5 | - "10" 6 | 7 | sudo: false 8 | 9 | cache: 10 | yarn: true 11 | 12 | env: 13 | EMBER_TRY_SCENARIO=ember-lts-3.12 14 | EMBER_TRY_SCENARIO=ember-lts-3.16 15 | EMBER_TRY_SCENARIO=ember-release 16 | EMBER_TRY_SCENARIO=ember-beta 17 | EMBER_TRY_SCENARIO=ember-canary 18 | EMBER_TRY_SCENARIO=ember-default-with-jquery 19 | EMBER_TRY_SCENARIO=ember-classic 20 | 21 | matrix: 22 | fast_finish: true 23 | allow_failures: 24 | - env: EMBER_TRY_SCENARIO=ember-canary 25 | 26 | before_install: 27 | - curl -o- -L https://yarnpkg.com/install.sh | bash 28 | - export PATH=$HOME/.yarn/bin:$PATH 29 | - yarn global add phantomjs-prebuilt 30 | - phantomjs --version 31 | 32 | install: 33 | - yarn install --no-lockfile 34 | 35 | script: 36 | # Usually, it's ok to finish the test scenario without reverting 37 | # to the addon's original dependency state, skipping "cleanup". 38 | - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup 39 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.3.0 (10/09/2020) 2 | 3 | - [dependencies] bumps `ember-cli-htmlbars@4.2.3` -> `ember-cli-htmlbars@5.3.1` 4 | 5 | # 1.2.1 (08/24/2020) 6 | 7 | - [bug] resolver.moduleBasedResolver must be set for the ember router to enable loading substates, so set that property in the constructor. 8 | 9 | # 1.2.0 (05/25/2020) 10 | 11 | - [enhancement] bring down upstream, `ember-resolver`, parsing logic, ensures that we don't assert against types that are not required to be dasherized and also put that behind a debug flag 12 | - [bug] ensure that require key exists before trying to retrieve from the require registry 13 | 14 | # 1.1.1 (05/21/2020) 15 | 16 | - Ensure internal `layoutFor` lookups for namespaced templates works 17 | 18 | # 1.1.0 (04/07/2020) 19 | 20 | - Fix uses of resolveRegistration('config:environment'). This works in the ember-resolver/classic as there is a hard coded rule that says to not pluralize config. This adds a similar rule but in the form of a strict requirement rather than a part of a pluralize strategy like ember-resolver/classic. 21 | 22 | # 1.0.0 (03/30/2020) 23 | 24 | - bumps all dependencies to support ember>=3.12 25 | 26 | # 0.2.1 (03/27/2020) 27 | 28 | - Removes monkey patch for registry caching and make it an opt via readme instructions 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How To Contribute 2 | 3 | ## Installation 4 | 5 | * `git clone ` 6 | * `cd ember-strict-resolver` 7 | * `npm install` 8 | 9 | ## Linting 10 | 11 | * `npm run lint:hbs` 12 | * `npm run lint:js` 13 | * `npm run lint:js -- --fix` 14 | 15 | ## Running tests 16 | 17 | * `ember test` – Runs the test suite on the current Ember version 18 | * `ember test --server` – Runs the test suite in "watch mode" 19 | * `ember try:each` – Runs the test suite against multiple Ember versions 20 | 21 | ## Running the dummy application 22 | 23 | * `ember serve` 24 | * Visit the dummy application at [http://localhost:4200](http://localhost:4200). 25 | 26 | For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/). 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ember-strict-resolver 2 | 3 | [![Build Status](https://travis-ci.org/stefanpenner/ember-strict-resolver.svg?branch=master)](https://travis-ci.org/stefanpenner/ember-strict-resolver) 4 | 5 | Fast, concise, zero fun resolver for ember apps. 6 | 7 | ## installation 8 | ``` 9 | ember install ember-strict-resolver 10 | ``` 11 | 12 | ## Usage 13 | 14 | in app/resolver.js 15 | ```js 16 | export { default } from 'ember-strict-resolver'; 17 | ``` 18 | 19 | _For additional improvements when fully using the ember-strict-resolver monkey patching the registry to no longer cache and simply returning the values passed like the following can be produce extra performance._ 20 | 21 | ```js 22 | // disable the normalization cache as we no longer normalize, the cache has become a bottle neck. 23 | Ember.Registry.prototype.normalize = function (i) { return i; } 24 | ``` 25 | 26 | ## Migration 27 | 28 | Migrating away from use the _ember-resolver/classic_ can be done in piecemeal by supporting a sub-set of the old resolution formats. 29 | 30 | > normalize is needed, because without it you will get errors related to failing to be able to inject services that were never normalized in the registry. 31 | 32 | ```js 33 | // app/resolver.js 34 | 35 | import Resolver from 'ember-strict-resolver'; 36 | 37 | export default class extends Resolver { 38 | legacyMappings = { 39 | 'service:camelCaseNotSupported': 'service:camel-case-not-supported' 40 | }; 41 | 42 | resolve(_fullName) { 43 | return super.resolve(this.legacyMappings[_fullName] || _fullName); 44 | } 45 | 46 | normalize(_fullName) { 47 | return this.legacyMappings[_fullName] || _fullName; 48 | } 49 | } 50 | ``` 51 | 52 | This will allow you file PRs with libraries that currently do not support the strict resolver in its entirety. 53 | 54 | In the event that you have a component that is failing to resolve correctly with the error `Attempted to lookup "helper:nameOfVariable". Use "helper:name-of-variable" instead.` please convert your template to use explicit-this. The template lint can be enabled by turning on [no-implicit-this](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-implicit-this.md). 55 | 56 | An example of what this looks like is the following 57 | 58 | ```hbs 59 | // addon/components/templates/foo.hbs 60 | 61 |
62 | {{fullName}} 63 |
64 | ``` 65 | 66 | This will result in the error, `Attempted to lookup "helper:fullName". Use "helper:full-name" instead.`. The fix for this would be to decide if this is a argument being passed into foo or if this is a local property. 67 | 68 | _fullName_ is coming from an invocation of _Foo_ like the following: 69 | 70 | ``` 71 | 74 | ``` 75 | 76 | Then the fix for your template would be: 77 | 78 | ```hbs 79 | // addon/components/templates/foo.hbs 80 | 81 |
82 | {{@fullName}} 83 |
84 | ``` 85 | 86 | If _fullName_ is a property on your component the fix would be: 87 | 88 | ```hbs 89 | // addon/components/templates/foo.hbs 90 | 91 |
92 | {{this.fullName}} 93 |
94 | ``` 95 | 96 | # Development of the addon 97 | 98 | * `git clone ` this repository 99 | * `cd strict-resolver` 100 | * `yarn install` 101 | 102 | ## Running 103 | 104 | * `ember serve` 105 | * Visit your app at [http://localhost:4200](http://localhost:4200). 106 | 107 | ## Running Tests 108 | 109 | * `npm test` (Runs `ember try:each` to test your addon against multiple Ember versions) 110 | * `ember test` 111 | * `ember test --server` 112 | 113 | ## Building 114 | 115 | * `ember build` 116 | 117 | For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/). 118 | -------------------------------------------------------------------------------- /addon/index.js: -------------------------------------------------------------------------------- 1 | /* globals requirejs */ 2 | 3 | import { warn } from '@ember/debug'; 4 | import { dasherize } from '@ember/string'; 5 | import { DEBUG } from '@glimmer/env'; 6 | 7 | import require from 'require'; 8 | 9 | export default class Resolver { 10 | constructor(attrs) { 11 | if (attrs) { 12 | this.namespace = attrs.namespace; 13 | } 14 | // secret handshake with router to ensure substates are enabled 15 | // see https://github.com/emberjs/ember.js/blob/a429dc327ee6ef97d948a83e727886c75c6fe043/packages/%40ember/-internals/routing/lib/system/router.ts#L344 16 | this.moduleBasedResolver = true; 17 | } 18 | 19 | static create(args) { 20 | return new this(args); 21 | } 22 | 23 | has(moduleName) { 24 | return moduleName in (requirejs.entries || requirejs._eak_seen); 25 | } 26 | 27 | parseFullName(fullName) { 28 | let prefix, type, name; 29 | 30 | let fullNameParts = fullName.split('@'); 31 | 32 | if (fullNameParts.length === 3) { 33 | if (fullNameParts[0].length === 0) { 34 | // leading scoped namespace: `@scope/pkg@type:name` 35 | prefix = `@${fullNameParts[1]}`; 36 | let prefixParts = fullNameParts[2].split(':'); 37 | type = prefixParts[0]; 38 | name = prefixParts[1]; 39 | } else { 40 | // interweaved scoped namespace: `type:@scope/pkg@name` 41 | prefix = `@${fullNameParts[1]}`; 42 | type = fullNameParts[0].slice(0, -1); 43 | name = fullNameParts[2]; 44 | } 45 | 46 | if (type === 'template:components') { 47 | name = `components/${name}`; 48 | type = 'template'; 49 | } 50 | } else if (fullNameParts.length === 2) { 51 | let prefixParts = fullNameParts[0].split(':'); 52 | 53 | if (prefixParts.length === 2) { 54 | if (prefixParts[1].length === 0) { 55 | type = prefixParts[0]; 56 | name = `@${fullNameParts[1]}`; 57 | } else { 58 | prefix = prefixParts[1]; 59 | type = prefixParts[0]; 60 | name = fullNameParts[1]; 61 | } 62 | } else { 63 | let nameParts = fullNameParts[1].split(':'); 64 | 65 | prefix = fullNameParts[0]; 66 | type = nameParts[0]; 67 | name = nameParts[1]; 68 | } 69 | 70 | if (type === 'template' && prefix.lastIndexOf('components/', 0) === 0) { 71 | name = `components/${name}`; 72 | prefix = prefix.slice(11); 73 | } 74 | } else { 75 | fullNameParts = fullName.split(':'); 76 | 77 | prefix = this.namespace.modulePrefix; 78 | type = fullNameParts[0]; 79 | name = fullNameParts[1]; 80 | } 81 | 82 | return { 83 | prefix, 84 | type, 85 | name 86 | } 87 | } 88 | 89 | moduleNameForFullName(fullName) { 90 | let moduleName; 91 | 92 | const { prefix, type, name } = this.parseFullName(fullName); 93 | 94 | if (name === 'main') { 95 | moduleName = `${prefix}/${type}`; 96 | } else if (type === 'engine') { 97 | moduleName = `${name}/engine`; 98 | } else if (type === 'route-map') { 99 | moduleName = `${name}/routes`; 100 | } else if (type === 'config') { 101 | moduleName = `${prefix}/${type}/${name.replace(/\./g, '/')}`; 102 | } else { 103 | moduleName = `${prefix}/${type}s/${name.replace(/\./g, '/')}`; 104 | } 105 | 106 | return moduleName; 107 | } 108 | 109 | resolve(fullName) { 110 | const moduleName = this.moduleNameForFullName(fullName); 111 | 112 | if (this.has(moduleName)) { 113 | // hit 114 | return require(moduleName)['default']; 115 | } 116 | // miss 117 | } 118 | 119 | normalize(fullName) { 120 | if(DEBUG) { 121 | const { type } = this.parseFullName(fullName); 122 | 123 | if(['service'].includes(type)) { 124 | warn(`Attempted to lookup "${fullName}". Use "${dasherize(fullName)}" instead.`, !fullName.match(/[a-z]+[A-Z]+/), { id: 'ember-strict-resolver.camelcase-names' }); 125 | } 126 | } 127 | 128 | return fullName; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /config/ember-try.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const getChannelURL = require('ember-source-channel-url'); 4 | 5 | module.exports = async function() { 6 | return { 7 | useYarn: true, 8 | scenarios: [ 9 | { 10 | name: 'ember-lts-3.12', 11 | npm: { 12 | devDependencies: { 13 | 'ember-source': '~3.12.0' 14 | } 15 | } 16 | }, 17 | { 18 | name: 'ember-lts-3.16', 19 | npm: { 20 | devDependencies: { 21 | 'ember-source': '~3.16.0' 22 | } 23 | } 24 | }, 25 | { 26 | name: 'ember-release', 27 | npm: { 28 | devDependencies: { 29 | 'ember-source': await getChannelURL('release') 30 | } 31 | } 32 | }, 33 | { 34 | name: 'ember-beta', 35 | npm: { 36 | devDependencies: { 37 | 'ember-source': await getChannelURL('beta') 38 | } 39 | } 40 | }, 41 | { 42 | name: 'ember-canary', 43 | npm: { 44 | devDependencies: { 45 | 'ember-source': await getChannelURL('canary') 46 | } 47 | } 48 | }, 49 | // The default `.travis.yml` runs this scenario via `npm test`, 50 | // not via `ember try`. It's still included here so that running 51 | // `ember try:each` manually or from a customized CI config will run it 52 | // along with all the other scenarios. 53 | { 54 | name: 'ember-default', 55 | npm: { 56 | devDependencies: {} 57 | } 58 | }, 59 | { 60 | name: 'ember-default-with-jquery', 61 | env: { 62 | EMBER_OPTIONAL_FEATURES: JSON.stringify({ 63 | 'jquery-integration': true 64 | }) 65 | }, 66 | npm: { 67 | devDependencies: { 68 | '@ember/jquery': '^0.5.1' 69 | } 70 | } 71 | }, 72 | { 73 | name: 'ember-classic', 74 | env: { 75 | EMBER_OPTIONAL_FEATURES: JSON.stringify({ 76 | 'application-template-wrapper': true, 77 | 'default-async-observers': false, 78 | 'template-only-glimmer-components': false 79 | }) 80 | }, 81 | npm: { 82 | ember: { 83 | edition: 'classic' 84 | } 85 | } 86 | } 87 | ] 88 | }; 89 | }; 90 | -------------------------------------------------------------------------------- /config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(/* environment, appConfig */) { 4 | return { }; 5 | }; 6 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); 4 | 5 | module.exports = function(defaults) { 6 | let app = new EmberAddon(defaults, { 7 | // Add options here 8 | }); 9 | 10 | /* 11 | This build file specifies the options for the dummy test app of this 12 | addon, located in `/tests/dummy` 13 | This build file does *not* influence how the addon or the app using it 14 | behave. You most likely want to be modifying `./index.js` or app's build file 15 | */ 16 | 17 | return app.toTree(); 18 | }; 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | name: require('./package').name 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-strict-resolver", 3 | "version": "1.3.0", 4 | "description": "A fast concise resolver for ember", 5 | "keywords": [ 6 | "ember-addon" 7 | ], 8 | "license": "MIT", 9 | "author": "Stefan Penner = 12" 64 | }, 65 | "ember": { 66 | "edition": "octane" 67 | }, 68 | "ember-addon": { 69 | "configPath": "tests/dummy/config" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /testem.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | test_page: 'tests/index.html?hidepassed', 5 | disable_watching: true, 6 | launch_in_ci: [ 7 | 'Chrome' 8 | ], 9 | launch_in_dev: [ 10 | 'Chrome' 11 | ], 12 | browser_start_timeout: 120, 13 | browser_args: { 14 | Chrome: { 15 | ci: [ 16 | // --no-sandbox is needed when running Chrome inside a container 17 | process.env.CI ? '--no-sandbox' : null, 18 | '--headless', 19 | '--disable-dev-shm-usage', 20 | '--disable-software-rasterizer', 21 | '--mute-audio', 22 | '--remote-debugging-port=0', 23 | '--window-size=1440,900' 24 | ].filter(Boolean) 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /tests/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | embertest: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /tests/dummy/app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from 'ember-strict-resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | export default class App extends Application { 7 | modulePrefix = config.modulePrefix; 8 | podModulePrefix = config.podModulePrefix; 9 | Resolver = Resolver; 10 | } 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | -------------------------------------------------------------------------------- /tests/dummy/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/controllers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/application.js: -------------------------------------------------------------------------------- 1 | export { default } from './index'; 2 | -------------------------------------------------------------------------------- /tests/dummy/app/controllers/index.js: -------------------------------------------------------------------------------- 1 | export default class Index { 2 | static create(attrs) { 3 | return new this(attrs); 4 | } 5 | 6 | setProperties(properties) { 7 | Object.assign(this, properties); 8 | } 9 | 10 | static proto() { 11 | return { 12 | queryParams: [] 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/dummy/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | 12 | 13 | 14 | 15 | {{content-for "head-footer"}} 16 | 17 | 18 | {{content-for "body"}} 19 | 20 | 21 | 22 | 23 | {{content-for "body-footer"}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/dummy/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/models/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/resolver.js: -------------------------------------------------------------------------------- 1 | export { default } from 'ember-strict-resolver'; 2 | -------------------------------------------------------------------------------- /tests/dummy/app/router.js: -------------------------------------------------------------------------------- 1 | import EmberRouter from '@ember/routing/router'; 2 | import config from './config/environment'; 3 | 4 | export default class Router extends EmberRouter { 5 | location = config.locationType; 6 | rootURL = config.rootURL; 7 | } 8 | 9 | Router.map(function() { 10 | }); 11 | -------------------------------------------------------------------------------- /tests/dummy/app/routes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/routes/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/routes/index.js: -------------------------------------------------------------------------------- 1 | import Route from '@ember/routing/route'; 2 | 3 | export default Route.extend({}); 4 | -------------------------------------------------------------------------------- /tests/dummy/app/styles/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/styles/app.css -------------------------------------------------------------------------------- /tests/dummy/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 |

Welcome to Ember

2 | 3 | {{outlet}} -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/dummy/app/templates/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/templates/index.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} 2 | -------------------------------------------------------------------------------- /tests/dummy/config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(environment) { 4 | let ENV = { 5 | modulePrefix: 'dummy', 6 | environment, 7 | rootURL: '/', 8 | locationType: 'auto', 9 | EmberENV: { 10 | FEATURES: { 11 | // Here you can enable experimental features on an ember canary build 12 | // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true 13 | }, 14 | EXTEND_PROTOTYPES: { 15 | // Prevent Ember Data from overriding Date.parse. 16 | Date: false 17 | } 18 | }, 19 | 20 | APP: { 21 | // Here you can pass flags/options to your application instance 22 | // when it is created 23 | } 24 | }; 25 | 26 | if (environment === 'development') { 27 | // ENV.APP.LOG_RESOLVER = true; 28 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 29 | // ENV.APP.LOG_TRANSITIONS = true; 30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 31 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 32 | } 33 | 34 | if (environment === 'test') { 35 | // Testem prefers this... 36 | ENV.locationType = 'none'; 37 | 38 | // keep test console output quieter 39 | ENV.APP.LOG_ACTIVE_GENERATION = false; 40 | ENV.APP.LOG_VIEW_LOOKUPS = false; 41 | 42 | ENV.APP.rootElement = '#ember-testing'; 43 | ENV.APP.autoboot = false; 44 | } 45 | 46 | if (environment === 'production') { 47 | // here you can enable a production-specific feature 48 | } 49 | 50 | return ENV; 51 | }; 52 | -------------------------------------------------------------------------------- /tests/dummy/config/optional-features.json: -------------------------------------------------------------------------------- 1 | { 2 | "application-template-wrapper": false, 3 | "default-async-observers": true, 4 | "jquery-integration": false, 5 | "template-only-glimmer-components": true 6 | } 7 | -------------------------------------------------------------------------------- /tests/dummy/config/targets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const browsers = [ 4 | 'last 1 Chrome versions', 5 | 'last 1 Firefox versions', 6 | 'last 1 Safari versions' 7 | ]; 8 | 9 | const isCI = !!process.env.CI; 10 | const isProduction = process.env.EMBER_ENV === 'production'; 11 | 12 | if (isCI || isProduction) { 13 | browsers.push('ie 11'); 14 | } 15 | 16 | module.exports = { 17 | browsers 18 | }; 19 | -------------------------------------------------------------------------------- /tests/dummy/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /tests/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /tests/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/integration/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/integration/.gitkeep -------------------------------------------------------------------------------- /tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import Application from '../app'; 2 | import config from '../config/environment'; 3 | import { setApplication } from '@ember/test-helpers'; 4 | import { start } from 'ember-qunit'; 5 | 6 | setApplication(Application.create(config.APP)); 7 | 8 | start(); 9 | -------------------------------------------------------------------------------- /tests/unit/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/tests/unit/.gitkeep -------------------------------------------------------------------------------- /tests/unit/strict-resolver/basic-test.js: -------------------------------------------------------------------------------- 1 | /* globals define, requirejs */ 2 | 3 | import { assign } from '@ember/polyfills'; 4 | import { module, test } from 'qunit'; 5 | import { setupTest } from 'ember-qunit'; 6 | import Resolver from 'ember-strict-resolver'; 7 | 8 | let originalRegistryEntries, resolver; 9 | 10 | function setupResolver(options) { 11 | if (!options) { 12 | options = { namespace: { modulePrefix: 'foo-bar' } }; 13 | } 14 | 15 | resolver = Resolver.create(options); 16 | } 17 | 18 | function resetRegistry() { 19 | requirejs.clear(); 20 | assign(requirejs.entries, originalRegistryEntries); 21 | } 22 | 23 | module('Unit | strict-resolver | basic', function(hooks) { 24 | setupTest(hooks); 25 | 26 | hooks.beforeEach(function() { 27 | originalRegistryEntries = assign({}, requirejs.entries); 28 | 29 | setupResolver(); 30 | }); 31 | 32 | hooks.afterEach(function() { 33 | resetRegistry(); 34 | }); 35 | 36 | test('does not require `namespace` to exist at `init` time', function(assert) { 37 | assert.expect(0); 38 | 39 | Resolver.create(); 40 | }); 41 | 42 | test('is module based', function (assert) { 43 | assert.strictEqual( 44 | resolver.moduleBasedResolver, 45 | true, 46 | 'resolver declares itself module-based to enable router features' 47 | ); 48 | }); 49 | 50 | test('moduleNameForFullName', function (assert) { 51 | const testPairs = [ 52 | ['route:application', 'foo-bar/routes/application'], 53 | ['route:application/index', 'foo-bar/routes/application/index'], 54 | ['application:main', 'foo-bar/application'], 55 | ['route:foo.bar.baz.index', 'foo-bar/routes/foo/bar/baz/index'], 56 | ['config:environment', 'foo-bar/config/environment'] 57 | ]; 58 | 59 | assert.expect(testPairs.length); 60 | 61 | testPairs.forEach(pair => { 62 | assert.equal(resolver.moduleNameForFullName(pair[0]), 63 | pair[1], 64 | `fullName was not resolved correctly for ${pair[0]}`) 65 | }) 66 | }); 67 | 68 | test('can lookup something', function(assert){ 69 | assert.expect(2); 70 | 71 | define('foo-bar/adapters/post', [], function(){ 72 | assert.ok(true, "adapter was invoked properly"); 73 | 74 | return {}; 75 | }); 76 | 77 | var adapter = resolver.resolve('adapter:post'); 78 | 79 | assert.ok(adapter, 'adapter was returned'); 80 | }); 81 | 82 | test("can lookup something in another namespace", function(assert){ 83 | assert.expect(3); 84 | 85 | let expected = {}; 86 | 87 | define('other/adapters/post', [], function(){ 88 | assert.ok(true, "adapter was invoked properly"); 89 | 90 | return { 91 | default: expected 92 | }; 93 | }); 94 | 95 | var adapter = resolver.resolve('other@adapter:post'); 96 | 97 | assert.ok(adapter, 'adapter was returned'); 98 | assert.equal(adapter, expected, 'default export was returned'); 99 | }); 100 | 101 | test("can lookup something in another namespace with different syntax", function(assert){ 102 | assert.expect(3); 103 | 104 | let expected = {}; 105 | define('other/adapters/post', [], function(){ 106 | assert.ok(true, "adapter was invoked properly"); 107 | 108 | return { default: expected }; 109 | }); 110 | 111 | var adapter = resolver.resolve('adapter:other@post'); 112 | 113 | assert.ok(adapter, 'adapter was returned'); 114 | assert.equal(adapter, expected, 'default export was returned'); 115 | }); 116 | 117 | test("can lookup a helper", function(assert) { 118 | assert.expect(3); 119 | 120 | let expected = { isHelperInstance: true }; 121 | define('foo-bar/helpers/reverse-list', [], function(){ 122 | assert.ok(true, "helper was invoked properly"); 123 | 124 | return { default: expected }; 125 | }); 126 | 127 | var helper = resolver.resolve('helper:reverse-list'); 128 | 129 | assert.ok(helper, 'helper was returned'); 130 | assert.equal(helper, expected, 'default export was returned'); 131 | }); 132 | 133 | test('can lookup an engine', function(assert) { 134 | assert.expect(3); 135 | 136 | let expected = {}; 137 | define('foo-bar/engine', [], function(){ 138 | assert.ok(true, 'engine was invoked properly'); 139 | 140 | return { default: expected }; 141 | }); 142 | 143 | let engine = resolver.resolve('engine:foo-bar'); 144 | 145 | assert.ok(engine, 'engine was returned'); 146 | assert.equal(engine, expected, 'default export was returned'); 147 | }); 148 | 149 | test('can lookup a route-map', function(assert) { 150 | assert.expect(3); 151 | 152 | let expected = { isRouteMap: true }; 153 | define('foo-bar/routes', [], function(){ 154 | assert.ok(true, 'route-map was invoked properly'); 155 | 156 | return { default: expected }; 157 | }); 158 | 159 | let routeMap = resolver.resolve('route-map:foo-bar'); 160 | 161 | assert.ok(routeMap, 'route-map was returned'); 162 | assert.equal(routeMap, expected, 'default export was returned'); 163 | }); 164 | 165 | test('warns if normalizations up a camelCase service name', function(assert){ 166 | assert.expect(2); 167 | 168 | define('foo-bar/services/reverse-list', [], function(){ 169 | return { default: { isHelperInstance: true } }; 170 | }); 171 | 172 | assert.equal('service:reverseList', resolver.normalize('service:reverseList'), 'no service was returned'); 173 | assert.expectWarning('Attempted to lookup "service:reverseList". Use "service:reverse-list" instead.'); 174 | }); 175 | 176 | test("will unwrap the 'default' export automatically", function(assert) { 177 | define('foo-bar/fruits/orange', [], function(){ 178 | return { default: 'is awesome' }; 179 | }); 180 | 181 | assert.equal(resolver.resolve('fruit:orange'), 'is awesome', 'adapter was returned'); 182 | }); 183 | 184 | test("router:main is hard-coded to prefix/router.js", function(assert) { 185 | assert.expect(1); 186 | 187 | define('foo-bar/router', [], function(){ 188 | assert.ok(true, 'router:main was looked up'); 189 | return 'whatever'; 190 | }); 191 | 192 | resolver.resolve('router:main'); 193 | }); 194 | 195 | test("store:main is looked up as prefix/store", function(assert) { 196 | assert.expect(1); 197 | 198 | define('foo-bar/store', [], function(){ 199 | assert.ok(true, 'store:main was looked up'); 200 | return 'whatever'; 201 | }); 202 | 203 | resolver.resolve('store:main'); 204 | }); 205 | 206 | test("store:posts as prefix/stores/post", function(assert) { 207 | assert.expect(1); 208 | 209 | define('foo-bar/stores/post', [], function(){ 210 | assert.ok(true, 'store:post was looked up'); 211 | return 'whatever'; 212 | }); 213 | 214 | resolver.resolve('store:post'); 215 | }); 216 | 217 | test("can lookup a component template in another namespace with different syntax", function(assert) { 218 | assert.expect(2); 219 | 220 | let expected = { isTemplate: true }; 221 | define('other/templates/components/foo-bar', [], function(){ 222 | assert.ok(true, "template was looked up properly"); 223 | 224 | return { default: expected }; 225 | }); 226 | 227 | var template = resolver.resolve('template:components/other@foo-bar'); 228 | 229 | assert.equal(template, expected, 'default export was returned'); 230 | }); 231 | 232 | test("does not lookup index when top level component is specified (route:view)", function(assert) { 233 | assert.expect(1); 234 | 235 | define('foo-bar/routes/view/index', [], function(){ 236 | assert.ok(false, 'should not have been required'); 237 | }); 238 | 239 | assert.ok(!resolver.resolve('route:view'), 'route was not returned'); 240 | }); 241 | 242 | test("can lookup an engine from a scoped package", function(assert) { 243 | assert.expect(3); 244 | 245 | let expected = {}; 246 | define('@some-scope/some-module/engine', [], function(){ 247 | assert.ok(true, "engine was invoked properly"); 248 | 249 | return { default: expected }; 250 | }); 251 | 252 | var engine = resolver.resolve('engine:@some-scope/some-module'); 253 | 254 | assert.ok(engine, 'engine was returned'); 255 | assert.equal(engine, expected, 'default export was returned'); 256 | }); 257 | 258 | test("can lookup something in another namespace with an @ scope", function(assert){ 259 | assert.expect(3); 260 | 261 | let expected = {}; 262 | 263 | define('@scope/other/adapters/post', [], function(){ 264 | assert.ok(true, "adapter was invoked properly"); 265 | 266 | return { 267 | default: expected 268 | }; 269 | }); 270 | 271 | var adapter = resolver.resolve('@scope/other@adapter:post'); 272 | 273 | assert.ok(adapter, 'adapter was returned'); 274 | assert.equal(adapter, expected, 'default export was returned'); 275 | }); 276 | }); 277 | -------------------------------------------------------------------------------- /vendor/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanpenner/ember-strict-resolver/13a400332c68e44b8ba2834c512a2c075c9cad4d/vendor/.gitkeep --------------------------------------------------------------------------------