├── .bowerrc
├── .editorconfig
├── .ember-cli
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── .watchmanconfig
├── LICENSE.md
├── README.md
├── addon
└── .gitkeep
├── app
└── .gitkeep
├── bower.json
├── config
├── ember-try.js
└── environment.js
├── ember-cli-build.js
├── index.js
├── lib
└── bootloader.js
├── package.json
├── testem.js
├── tests
├── .jshintrc
├── dummy
│ ├── app
│ │ ├── app.js
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── index.html
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── resolver.js
│ │ ├── router.js
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── styles
│ │ │ └── app.css
│ │ └── templates
│ │ │ ├── application.hbs
│ │ │ └── components
│ │ │ └── .gitkeep
│ ├── config
│ │ └── environment.js
│ └── public
│ │ ├── crossdomain.xml
│ │ └── robots.txt
├── helpers
│ ├── destroy-app.js
│ ├── module-for-acceptance.js
│ ├── resolver.js
│ └── start-app.js
├── index.html
├── integration
│ └── .gitkeep
├── test-helper.js
└── unit
│ └── .gitkeep
└── vendor
└── .gitkeep
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/.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 | [*.js]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.hbs]
21 | insert_final_newline = false
22 | indent_style = space
23 | indent_size = 2
24 |
25 | [*.css]
26 | indent_style = space
27 | indent_size = 2
28 |
29 | [*.html]
30 | indent_style = space
31 | indent_size = 2
32 |
33 | [*.{diff,md}]
34 | trim_trailing_whitespace = false
35 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log
17 | testem.log
18 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "-Promise"
6 | ],
7 | "browser": true,
8 | "boss": true,
9 | "curly": true,
10 | "debug": false,
11 | "devel": true,
12 | "eqeqeq": true,
13 | "evil": true,
14 | "forin": false,
15 | "immed": false,
16 | "laxbreak": false,
17 | "newcap": true,
18 | "noarg": true,
19 | "noempty": false,
20 | "nonew": false,
21 | "nomen": false,
22 | "onevar": false,
23 | "plusplus": false,
24 | "regexp": false,
25 | "undef": true,
26 | "sub": true,
27 | "strict": false,
28 | "white": false,
29 | "eqnull": true,
30 | "esnext": true,
31 | "unused": true
32 | }
33 |
--------------------------------------------------------------------------------
/.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 | .jshintrc
12 | .watchmanconfig
13 | .travis.yml
14 | bower.json
15 | ember-cli-build.js
16 | testem.js
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - "0.12"
5 |
6 | sudo: false
7 |
8 | cache:
9 | directories:
10 | - node_modules
11 |
12 | env:
13 | - EMBER_TRY_SCENARIO=default
14 | - EMBER_TRY_SCENARIO=ember-1-13
15 | - EMBER_TRY_SCENARIO=ember-release
16 | - EMBER_TRY_SCENARIO=ember-beta
17 | - EMBER_TRY_SCENARIO=ember-canary
18 |
19 | matrix:
20 | fast_finish: true
21 | allow_failures:
22 | - env: EMBER_TRY_SCENARIO=ember-canary
23 |
24 | before_install:
25 | - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
26 | - "npm config set spin false"
27 | - "npm install -g npm@^2"
28 |
29 | install:
30 | - npm install -g bower
31 | - npm install
32 | - bower install
33 |
34 | script:
35 | - ember try $EMBER_TRY_SCENARIO test
36 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
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-cli-deploy-appshell
2 |
3 | This is an ember-cli-deploy plugin that loads your Ember application
4 | via an `applicationCache`-based shell. It
5 |
6 | - reliably caches all your assets for speed and offline use
7 | - always boots your freshest version when the network is sufficiently fast
8 | - never blocks application boot to preemptively cache assets
9 | - works correctly with CDN-deployed assets
10 | - can cache external assets
11 |
12 | ## Demo
13 |
14 | This app has a working deploy setup for running out of s3, complete with "lightning deploy"-style activation.
15 |
16 | https://github.com/ef4/ember-appcache-demo
17 |
18 | Running version is here:
19 |
20 | http://appcache-demo.eaf4.com/
21 |
22 | ## Key requirements:
23 |
24 | 1. Set `autoRun: false` in the arguments to `new EmberApp` in your `ember-cli-build.js` file. Our bootloader code takes over deciding when to boot your app.
25 |
26 | 2. Remove `loader.js` from your package.json, and set `_ignoreMissingLoader: true` in the arguments to `new EmberApp` in your `ember-cli-build.js` file. This addon inlines its own copy of `loader.js` in order to manage ambiguity between multiple versions of your app that may be attempting to load in parallel.
27 |
28 | 3. Wherever you are deploying `index.html`, you must also deploy `appshell.html` and `appcache.manifest`.
29 |
30 | 4. Make sure you're using fingerprinted assets. This is critical to busting through the application cache to get instant updates when online.
31 |
32 | ## What is appshell.html?
33 |
34 | It's a nearly-identical copy of your index.html, with one key difference: it lacks a `manifest` attribute, so it doesn't get stored in `applicationCache`. We use it to bust through the cache when we want to check for the latest index. If we find a new index, we shove it into DOM and let it take over immediately, while the normal `applicationCache` update is happening in the background.
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/addon/.gitkeep
--------------------------------------------------------------------------------
/app/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/app/.gitkeep
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-app-shell",
3 | "dependencies": {
4 | "ember": "~2.4.1",
5 | "ember-cli-shims": "0.1.0",
6 | "ember-cli-test-loader": "0.2.2",
7 | "ember-qunit-notifications": "0.1.0"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | scenarios: [
4 | {
5 | name: 'default',
6 | bower: {
7 | dependencies: { }
8 | }
9 | },
10 | {
11 | name: 'ember-1-13',
12 | bower: {
13 | dependencies: {
14 | 'ember': '~1.13.0'
15 | },
16 | resolutions: {
17 | 'ember': '~1.13.0'
18 | }
19 | }
20 | },
21 | {
22 | name: 'ember-release',
23 | bower: {
24 | dependencies: {
25 | 'ember': 'components/ember#release'
26 | },
27 | resolutions: {
28 | 'ember': 'release'
29 | }
30 | }
31 | },
32 | {
33 | name: 'ember-beta',
34 | bower: {
35 | dependencies: {
36 | 'ember': 'components/ember#beta'
37 | },
38 | resolutions: {
39 | 'ember': 'beta'
40 | }
41 | }
42 | },
43 | {
44 | name: 'ember-canary',
45 | bower: {
46 | dependencies: {
47 | 'ember': 'components/ember#canary'
48 | },
49 | resolutions: {
50 | 'ember': 'canary'
51 | }
52 | }
53 | }
54 | ]
55 | };
56 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | 'use strict';
3 |
4 | module.exports = function(/* environment, appConfig */) {
5 | return { };
6 | };
7 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | /* global require, module */
3 | var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function(defaults) {
6 | var 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 | /* jshint node: true */
2 | "use strict";
3 | let path = require('path');
4 | let uglify = require('uglify-js');
5 | let DeployPluginBase = require('ember-cli-deploy-plugin');
6 | let fs = require('fs');
7 | let minimatch = require('minimatch');
8 |
9 | module.exports = {
10 | name: 'ember-cli-deploy-appshell',
11 |
12 | included(app) {
13 | this.app = app;
14 | },
15 |
16 | contentFor(type, config) {
17 | if (type === 'head') {
18 | let loader = fs.readFileSync(require.resolve('loader.js'), 'utf8');
19 | let src = fs.readFileSync(path.join(__dirname, 'lib', 'bootloader.js'), 'utf8').replace(/MODULE_PREFIX/g, config.modulePrefix);
20 | let bootloader = uglify.minify(loader + src, { fromString: true, mangle:true, compress: true}).code;
21 | this.baseURL = config.baseURL;
22 | return ``;
23 | }
24 | },
25 |
26 | createDeployPlugin: function(options) {
27 | let baseURL = () => this.baseURL;
28 | let DeployPlugin = DeployPluginBase.extend({
29 | name: options.name,
30 | didBuild: function(context) {
31 | let distDir = context.distDir;
32 | let files = context.distFiles;
33 | fs.writeFileSync(path.join(distDir, 'manifest.appcache'), this.renderManifest(files));
34 | let indexHTML = fs.readFileSync(path.join(distDir, 'index.html'), 'utf8');
35 | fs.writeFileSync(path.join(distDir, 'appshell.html'), indexHTML);
36 | context.distFiles.push('appshell.html');
37 | fs.writeFileSync(path.join(distDir, 'index.html'), indexHTML.replace(//i, ``));
38 | },
39 | renderManifest: function(paths) {
40 | let excludePattern = this.readConfig('excludePattern');
41 | let prefixDomains = this.readConfig('prefixDomains');
42 | let outputPaths = paths.filter(function(p){ return !minimatch(p, excludePattern); })
43 | .map(function(p) {
44 | let domain = Object.keys(prefixDomains).find(function(domain) {
45 | return minimatch(p, prefixDomains[domain]);
46 | });
47 | if (domain) {
48 | return domain + p;
49 | } else {
50 | return p;
51 | }
52 | });
53 | outputPaths = outputPaths.concat(this.readConfig('externalDependencies'));
54 |
55 | return `CACHE MANIFEST
56 | # ${new Date()}
57 | ${ outputPaths.join("\n") }
58 | NETWORK:
59 | *`;
60 | }
61 | });
62 | return new DeployPlugin();
63 | }
64 |
65 | };
66 |
--------------------------------------------------------------------------------
/lib/bootloader.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | // We need to defend against reentrance, because if we end up
3 | // replacing the current page with an updated version, the updated
4 | // version will probably also include a copy of ourself.
5 | if (window._ember_cli_deploy_appshell_running) {
6 | return;
7 | }
8 | window._ember_cli_deploy_appshell_running = true;
9 |
10 | function log(msg) {
11 | msg = '[appshell] ' + msg;
12 | var args = Array.prototype.slice.call(arguments, 1);
13 | args.unshift(msg);
14 | console.log.apply(console, args);
15 | }
16 |
17 | // We're running before we can rely on jQuery having loaded, so
18 | // we're playing on hard mode.
19 | function ready(fn) {
20 | if (document.readyState !== "loading") {
21 | fn();
22 | } else {
23 | document.addEventListener( "DOMContentLoaded", fn);
24 | }
25 | }
26 |
27 | // This replaces ember-cli's normal autorun step. The module prefix
28 | // below gets rewritten at build time to match your real value.
29 | var allowedNormalBoot = false;
30 | function allowNormalBoot() {
31 | if (allowedNormalBoot){ return; }
32 | log("allowing app to boot");
33 | allowedNormalBoot = true;
34 | var tag = document.createElement('script');
35 | tag.type = "text/javascript";
36 | tag.textContent = "require('MODULE_PREFIX/app').default.create(require('MODULE_PREFIX/config/environment').default.APP)";
37 | ready(function(){
38 | document.getElementsByTagName('body')[0].appendChild(tag);
39 | });
40 | }
41 |
42 | // appshell.html is a copy of our index.html that doesn't include a
43 | // manifest attribute. Therefore we can always grab the latest
44 | // version without applicationCache intercepting us.
45 | function getShadowIndex(cb, failureCb) {
46 | var req = new XMLHttpRequest();
47 | req.open("GET","appshell.html",true);
48 | req.onreadystatechange = function(){
49 | if (req.readyState === req.DONE){
50 | if (req.status === 200){
51 | cb(req.response);
52 | } else {
53 | failureCb(new Error("failed to retrieve shadow index"));
54 | }
55 | }
56 | };
57 | req.send();
58 | }
59 |
60 | function htmlParser(){
61 | // Browsers back through IE9 support DOMParser, although not
62 | // necessarily with html support.
63 | var parser = new DOMParser();
64 |
65 | // Firefox/Opera/IE throw errors on unsupported types
66 | try {
67 | // WebKit returns null on unsupported types
68 | if (parser.parseFromString("", "text/html")) {
69 | // text/html parsing is natively supported
70 | return function(htmlString){ return parser.parseFromString(htmlString, 'text/html'); };
71 | }
72 | } catch (ex) {}
73 |
74 | return function(htmlString) {
75 | var doc = document.implementation.createHTMLDocument("");
76 | if (htmlString.toLowerCase().indexOf(' -1) {
77 | doc.documentElement.innerHTML = htmlString;
78 | }
79 | else {
80 | doc.body.innerHTML = htmlString;
81 | }
82 | return doc;
83 | };
84 | }
85 |
86 | // We need to manage the timing of script loading to ensure that the
87 | // newest scripts have loaded before we trigger app
88 | // boot. Dynamically appended script tags don't otherwise have a
89 | // reliable ordering.
90 | function scriptLoader() {
91 | var pendingScripts = 0;
92 | var allDoneCb;
93 |
94 | function didLoad() {
95 | pendingScripts--;
96 | if (pendingScripts === 0) {
97 | if (allDoneCb) {
98 | allDoneCb();
99 | }
100 | }
101 | }
102 |
103 | return {
104 | waitFor: function(script) {
105 | if (script.hasAttribute('src')) {
106 | script.onload = didLoad;
107 | script.onerror = didLoad;
108 | script.onabort = didLoad;
109 | pendingScripts++;
110 | }
111 | },
112 | allDoneThen: function(cb) {
113 | if (pendingScripts === 0) {
114 | cb();
115 | } else {
116 | allDoneCb = cb;
117 | }
118 | }
119 | };
120 | }
121 |
122 | function replace(source, destination, loader) {
123 | while (destination.firstChild) {
124 | destination.firstChild.remove();
125 | }
126 | while (source.firstChild) {
127 | // importNode is important here. Without it, the browser will
128 | // implicitly copy the nodes for you, but we would lose the
129 | // onload handler installed by loader.waitFor.
130 | var child = document.importNode(source.firstChild, true);
131 | source.firstChild.remove();
132 | if (child.tagName === 'SCRIPT') {
133 | loader.waitFor(child);
134 | }
135 | destination.appendChild(child);
136 | }
137 | }
138 |
139 | function cacheBust() {
140 | log("fetching shadow index");
141 | getShadowIndex(function(html) {
142 | log("got shadow index, stuffing it into dom");
143 | window.shadowIndex = html;
144 | var doc = htmlParser()(html);
145 | var loader = scriptLoader();
146 | replace(doc.getElementsByTagName('head')[0], document.getElementsByTagName('head')[0], loader);
147 | replace(doc.getElementsByTagName('body')[0], document.getElementsByTagName('body')[0], loader);
148 | // Once all the new contents of index.html (fetched via
149 | // appshell.html) are appended and loaded, we can allow the app
150 | // to boot. Note that the rest of the applicationCache probably
151 | // hasn't updated yet at this point! That's OK as long as our
152 | // assets are fingerprinted -- our new assets came straight from
153 | // the network. The applicationCache can do its usual update
154 | // thing in the background (and we share the normal HTTP cache
155 | // with it, so as long as your cache headers are good we won't
156 | // double fetch).
157 | loader.allDoneThen(allowNormalBoot);
158 | }, function(err) {
159 | // If something goes wrong with the fetch, it's better to try to
160 | // boot what we already have than just let the app die.
161 | allowNormalBoot();
162 | throw err;
163 | });
164 | }
165 |
166 | if (typeof applicationCache === 'undefined' || applicationCache.status === applicationCache.UNCACHED || applicationCache.status === applicationCache.IDLE) {
167 | // IDLE here only happens if the applicationCache managed to
168 | // complete its check before we got here, and it found nothing
169 | // new. So we know we can just boot out of cache immediately.
170 | log("appcache is idle or missing, allowing normal boot");
171 | allowNormalBoot();
172 | } else if (applicationCache.status === applicationCache.CHECKING) {
173 | log("appcache check is in progress, will wait briefly");
174 | var waiting = true;
175 | var nevermind = function(msg) {
176 | return function() {
177 | if (waiting){
178 | log(msg);
179 | waiting = false;
180 | allowNormalBoot();
181 | }
182 | };
183 | };
184 | var useLatest = function(msg) {
185 | return function(){
186 | if (waiting) {
187 | log(msg);
188 | waiting = false;
189 | cacheBust();
190 | }
191 | };
192 | };
193 | applicationCache.addEventListener("noupdate", nevermind("confirmed no update"));
194 | applicationCache.addEventListener("error", nevermind("error while updating"));
195 | applicationCache.addEventListener("obsolete", useLatest("appcache is obsolete"));
196 | applicationCache.addEventListener("downloading", useLatest("downloading update"));
197 | // This handles the case where we're on a "Lie-Fi" network: it
198 | // looks up, but it's just hanging. This timeout should become configurable.
199 | setTimeout(nevermind("checking for update is taking too long"), 500);
200 | } else {
201 | // We go down this path when we find the cache is already
202 | // DOWNLOADING, UPDATEREADY, or OBSOLETE. This can happen if the
203 | // applicationCache's own update happened so quickly that it
204 | // finished before we got here.
205 | log("busting appcache for great freshness");
206 | cacheBust();
207 | }
208 |
209 | })();
210 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-deploy-appshell",
3 | "version": "0.2.2",
4 | "description": "applicationCache based shell for loading Ember apps",
5 | "directories": {
6 | "doc": "doc",
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "build": "ember build",
11 | "start": "ember server",
12 | "test": "ember try:testall"
13 | },
14 | "repository": "https://github.com/ef4/ember-cli-deploy-appshell",
15 | "engines": {
16 | "node": ">= 4.0.0"
17 | },
18 | "author": "Edward Faulkner ",
19 | "license": "MIT",
20 | "devDependencies": {
21 | "broccoli-asset-rev": "^2.2.0",
22 | "ember-ajax": "0.7.1",
23 | "ember-cli": "2.4.1",
24 | "ember-cli-app-version": "^1.0.0",
25 | "ember-cli-dependency-checker": "^1.2.0",
26 | "ember-cli-htmlbars": "^1.0.1",
27 | "ember-cli-htmlbars-inline-precompile": "^0.3.1",
28 | "ember-cli-inject-live-reload": "^1.3.1",
29 | "ember-cli-qunit": "^1.2.1",
30 | "ember-cli-release": "0.2.8",
31 | "ember-cli-sri": "^2.1.0",
32 | "ember-cli-uglify": "^1.2.0",
33 | "ember-data": "^2.4.0",
34 | "ember-disable-prototype-extensions": "^1.1.0",
35 | "ember-disable-proxy-controllers": "^1.0.1",
36 | "ember-export-application-global": "^1.0.4",
37 | "ember-load-initializers": "^0.5.0",
38 | "ember-resolver": "^2.0.3",
39 | "ember-try": "^0.1.2",
40 | "loader.js": "^4.0.0"
41 | },
42 | "keywords": [
43 | "ember-addon",
44 | "ember-cli-deploy-plugin"
45 | ],
46 | "dependencies": {
47 | "ember-cli-babel": "^5.1.5",
48 | "ember-cli-deploy-plugin": "^0.2.2",
49 | "loader.js": "^4.0.1",
50 | "minimatch": "^3.0.0",
51 | "uglify-js": "^2.6.2"
52 | },
53 | "ember-addon": {
54 | "configPath": "tests/dummy/config",
55 | "after": "broccoli-asset-rev"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | "framework": "qunit",
4 | "test_page": "tests/index.html?hidepassed",
5 | "disable_watching": true,
6 | "launch_in_ci": [
7 | "PhantomJS"
8 | ],
9 | "launch_in_dev": [
10 | "PhantomJS",
11 | "Chrome"
12 | ]
13 | };
14 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "DS",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName"
25 | ],
26 | "node": false,
27 | "browser": false,
28 | "boss": true,
29 | "curly": true,
30 | "debug": false,
31 | "devel": false,
32 | "eqeqeq": true,
33 | "evil": true,
34 | "forin": false,
35 | "immed": false,
36 | "laxbreak": false,
37 | "newcap": true,
38 | "noarg": true,
39 | "noempty": false,
40 | "nonew": false,
41 | "nomen": false,
42 | "onevar": false,
43 | "plusplus": false,
44 | "regexp": false,
45 | "undef": true,
46 | "sub": true,
47 | "strict": false,
48 | "white": false,
49 | "eqnull": true,
50 | "esnext": true,
51 | "unused": true
52 | }
53 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from './resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | let App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/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/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | const Router = Ember.Router.extend({
5 | location: config.locationType
6 | });
7 |
8 | Router.map(function() {
9 | });
10 |
11 | export default Router;
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/routes/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/styles/app.css
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | Welcome to Ember
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/dummy/app/templates/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: 'dummy',
6 | environment: environment,
7 | baseURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | }
14 | },
15 |
16 | APP: {
17 | // Here you can pass flags/options to your application instance
18 | // when it is created
19 | }
20 | };
21 |
22 | if (environment === 'development') {
23 | // ENV.APP.LOG_RESOLVER = true;
24 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
25 | // ENV.APP.LOG_TRANSITIONS = true;
26 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
27 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
28 | }
29 |
30 | if (environment === 'test') {
31 | // Testem prefers this...
32 | ENV.baseURL = '/';
33 | ENV.locationType = 'none';
34 |
35 | // keep test console output quieter
36 | ENV.APP.LOG_ACTIVE_GENERATION = false;
37 | ENV.APP.LOG_VIEW_LOOKUPS = false;
38 |
39 | ENV.APP.rootElement = '#ember-testing';
40 | }
41 |
42 | if (environment === 'production') {
43 |
44 | }
45 |
46 | return ENV;
47 | };
48 |
--------------------------------------------------------------------------------
/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/destroy-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default function destroyApp(application) {
4 | Ember.run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/tests/helpers/module-for-acceptance.js:
--------------------------------------------------------------------------------
1 | import { module } from 'qunit';
2 | import startApp from '../helpers/start-app';
3 | import destroyApp from '../helpers/destroy-app';
4 |
5 | export default function(name, options = {}) {
6 | module(name, {
7 | beforeEach() {
8 | this.application = startApp();
9 |
10 | if (options.beforeEach) {
11 | options.beforeEach.apply(this, arguments);
12 | }
13 | },
14 |
15 | afterEach() {
16 | if (options.afterEach) {
17 | options.afterEach.apply(this, arguments);
18 | }
19 |
20 | destroyApp(this.application);
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from '../../resolver';
2 | import config from '../../config/environment';
3 |
4 | const resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | let application;
7 |
8 | let attributes = Ember.merge({}, config.APP);
9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | Ember.run(() => {
12 | application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | });
16 |
17 | return application;
18 | }
19 |
--------------------------------------------------------------------------------
/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 |
31 | {{content-for "body-footer"}}
32 | {{content-for "test-body-footer"}}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/integration/.gitkeep
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/tests/unit/.gitkeep
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ef4/ember-cli-deploy-appshell/a5259f6ce01e0642b2ac69d3f5b6649334e819ee/vendor/.gitkeep
--------------------------------------------------------------------------------