├── dist
└── .keep
├── public
├── .gitkeep
└── inject-cordova.js
├── tests
├── unit
│ └── .gitkeep
├── dummy
│ ├── public
│ │ ├── .gitkeep
│ │ ├── robots.txt
│ │ └── crossdomain.xml
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ ├── .gitkeep
│ │ │ └── nav-bar
│ │ │ │ ├── index.js
│ │ │ │ ├── page-1.js
│ │ │ │ └── options-from-model.js
│ │ ├── styles
│ │ │ ├── .gitkeep
│ │ │ └── app.css
│ │ ├── views
│ │ │ └── .gitkeep
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ ├── .gitkeep
│ │ │ └── nav-bar.js
│ │ ├── templates
│ │ │ ├── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── application.hbs
│ │ │ └── nav-bar.hbs
│ │ ├── resolver.js
│ │ ├── router.js
│ │ ├── app.js
│ │ └── index.html
│ ├── .jshintrc
│ └── config
│ │ └── environment.js
├── helpers
│ ├── destroy-app.js
│ ├── resolver.js
│ ├── start-app.js
│ ├── module-for-acceptance.js
│ └── describe-app.js
├── test-helper.js
├── index.html
├── .jshintrc
└── integration
│ └── nav-bar-test.js
├── .npmignore
├── .bowerrc
├── app
├── templates
│ ├── components
│ │ └── cdv-nav-bar.hbs
│ └── cdv-generic-nav-bar.hbs
├── components
│ └── cdv-nav-bar.js
├── services
│ └── cordova.js
└── initializers
│ └── in-app-livereload.js
├── node-tests
├── helpers
│ ├── noop.js
│ ├── mocks.js
│ ├── stub.js
│ └── _helper.js
├── fixtures
│ └── project
│ │ ├── .ember-cdv
│ │ └── cordova
│ │ └── config.xml
└── unit
│ ├── models
│ └── project-with-config-test.js
│ ├── tasks
│ ├── add-platforms-test.js
│ ├── verify-dist-test.js
│ ├── update-config-xml-version-test.js
│ ├── cordova-test.js
│ ├── create-cordova-project-test.js
│ ├── update-config-xml-test.js
│ ├── link-environment-test.js
│ ├── open-test.js
│ ├── build-test.js
│ ├── post-build-test.js
│ └── archive-test.js
│ └── addon-test.js
├── .watchmanconfig
├── .hound.yml
├── blueprints
├── cordova-starter-kit
│ ├── files
│ │ ├── app
│ │ │ ├── transitions.js
│ │ │ ├── templates
│ │ │ │ └── application.hbs
│ │ │ ├── adapters
│ │ │ │ └── application.js
│ │ │ ├── routes
│ │ │ │ └── application.js
│ │ │ └── styles
│ │ │ │ └── app.scss
│ │ └── config
│ │ │ └── environment.js
│ └── index.js
└── cordova-init
│ ├── files
│ ├── gitignore
│ └── config
│ │ └── environment.js
│ └── index.js
├── testem.json
├── lib
├── utils
│ ├── default-platform.js
│ ├── string.js
│ ├── open.js
│ └── run-command.js
├── commands
│ ├── index.js
│ ├── open.js
│ ├── cordova.js
│ ├── build.js
│ ├── prepare.js
│ └── archive.js
├── ui
│ └── index.js
├── tasks
│ ├── add-platforms.js
│ ├── create-cordova-project.js
│ ├── update-config-xml-version.js
│ ├── cordova.js
│ ├── verify-dist.js
│ ├── open.js
│ ├── link-environment.js
│ ├── build.js
│ ├── modify-xml.js
│ ├── update-config-xml.js
│ ├── update-config-xml-android-version-code.js
│ ├── post-build.js
│ └── archive.js
├── models
│ └── project-with-config.js
└── ext
│ └── promise.js
├── .travis.yml
├── bower.json
├── addon
├── utils
│ └── redirect.js
├── initializers
│ └── in-app-livereload.js
├── mixins
│ ├── controllers
│ │ └── nav-bar.js
│ ├── cordova-events.js
│ └── routes
│ │ └── nav-bar.js
└── services
│ └── cordova.js
├── .ember-cli
├── .gitignore
├── ember-cli-build.js
├── .editorconfig
├── .jshintrc
├── docs
├── faq.md
├── configuration.md
├── events.md
├── commands.md
├── nav-bar.md
└── getting-started.md
├── LICENSE
├── package.json
├── index.js
└── README.md
/dist/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test-app
2 | tests
3 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/views/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/app/templates/components/cdv-nav-bar.hbs:
--------------------------------------------------------------------------------
1 | {{yield}}
2 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | {{outlet}}
2 |
--------------------------------------------------------------------------------
/node-tests/helpers/noop.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {};
2 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 20px;
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org/
2 |
3 | User-agent: *
4 |
--------------------------------------------------------------------------------
/.hound.yml:
--------------------------------------------------------------------------------
1 | javascript:
2 | enabled: true
3 | config_file: .jshintrc
4 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/app/transitions.js:
--------------------------------------------------------------------------------
1 | export default function() {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/app/components/cdv-nav-bar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Component.extend({
4 | tagName: 'header'
5 | });
6 |
--------------------------------------------------------------------------------
/node-tests/fixtures/project/.ember-cdv:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TestApp",
3 | "modulePrefix": "test-app",
4 | "id": "com.poetic.test-app"
5 | }
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/nav-bar.hbs:
--------------------------------------------------------------------------------
1 | {{#cdv-nav-bar}}
2 | {{partial 'cdv-generic-nav-bar'}}
3 | {{/cdv-nav-bar }}
4 |
5 | {{outlet}}
6 |
--------------------------------------------------------------------------------
/tests/helpers/destroy-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default function destroyApp(application) {
4 | Ember.run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/app/services/cordova.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import CordovaService from 'ember-cli-cordova/services/cordova';
4 |
5 | export default CordovaService.extend({});
6 |
--------------------------------------------------------------------------------
/testem.json:
--------------------------------------------------------------------------------
1 | {
2 | "framework": "qunit",
3 | "test_page": "tests/index.html",
4 | "launch_in_ci": ["PhantomJS"],
5 | "launch_in_dev": ["PhantomJS", "Chrome"]
6 | }
7 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
Welcome to ember-cli-cordova!
2 |
3 | {{liquid-outlet name="main"}}
4 |
5 | {{liquid-outlet modal}}
6 |
--------------------------------------------------------------------------------
/lib/utils/default-platform.js:
--------------------------------------------------------------------------------
1 | module.exports = function defaultPlatform(project) {
2 | var config = project.config().cordova || {};
3 | return config.platform || 'ios';
4 | };
5 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/nav-bar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import NavBarMixin from 'ember-cli-cordova/mixins/controllers/nav-bar';
3 |
4 | export default Ember.Controller.extend(NavBarMixin);
5 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/app/adapters/application.js:
--------------------------------------------------------------------------------
1 | import DS from 'ember-data';
2 | import config from '../config/environment';
3 |
4 | export default DS.ActiveModelAdapter.extend({
5 | host: config.apiUrl
6 | });
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | sudo: false
4 |
5 | cache:
6 | directories:
7 | - node_modules
8 |
9 | install:
10 | - npm install -g bower
11 | - npm install
12 | - bower install
13 |
14 | script:
15 | - npm test
16 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-cordova",
3 | "dependencies": {
4 | "ember": "~2.3.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 |
--------------------------------------------------------------------------------
/addon/utils/redirect.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default function(url) {
4 | if(window.location.href.indexOf('file://') > -1) {
5 | Ember.run.later(function() {
6 | window.location.replace(url);
7 | }, 50);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/commands/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'cordova': require('./cordova'),
3 | 'cordova:build': require('./build'),
4 | 'cordova:open': require('./open'),
5 | 'cordova:prepare': require('./prepare'),
6 | 'cordova:archive': require('./archive')
7 | };
8 |
--------------------------------------------------------------------------------
/node-tests/helpers/mocks.js:
--------------------------------------------------------------------------------
1 | var noop = require('./noop');
2 |
3 | exports.ui = {
4 | write: noop,
5 | pleasantProgress: {
6 | write: noop,
7 | start: noop,
8 | stop: noop,
9 | clear: noop,
10 | }
11 | }
12 |
13 | exports.Promise = {
14 | denodeify: function(fn) { return fn; }
15 | }
16 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/app/routes/application.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | actions: {
5 | back: function() {
6 | history.back();
7 | },
8 |
9 | openLink: function(url) {
10 | window.open(url, '_system');
11 | }
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/public/inject-cordova.js:
--------------------------------------------------------------------------------
1 | // ember-cli-cordova
2 | (function() {
3 | var platform = navigator.platform;
4 | if (platform.match(/(ipad|iphone|ipod|android)/i)) {
5 | var script = document.createElement('script');
6 | script.setAttribute('src', 'cordova.js');
7 | document.head.appendChild(script);
8 | }
9 | })()
10 |
--------------------------------------------------------------------------------
/addon/initializers/in-app-livereload.js:
--------------------------------------------------------------------------------
1 | import redirect from '../utils/redirect';
2 |
3 | export var initialize = function(app, config) {
4 | var url = config.cordova.emberUrl || 'http://localhost:4200';
5 | return redirect(url);
6 | };
7 |
8 | export default {
9 | name: 'cordova:in-app-livereload',
10 | initialize: initialize
11 | };
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | !/dist/.keep
6 | /tmp
7 |
8 | # dependencies
9 | /node_modules
10 | /bower_components/*
11 |
12 | # misc
13 | /.sass-cache
14 | /connect.lock
15 | /coverage/*
16 | /libpeerconnection.log
17 | npm-debug.log
18 | testem.log
19 | .idea
20 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/app/styles/app.scss:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0,0,0,0);
3 | -webkit-tap-highlight-color: transparent;
4 | box-sizing: border-box;
5 | -webkit-touch-callout: none;
6 | -webkit-user-select: none;
7 | input, textarea {
8 | -webkit-touch-callout: auto;
9 | -webkit-user-select: auto;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/ui/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var PleasantProgress = require('pleasant-progress');
4 |
5 | module.exports = {
6 | pleasantProgress: new PleasantProgress(),
7 | start: function(msg) {
8 | this.pleasantProgress.stop(true);
9 | this.pleasantProgress.start(msg)
10 | },
11 | write: function(msg) {
12 | this.pleasantProgress.stream.write(msg);
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/lib/tasks/add-platforms.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var runCommand = require('../utils/run-command');
4 | var path = require('path');
5 |
6 | module.exports = function(project, options) {
7 | var command = 'cordova platforms add ' + options.platform;
8 |
9 | return runCommand(command, 'Adding ' + options.platform + ' platform to cordova', {
10 | cwd: path.join(project.root, 'cordova')
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/lib/tasks/create-cordova-project.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var runCommand = require('../utils/run-command');
4 | var path = require('path');
5 |
6 | module.exports = function(project) {
7 | var config = project.cordovaConfig;
8 | var command = 'cordova create cordova ' + config.id + ' ' + config.name;
9 |
10 | return runCommand(command, 'Creating Cordova project', {
11 | cwd: project.root
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | var Router = Ember.Router.extend({
5 | location: config.locationType
6 | });
7 |
8 | Router.map(function() {
9 | this.resource('nav-bar', function() {
10 | this.route('page-1');
11 | this.route('options-from-model');
12 | this.route('should-reset');
13 | });
14 | });
15 |
16 | export default Router;
17 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/nav-bar/index.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import NavBarMixin from 'ember-cli-cordova/mixins/routes/nav-bar';
3 |
4 | export default Ember.Route.extend(NavBarMixin, {
5 | nav: {
6 | controller: 'nav-bar',
7 | title: {
8 | text: 'Index'
9 | },
10 | leftButton: {
11 | text: 'iLeft'
12 | },
13 | rightButton: {
14 | text: 'iRight'
15 | },
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/nav-bar/page-1.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import NavBarMixin from 'ember-cli-cordova/mixins/routes/nav-bar';
3 |
4 | export default Ember.Route.extend(NavBarMixin, {
5 | nav: {
6 | controller: 'nav-bar',
7 | title: {
8 | text: 'Page 1'
9 | },
10 | leftButton: {
11 | text: 'pLeft'
12 | },
13 | rightButton: {
14 | text: 'pRight'
15 | },
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/node-tests/helpers/stub.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function stub(obj, name, value) {
4 | var original = obj[name];
5 |
6 | obj[name] = function() {
7 | obj[name].called++;
8 | obj[name].calledWith.push(arguments);
9 | return value;
10 | };
11 |
12 | obj[name].restore = function() {
13 | obj[name] = original;
14 | };
15 |
16 | obj[name].called = 0;
17 | obj[name].calledWith = [];
18 |
19 | return obj[name];
20 | };
21 |
--------------------------------------------------------------------------------
/lib/tasks/update-config-xml-version.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 |
5 | var versionRegex = /(version=\")[\d.]+(\")/;
6 |
7 | module.exports = function(version, project) {
8 | var message = 'Update config.xml with version ' + version;
9 | var cordovaPath = path.join(project.root, 'cordova');
10 |
11 | return require('./modify-xml')(message, cordovaPath, function(xml) {
12 | return this.xmlReplace(versionRegex, version, xml);
13 | });
14 |
15 | };
16 |
--------------------------------------------------------------------------------
/lib/tasks/cordova.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var runCommand = require('../utils/run-command');
5 |
6 | module.exports = function(rawArgs, project) {
7 |
8 | var joinedArgs = rawArgs.join(' ');
9 | var cdvCommand = 'cordova ' + joinedArgs;
10 |
11 | var msg = "Running 'cordova " + joinedArgs + "'";
12 |
13 | return function(){
14 | return runCommand(cdvCommand, msg, {
15 | cwd: path.join(project.root, 'cordova')
16 | })();
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/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/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
8 | document.write('');
9 |
10 | QUnit.config.urlConfig.push({ id: 'nocontainer', label: 'Hide container'});
11 | var containerVisibility = QUnit.urlParams.nocontainer ? 'hidden' : 'visible';
12 | document.getElementById('ember-testing-container').style.visibility = containerVisibility;
13 |
--------------------------------------------------------------------------------
/node-tests/fixtures/project/cordova/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ExampleApp
4 |
5 | A sample Apache Cordova application that responds to the deviceready event.
6 |
7 |
8 | Apache Cordova Team
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/templates/cdv-generic-nav-bar.hbs:
--------------------------------------------------------------------------------
1 | {{#if nav.leftButton.text}}
2 |
8 | {{/if}}
9 |
10 | {{#if nav.title.text}}
11 |
12 | {{nav.title.text}}
13 |
14 | {{/if}}
15 |
16 | {{#if nav.rightButton.text}}
17 |
23 | {{/if}}
24 |
--------------------------------------------------------------------------------
/lib/tasks/verify-dist.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var runCommand = require('../utils/run-command');
4 | var path = require('path');
5 | var fs = require('fs');
6 | var Promise = require('../ext/promise');
7 |
8 | module.exports = function(project) {
9 | return function() {
10 | var distPath = path.join(project.root, 'dist');
11 |
12 | if(fs.existsSync(distPath)) {
13 | return Promise.resolve();
14 | } else {
15 | return runCommand('ember build', 'Building ember app since dist/ dir doesn\'t exist yet', {
16 | cwd: project.root
17 | })();
18 | }
19 |
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/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 | destroyApp(this.application);
17 |
18 | if (options.afterEach) {
19 | options.afterEach.apply(this, arguments);
20 | }
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/tests/helpers/describe-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import startApp from './start-app';
3 |
4 | export default function(name, callback) {
5 | return describe(name, function() {
6 | before(function() {
7 | this.app = startApp();
8 | });
9 |
10 | after(function() {
11 | Ember.run(this.app, 'destroy');
12 | });
13 |
14 | lazy('store', function() {
15 | return this.app.__container__.lookup('store:main');
16 | });
17 |
18 | helper('lookupController', function(name) {
19 | return this.app.__container__.lookup('controller:' + name);
20 | });
21 |
22 | callback.call(this);
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/.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 | indent_style = space
22 | indent_size = 2
23 |
24 | [*.css]
25 | indent_style = space
26 | indent_size = 2
27 |
28 | [*.html]
29 | indent_style = space
30 | indent_size = 2
31 |
32 | [*.md]
33 | trim_trailing_whitespace = false
34 |
--------------------------------------------------------------------------------
/.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 | "moz": true
33 | }
34 |
--------------------------------------------------------------------------------
/lib/utils/string.js:
--------------------------------------------------------------------------------
1 | // https://github.com/emberjs/ember.js/blob/v1.5.0/packages/ember-runtime/lib/system/string.js
2 | 'use strict';
3 |
4 | var STRING_DECAMELIZE_REGEXP = (/([a-z\d])([A-Z])/g);
5 | var _s = require('underscore.string');
6 |
7 | module.exports = {
8 | decamelize: function(str) {
9 | return str ? str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase() : '';
10 | },
11 | dasherize: function(str) {
12 | return str ? _s.dasherize(str).replace(/^\-/, '') : '';
13 | },
14 | classify: function(str) {
15 | // Have to humanize first so that 'MyApp' doesnt turn into 'Myapp'
16 | return str ? _s.classify(_s.humanize(str)) : '';
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/node-tests/unit/models/project-with-config-test.js:
--------------------------------------------------------------------------------
1 | var expect = require('chai').expect;
2 | var path = require('path');
3 | var projectWithConfig = require('../../../lib/models/project-with-config');
4 |
5 | describe('Model - ProjectWithConfig', function() {
6 | var project;
7 |
8 | beforeEach(function() {
9 | project = {
10 | root: path.join(__dirname, '..', '..', 'fixtures/project'),
11 | name: function() {}
12 | }
13 | });
14 |
15 | it('adds the ember cordova config instance', function() {
16 | project = projectWithConfig(project);
17 | expect(project.cordovaConfig.id).to.equal('com.example.app');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/app/initializers/in-app-livereload.js:
--------------------------------------------------------------------------------
1 | /* globals cordova */
2 |
3 | import config from '../config/environment';
4 | import reloadInitializer from 'ember-cli-cordova/initializers/in-app-livereload';
5 |
6 | var inAppReload = reloadInitializer.initialize;
7 |
8 | export var initialize = function(app) {
9 | if(typeof cordova === 'undefined' ||
10 | config.environment !== 'development' ||
11 | (config.cordova &&
12 | (!config.cordova.liveReload || !config.cordova.liveReload.enabled))) {
13 | return;
14 | }
15 |
16 | return inAppReload(app, config);
17 | };
18 |
19 | export default {
20 | name: 'cordova:in-app-livereload',
21 | initialize: initialize
22 | };
23 |
--------------------------------------------------------------------------------
/lib/commands/open.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var defaultPlatform = require('../utils/default-platform');
5 |
6 | module.exports = {
7 | name: 'cordova:open',
8 | aliases: ['cdv:open'],
9 | description: 'Open the native platform project with the default or specified application',
10 | works: 'insideProject',
11 |
12 | availableOptions: [
13 | { name: 'platform', type: String },
14 | { name: 'application', type: String}
15 | ],
16 |
17 | run: function(options) {
18 | var platform = options.platform || defaultPlatform(this.project);
19 | return require('../tasks/open')(this.project, platform, options.application)();
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/tests/dummy/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": {
3 | "document": true,
4 | "window": true,
5 | "-Promise": true,
6 | "DummyENV": true
7 | },
8 | "browser" : true,
9 | "boss" : true,
10 | "curly": true,
11 | "debug": false,
12 | "devel": true,
13 | "eqeqeq": true,
14 | "evil": true,
15 | "forin": false,
16 | "immed": false,
17 | "laxbreak": false,
18 | "newcap": true,
19 | "noarg": true,
20 | "noempty": false,
21 | "nonew": false,
22 | "nomen": false,
23 | "onevar": false,
24 | "plusplus": false,
25 | "regexp": false,
26 | "undef": true,
27 | "sub": true,
28 | "strict": false,
29 | "white": false,
30 | "eqnull": true,
31 | "esnext": true,
32 | "unused": true
33 | }
34 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/commands/cordova.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var chalk = require('chalk');
5 |
6 | module.exports = {
7 | name: 'cordova',
8 | aliases: ['cdv'],
9 | description: 'Passes commands(plugin(s), platform(s), run, emulate) and arguments to the cordova command',
10 | works: 'insideProject',
11 | allowedCordovaCommands: [
12 | 'plugin', 'plugins', 'platform', 'platforms', 'run', 'emulate'
13 | ],
14 |
15 | validateAndRun: function(rawArgs) {
16 | if(this.allowedCordovaCommands.indexOf(rawArgs[0]) > -1) {
17 | return this.run({}, rawArgs);
18 | }
19 | },
20 |
21 | run: function(options, rawArgs) {
22 | return require('../tasks/cordova')(rawArgs, this.project)();
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/addon/mixins/controllers/nav-bar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Mixin.create({
4 | nav: {
5 | title: { },
6 | leftButton: { },
7 | rightButton: { }
8 | },
9 |
10 | actions: {
11 | leftButton: function() {
12 | var leftAction = this.get('nav.leftButton.action');
13 |
14 | if(leftAction) {
15 | leftAction();
16 | }
17 | },
18 |
19 | rightButton: function() {
20 | var rightAction = this.get('nav.rightButton.action');
21 |
22 | if(rightAction) {
23 | rightAction();
24 | }
25 | },
26 |
27 | resetNavBar: function() {
28 | this.set('nav', {
29 | title: { },
30 | leftButton: { },
31 | rightButton: { }
32 | });
33 | }
34 | }
35 | });
36 |
--------------------------------------------------------------------------------
/lib/commands/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var chalk = require('chalk');
5 | var defaultPlatform = require('../utils/default-platform');
6 |
7 | module.exports = {
8 | name: 'cordova:build',
9 | aliases: ['cdv:build'],
10 | description: 'Build the ember and cordova project together running in the simulator or on a device',
11 | works: 'insideProject',
12 |
13 | availableOptions: [
14 | { name: 'environment', type: String, default: 'development' },
15 | { name: 'platform', type: String }
16 | ],
17 |
18 | run: function(options) {
19 | var platform = options.platform || defaultPlatform(this.project);
20 | return require('../tasks/build')(options.environment, platform, this.project)();
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/node-tests/helpers/_helper.js:
--------------------------------------------------------------------------------
1 | global.expect = require('chai').expect;
2 | global.sinon = require('sinon');
3 |
4 | // be sure to not have any env variable set
5 | delete process.env.EMBER_CLI_CORDOVA;
6 |
7 | // Requiring a relative path will need to be relative to THIS file path
8 | global.proxyquire = require('proxyquire');
9 |
10 | global.Promise = require('../../lib/ext/promise');
11 | global.noop = require('./noop');
12 |
13 | global.resolveFn = function() { return Promise.resolve() };
14 |
15 | global.newProject = function() {
16 | return {
17 | cordovaConfig: {
18 | id: 'com.poetic.test-app',
19 | name: 'TestApp'
20 | },
21 | root: 'project-root',
22 | config: function (){
23 | return {
24 | cordova: {}
25 | };
26 | }
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/add-platforms-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Add Platforms', function() {
2 | it('creates the proper command', function() {
3 | var addPlatforms = proxyquire('../../lib/tasks/add-platforms', {
4 | '../utils/run-command': function(command) {
5 | expect(command).to.contain('platforms add some-platform');
6 | }
7 | });
8 |
9 | return addPlatforms({root: 'test'}, {platform: 'some-platform'});
10 | });
11 |
12 | it('executes command in cordova directory', function() {
13 | var addPlatforms = proxyquire('../../lib/tasks/add-platforms', {
14 | '../utils/run-command': function(_, __, options) {
15 | expect(options.cwd).to.equal('test/cordova');
16 | }
17 | });
18 |
19 | return addPlatforms({root: 'test'}, {platform: 'some-platform'});
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/lib/models/project-with-config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var stringUtils = require('../utils/string');
4 |
5 | var getComId = function(project) {
6 |
7 | var fs = require('fs');
8 | var path = require('path');
9 |
10 | var configPath = path.join(project.root, 'cordova', 'config.xml');
11 | var configFile = fs.readFileSync(configPath, { encoding: 'utf-8'});
12 |
13 | var idRegex = /id=\"([\w\-\.]+)\"/;
14 | var matches = configFile.match(idRegex);
15 |
16 | if(matches.length) {
17 | return matches[1];
18 | }
19 |
20 | throw new Error('Unable to find an id within your cordova/config.xml');
21 | }
22 |
23 | module.exports = function(project, id) {
24 | project.cordovaConfig = {
25 | name: stringUtils.classify(project.name()),
26 | id: id || getComId(project)
27 | };
28 |
29 | return project;
30 | };
31 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/verify-dist-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Verify Dist', function() {
2 | var project;
3 | beforeEach(function() {
4 | project = newProject();
5 | });
6 |
7 | it('resolves when path exists', function() {
8 | var verifyDist = proxyquire('../../lib/tasks/verify-dist', {
9 | 'fs': {
10 | existsSync: function() { return true; }
11 | }
12 | });
13 |
14 | return verifyDist(project)().then(function() {
15 | expect(true).to.be.ok;
16 | });
17 | });
18 |
19 | it('runs ember build when it doesn\'t exist', function() {
20 | var verifyDist = proxyquire('../../lib/tasks/verify-dist', {
21 | '../utils/run-command': function(command) {
22 | expect(command).to.eql('ember build');
23 | }
24 | });
25 |
26 | return verifyDist(project);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/update-config-xml-version-test.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | describe('Tasks - Update config xml version', function() {
4 | var project;
5 | beforeEach(function() {
6 | project = {
7 | root: path.join(__dirname, '..', '..', 'fixtures/project')
8 | }
9 | });
10 |
11 | it('updates version and writes it', function() {
12 | var update = proxyquire('../../lib/tasks/update-config-xml-version', {
13 | './modify-xml': proxyquire('../../lib/tasks/modify-xml', {
14 | 'fs': {
15 | writeFileSync: function(path, xml) {
16 | expect(path).to.eql(project.root + '/cordova/config.xml');
17 | expect(xml).to.match(/\sversion=\"0.1.0"\s/);
18 | }
19 | }
20 | })
21 | });
22 |
23 | return update('0.1.0', project)();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/lib/commands/prepare.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var linkEnv = require('../tasks/link-environment');
3 | var runCommand = require('../utils/run-command');
4 | var Promise = require('../ext/promise');
5 |
6 | module.exports = {
7 | name: 'cordova:prepare',
8 | aliases: ['cdv:prepare'],
9 | description: 'Needed after cloning or copying a project.',
10 | works: 'insideProject',
11 |
12 | run: function() {
13 | var installDeps = runCommand('npm install && bower install', 'Installing npm and bower dependencies', {
14 | cwd: this.project.root
15 | });
16 |
17 | // Because of this being parallel. It breaks the logging and it looks like
18 | //
19 | // Symlinking ember dir to cordova www...
20 | // Installing npm and bower dependencies...donedone
21 | return Promise.all([linkEnv(this.project)(), installDeps()]);
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/cordova-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Cordova', function() {
2 | it('creates a proper command', function() {
3 | var cordova = proxyquire('../../lib/tasks/cordova', {
4 | '../utils/run-command': function(command, msg, options){
5 | expect(command).to.match(/cordova plugins add org\.apache\.test$/);
6 | return noop;
7 | },
8 | });
9 |
10 | return cordova(['plugins', 'add', 'org.apache.test'], { root: 'test' })();
11 | });
12 |
13 | it('executes in proper directory', function() {
14 | var cordova = proxyquire('../../lib/tasks/cordova', {
15 | '../utils/run-command': function(command, msg, options){
16 | expect(options.cwd).to.match(/test\/cordova$/);
17 | return noop;
18 | },
19 | });
20 |
21 | return cordova(['plugins', 'add', 'org.apache.test'], { root: 'test' })();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/lib/tasks/open.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Promise = require('../ext/promise');
4 | var path = require('path');
5 | var runCommand = require('../utils/run-command');
6 | var getOpenCommand = require('../utils/open');
7 |
8 | module.exports = function(project, platform, application) {
9 | var projectPath, command;
10 | if (platform === 'ios') {
11 | projectPath = path.join(project.root, 'cordova', 'platforms/ios/*.xcodeproj');
12 | } else if (platform === 'android') {
13 | projectPath = path.join(project.root, 'cordova', 'platforms/android/.project');
14 | } else {
15 | return Promise.reject(new Error('The ' + platform + ' platform is not supported. Please use "ios" or "android"'));
16 | }
17 |
18 | var command = getOpenCommand(projectPath, application);
19 |
20 | return runCommand(command, 'Opening ' + platform + ' project with the default application');
21 | };
22 |
--------------------------------------------------------------------------------
/lib/tasks/link-environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Promise = require('../ext/promise');
4 | var fs = require('fs-extra');
5 | var symlink = Promise.denodeify(fs.symlink);
6 | var remove = Promise.denodeify(fs.remove);
7 | var path = require('path');
8 | var chalk = require('chalk');
9 | var verifyDist = require('./verify-dist');
10 |
11 | module.exports = function(project){
12 | if(!project) {
13 | throw new Error('A project must be passed into this function');
14 | }
15 |
16 | var cordovaPath = path.join(project.root, 'cordova');
17 | var wwwPath = path.join(cordovaPath, 'www');
18 |
19 | return function() {
20 | // allows us to do a relative symlink
21 | process.chdir(cordovaPath);
22 |
23 | return remove(wwwPath)
24 | .then(symlink.bind(this, '../dist', 'www', 'dir'))
25 | .then(verifyDist(project));
26 | };
27 | };
28 |
29 |
--------------------------------------------------------------------------------
/lib/commands/archive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var projectWithConfig = require('../models/project-with-config');
5 |
6 | module.exports = {
7 | name: 'cordova:archive',
8 | aliases: ['cdv:archive'],
9 | description: 'Build project and create xcode archive. If the tag or commit options are present they will be performed after archiving.',
10 | works: 'insideProject',
11 |
12 | anonymousOptions: [
13 | ''
14 | ],
15 |
16 | availableOptions: [
17 | { name: 'environment', type: String, default: 'staging' },
18 | { name: 'tag', type: Boolean, default: false },
19 | { name: 'commit', type: Boolean, default: false }
20 | ],
21 |
22 | run: function(options, rawArgs) {
23 | projectWithConfig(this.project);
24 | var version = rawArgs[0];
25 |
26 | return require('../tasks/archive')(version, options, this.project)();
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/lib/tasks/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var runCommand = require('../utils/run-command');
4 | var path = require('path');
5 | var linkEnv = require('../tasks/link-environment');
6 |
7 | module.exports = function(env, platform, project) {
8 | var emberCommand = 'ember build --environment ' + env;
9 |
10 | var emberMsg = 'Building ember project for environment ' + env;
11 | var emberBuild = runCommand(emberCommand, emberMsg, {
12 | cwd: project.root
13 | });
14 |
15 | var cdvCommand = 'cordova build ' + platform;
16 |
17 | if (env !== 'development') {
18 | cdvCommand += ' --release'
19 | }
20 |
21 | var cdvMsg = 'Building cordova project for platform ' + platform;
22 | var cdvBuild = runCommand(cdvCommand, cdvMsg, {
23 | cwd: path.join(project.root, 'cordova')
24 | });
25 |
26 | return function(){
27 | return linkEnv(project)().then(emberBuild).then(cdvBuild);
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/create-cordova-project-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Create cordova project', function() {
2 | var project;
3 | beforeEach(function() {
4 | project = newProject();
5 | });
6 |
7 | it('creates the proper command', function() {
8 | var createProject = proxyquire('../../lib/tasks/create-cordova-project', {
9 | '../utils/run-command': function(command) {
10 | expect(command).to.eql('cordova create cordova com.poetic.test-app TestApp');
11 | return resolveFn;
12 | }
13 | });
14 |
15 | return createProject(project)();
16 | });
17 |
18 | it('should execute in proper folder', function() {
19 | var createProject = proxyquire('../../lib/tasks/create-cordova-project', {
20 | '../utils/run-command': function(_, _, options) {
21 | expect(options.cwd).to.equal('project-root');
22 | return resolveFn;
23 | }
24 | });
25 |
26 | return createProject(project)();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/lib/tasks/modify-xml.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var chalk = require('chalk');
5 | var path = require('path');
6 | var ui = require('../ui');
7 | var Promise = require('../ext/promise');
8 |
9 | // Used as the context of this for the replaceFn so it can be used
10 | var replaceObject = {
11 | xmlReplace: function(regex, value, xml) {
12 | return xml.replace(regex, '$1' + value + '$2');
13 | }
14 | };
15 |
16 | module.exports = function(message, root, replaceFn) {
17 | return function modifyXml() {
18 | return new Promise(function(resolve, reject){
19 | try {
20 | var configPath = path.join(root, 'config.xml');
21 |
22 | ui.start(chalk.green(message));
23 |
24 | var xml = fs.readFileSync(configPath, { encoding: 'utf8' });
25 |
26 | xml = replaceFn.call(replaceObject, xml);
27 |
28 | fs.writeFileSync(configPath, xml);
29 | resolve();
30 |
31 | } catch(e) {
32 | reject(e);
33 | }
34 | });
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/lib/tasks/update-config-xml.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 |
5 | // Match the outer tags so we can match and reinsert them with a String#replace
6 | var idRegex = /(id=\")[\w\.]+(\")/;
7 | var nameRegex = /()\w+(<\/name>)/;
8 | var endWidgetRegex = /(.*)(<\/widget>)/;
9 |
10 | var preferences = [
11 | // haha, 4 spaces at the beginning
12 | ' '
13 | ];
14 |
15 | module.exports = function(project) {
16 | var config = project.cordovaConfig;
17 | var message = 'Update config.xml with your project settings';
18 | var cordovaPath = path.join(project.root, 'cordova');
19 |
20 | return require('./modify-xml')(message, cordovaPath, function(xml) {
21 | xml = this.xmlReplace(idRegex, config.id, xml);
22 | xml = this.xmlReplace(nameRegex, config.name, xml);
23 |
24 | // add preference tag(s)
25 | xml = this.xmlReplace(endWidgetRegex, preferences.join('\n') + '\n', xml);
26 |
27 | return xml;
28 | });
29 | };
30 |
31 |
--------------------------------------------------------------------------------
/docs/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | #### I am getting `Current working directory is not a Cordova-based project.` when I run a cordova command
4 |
5 | If you are running a cli command, make sure the dist directory exists. You can
6 | run `ember build` to create it if it doesnt. You can also try to run `ember
7 | cordova:prepare`
8 |
9 | #### When running `ember cordova:archive` command I get an Xcode build error saying the scheme doesnt exist
10 |
11 | Error example:
12 |
13 | ```
14 | ld[10658:1007] WARNING: Timed out waiting for /"runContextManager.runContexts" (10.000125 seconds elapsed)
16 | xcodebuild: error: The project 'MyApp' does not contain a scheme named 'MyApp'.
17 | ```
18 |
19 | This is caused by not having opened the project in Xcode before. It
20 | automatically generates some info it needs to archive the project. To fix this,
21 | run `ember cordova:open` and let it open in Xcode. After you've done this once you
22 | can just run `ember cordova:archive` command again and it shouldn't give you any more
23 | trouble.
24 |
25 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/nav-bar/options-from-model.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import NavBarMixin from 'ember-cli-cordova/mixins/routes/nav-bar';
3 |
4 | export default Ember.Route.extend(NavBarMixin, {
5 | nav: {
6 | controller: 'nav-bar',
7 | title: {
8 | text: function(model) {
9 | return model.get('title');
10 | }
11 | },
12 |
13 | leftButton: {
14 | text: function(model) {
15 | return model.get('leftButton');
16 | },
17 | icon: function(model) {
18 | return model.get('leftClass');
19 | }
20 | },
21 |
22 | rightButton: {
23 | text: function(model) {
24 | return model.get('rightButton');
25 | },
26 | icon: function(model) {
27 | return model.get('rightClass');
28 | }
29 | }
30 | },
31 |
32 | model: function() {
33 | return Ember.Object.create({
34 | title: 'modelOption',
35 | leftButton: 'modelLeft',
36 | leftClass: 'leftClass',
37 | rightButton: 'modelRight',
38 | rightClass: 'rightClass'
39 | });
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Jake Craige
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/lib/tasks/update-config-xml-android-version-code.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var path = require('path');
5 | var Promise = require('../ext/promise');
6 |
7 | var versionCodeRegex = /(android-versionCode=\")[\d.]+(\")/;
8 | var versionCodeMatch = /android-versionCode=\"([\d.])+\"/;
9 |
10 | module.exports = function(project) {
11 | return new Promise(function(resolve, reject){
12 | try {
13 | var cordovaPath = path.join(project.root, 'cordova');
14 | var configPath = path.join(cordovaPath, 'config.xml');
15 | var xml = fs.readFileSync(configPath, { encoding: 'utf8' });
16 |
17 | var match = xml.match(versionCodeMatch);
18 | if(match) {
19 | var versionCode = (parseInt(match[1], 10)) + 1;
20 | var message = 'Update config.xml with android-versionCode ' + versionCode;
21 |
22 | return require('./modify-xml')(message, cordovaPath, function(xml) {
23 | return this.xmlReplace(versionCodeRegex, versionCode, xml);
24 | })().then(resolve, reject);
25 | } else {
26 | reject();
27 | }
28 | } catch (e) {
29 | reject(e);
30 | }
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/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: 'hash',
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 = 'auto';
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 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/update-config-xml-test.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var uiMock = { start: noop };
3 |
4 | var project;
5 | describe('Tasks - Update config xml', function() {
6 | beforeEach(function() {
7 | project = {
8 | cordovaConfig: {
9 | id: 'com.poetic.test-app',
10 | name: 'TestApp'
11 | },
12 | root: path.join(__dirname, '..', '..', 'fixtures/project')
13 | }
14 | });
15 |
16 | it('updates id and name', function() {
17 | return proxyUpdate(function(xml) {
18 | expect(xml).to.match(/\sid=\"com\.poetic\.test\-app"\s/);
19 | expect(xml).to.match(/TestApp<\/name>/);
20 | });
21 | });
22 |
23 | it('adds DisallowOverscroll preference', function() {
24 | return proxyUpdate(function(xml) {
25 | expect(xml).to.match(//);
26 | });
27 | });
28 | });
29 |
30 | function proxyUpdate(callback) {
31 | var update = proxyquire('../../lib/tasks/update-config-xml', {
32 | './modify-xml': proxyquire('../../lib/tasks/modify-xml', {
33 | 'fs': {
34 | writeFileSync: function(path, xml) {
35 | callback(xml);
36 | }
37 | },
38 | '../ui': uiMock
39 | })
40 | });
41 |
42 | return update(project)();
43 | }
44 |
--------------------------------------------------------------------------------
/blueprints/cordova-init/files/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 |
19 | # iOS
20 | cordova/platforms/ios/build/
21 | cordova/platforms/ios/www/
22 | cordova/platforms/ios/cordova/console.log
23 | *.xcuserdatad
24 |
25 | # android
26 | cordova/platforms/android/assets/www
27 | cordova/platforms/android/bin
28 | cordova/platforms/android/gen
29 | cordova/platforms/android/local.properties
30 | cordova/platforms/android/ant-build
31 | cordova/platforms/android/ant-gen
32 | cordova/platforms/android/CordovaLib/ant-build
33 | cordova/platforms/android/CordovaLib/ant-gen
34 | cordova/platforms/android/CordovaLib/bin
35 | cordova/platforms/android/CordovaLib/gen
36 | cordova/platforms/android/CordovaLib/local.properties
37 |
38 | # wp8
39 | cordova/platforms/wp8/bin
40 | cordova/platforms/wp8/obj
41 | cordova/platforms/wp8/www
42 | cordova/platforms/wp8/.staging
43 | cordova/platforms/wp8/*.suo
44 | cordova/platforms/wp8/*.csproj.user
45 |
46 | #browser
47 | cordova/platforms/browser/build
48 | cordova/platforms/browser/www
49 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/index.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var chalk = require('chalk');
3 | var Promise = require('../../lib/ext/promise');
4 | var stringUtils = require('../../lib/utils/string');
5 | var runCommand = require('../../lib/utils/run-command');
6 |
7 | module.exports = {
8 | // Allows the generator to not require an entity name
9 | normalizeEntityName: function(entityName) {
10 | return entityName;
11 | },
12 |
13 | locals: function(options) {
14 | var name = options.project.pkg.name;
15 |
16 | return {
17 | namespace: stringUtils.classify(name),
18 | modulePrefix: stringUtils.dasherize(name)
19 | }
20 | },
21 |
22 | addPluginToProject: function(name) {
23 | var ui = this.ui;
24 |
25 | return runCommand('cordova plugin add ' + name, null, {
26 | cwd: path.join(this.project.root, 'cordova')
27 | })().then(function() {
28 | if (ui) {
29 | ui.writeLine(' ' + chalk.green('install plugin') + ' ' + name);
30 | }
31 | });
32 | },
33 |
34 | afterInstall: function() {
35 | return Promise.all([
36 | this.addPackageToProject('broccoli-sass'),
37 | this.addPackageToProject('liquid-fire'),
38 | this.addPackageToProject('ember-gestures')
39 | ]);
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/lib/tasks/post-build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var runCommand = require('../utils/run-command');
4 | var defaultPlatform = require('../utils/default-platform');
5 | var path = require('path');
6 | var chalk = require('chalk');
7 | var ui = require('../ui');
8 | var Promise = require('../ext/promise');
9 |
10 | function createCommand(project, options) {
11 | var platform = options.platform || defaultPlatform(project);
12 | var command = 'cordova build ' + platform;
13 |
14 | if (options.emulate) {
15 | command += ' && cordova emulate ' + platform;
16 |
17 | if (options.emulateTarget) {
18 | if (options.emulateTarget[platform]) {
19 | command += ' --target="' + options.emulateTarget[platform] + '"';
20 | }
21 | }
22 | }
23 |
24 | return runCommand(command, null, {
25 | cwd: path.join(project.root, 'cordova')
26 | });
27 | }
28 |
29 | module.exports = function(project, options) {
30 | if (!options.rebuildOnChange) {
31 | return function() {};
32 | }
33 |
34 | return function() {
35 | var rebuild = createCommand(project, options)();
36 |
37 | rebuild.then(function() {
38 | ui.write(chalk.green('Cordova build successful.\n'));
39 | });
40 |
41 | return Promise.resolve();
42 | }
43 | };
44 |
--------------------------------------------------------------------------------
/lib/utils/open.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | This file needs to be removed when issue https://github.com/pwnall/node-open/issues/30
4 | is resolved, original file can be seen here:
5 | https://github.com/pwnall/node-open/blob/0c3ad272bfbc163cce8806e64630c623a9cfd8f4/lib/open.js
6 | */
7 | module.exports = function(target, appName) {
8 | var opener;
9 |
10 | switch (process.platform) {
11 | case 'darwin':
12 | if (appName) {
13 | opener = 'open -a "' + escape(appName) + '"';
14 | } else {
15 | opener = 'open';
16 | }
17 | break;
18 | case 'win32':
19 | // if the first parameter to start is quoted, it uses that as the title
20 | // so we pass a blank title so we can quote the file we are opening
21 | if (appName) {
22 | opener = 'start "" "' + escape(appName) + '"';
23 | } else {
24 | opener = 'start';
25 | }
26 | break;
27 | default:
28 | if (appName) {
29 | opener = escape(appName);
30 | } else {
31 | // use Portlands xdg-open everywhere else
32 | opener = 'xdg-open';
33 | }
34 | break;
35 | }
36 |
37 | if (process.env.SUDO_USER) {
38 | opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener;
39 | }
40 |
41 | return opener + ' ' + target;
42 | }
43 |
--------------------------------------------------------------------------------
/lib/utils/run-command.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Promise = require('../ext/promise');
4 | var exec = require('child_process').exec;
5 | var chalk = require('chalk');
6 | var ui = require('../ui');
7 | var defaults = require('lodash').defaults;
8 |
9 | module.exports = function runCommand(command, startedMsg, options) {
10 | if(options == null) {
11 | options = {}
12 | }
13 |
14 | return function() {
15 | if(startedMsg) {
16 | ui.start(chalk.green(startedMsg));
17 | }
18 |
19 | options = defaults(options, {
20 | maxBuffer: 5000 * 1024
21 | });
22 |
23 | return new Promise(function(resolve, reject) {
24 | exec(command, options, function(err, stdout, stderr) {
25 | ui.write('\n');
26 |
27 | if (stdout && stdout.length) {
28 | ui.write(stdout);
29 | }
30 |
31 | if (stderr && stderr.length) {
32 | ui.write(stderr);
33 | }
34 |
35 | if (err) {
36 | return reject(commandError(command, err));
37 | }
38 |
39 | resolve(stdout);
40 | });
41 | });
42 | };
43 | };
44 |
45 | function commandError(command, err) {
46 | ui.write(chalk.red('\nError thrown while running shell command: "' + command + '"\n'));
47 | if(err.stack) {
48 | ui.write(err.stack);
49 | } else {
50 | ui.write(err);
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/blueprints/cordova-init/index.js:
--------------------------------------------------------------------------------
1 | var projectWithConfig = require('../../lib/models/project-with-config');
2 | var Promise = require('../../lib/ext/promise');
3 | var stringUtils = require('../../lib/utils/string');
4 | var defaultPlatform = require('../../lib/utils/default-platform');
5 |
6 | module.exports = {
7 | locals: function(options) {
8 | var name = options.project.pkg.name;
9 |
10 | return {
11 | namespace: stringUtils.classify(name),
12 | modulePrefix: stringUtils.dasherize(name)
13 | }
14 | },
15 |
16 | afterInstall: function(options) {
17 | this.options = options.entity.options;
18 | this.options.platform = options.platform || defaultPlatform(this.project);
19 |
20 | projectWithConfig(this.project, options.entity.name);
21 |
22 | return this.setupCordova();
23 | },
24 |
25 | setupCordova: function() {
26 | var createProject = require('../../lib/tasks/create-cordova-project')(this.project);
27 | var addPlatforms = require('../../lib/tasks/add-platforms')(this.project, this.options);
28 | var updateConfig = require('../../lib/tasks/update-config-xml')(this.project);
29 | var linkEnvironment = require('../../lib/tasks/link-environment')(this.project);
30 |
31 | return createProject().then(addPlatforms).then(updateConfig).then(linkEnvironment);
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/docs/configuration.md:
--------------------------------------------------------------------------------
1 | ### Configuration
2 |
3 | All configuration is currently optional. Configuration will be done in your
4 | app's `config/environment`. You need to set it up like this:
5 |
6 | ```js
7 | ENV.cordova = {
8 | // Rebuild the cordova project on file changes. Blocks the server until it's
9 | // finished.
10 | //
11 | // default: false
12 | rebuildOnChange: true,
13 |
14 | // Run the cordova emulate command after the build is finished
15 | //
16 | // default: false
17 | emulate: true,
18 |
19 | // Which emulated target to deploy to
20 | //
21 | // default:
22 | emulateTarget: {
23 | ios: "iPad-2",
24 | android: "android-20"
25 | },
26 |
27 | // Which platform to build and/or emulate
28 | //
29 | // default: 'ios'
30 | platform: 'ios',
31 |
32 | // Which URL the ember server is running on. This is used when using
33 | // live-reload that comes with the starter kit.
34 | //
35 | // default: 'the-device-ip:4200'
36 | emberUrl: 'http://10.0.1.12:4200',
37 |
38 | // Whether or not to use liveReload on the device simulator. Requires a few
39 | // plugins to be installed that come with the starter-kit. It will cause your
40 | // app to not boot up in the browser
41 | //
42 | // default: false and iOS
43 | liveReload: {
44 | enabled: false,
45 | platform: 'ios'
46 | }
47 | };
48 | ```
49 |
--------------------------------------------------------------------------------
/addon/services/cordova.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import Ember from 'ember';
4 |
5 | // from https://cordova.apache.org/docs/en/4.0.0/cordova_events_events.md.html
6 | // use var because cordova/android was throwing errors re: const && strict mode
7 | var CORDOVA_EVENTS = Ember.A([
8 | 'deviceready',
9 | 'pause',
10 | 'resume',
11 | 'backbutton',
12 | 'menubutton',
13 | 'searchbutton',
14 | 'startcallbutton',
15 | 'endcallbutton',
16 | 'volumedownbutton',
17 | 'volumeupbutton',
18 | 'batterycritical',
19 | 'batterylow',
20 | 'batterystatus',
21 | 'online',
22 | 'offline'
23 | ]);
24 |
25 | // the cordova service listens for cordova events emitted to the document,
26 | // and triggers the same events in emberland.
27 | //
28 | // subscribe to cordova events as such:
29 | //
30 | // ```javascript
31 | // export default MyEmberObject.extend({
32 | // cordova: Ember.inject.service()
33 | //
34 | // init: function() {
35 | // cordova.on('resume', function() { console.log('i am resumed'); });
36 | // }
37 | // });
38 | // ```
39 | export default Ember.Service.extend(
40 | Ember.Evented, {
41 |
42 | setEventTriggers: Ember.on('init', function() {
43 | var _this = this;
44 |
45 | CORDOVA_EVENTS.forEach(function(eventName) {
46 | Ember.$(document).on(eventName, function() {
47 | _this.trigger(eventName);
48 | });
49 | });
50 | })
51 | });
52 |
--------------------------------------------------------------------------------
/blueprints/cordova-init/files/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: '<%= modulePrefix %>',
6 | environment: environment,
7 | baseURL: '/',
8 | defaultLocationType: '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 | cordova: {
22 | rebuildOnChange: false,
23 | emulate: false
24 | }
25 | };
26 |
27 | if (environment === 'development') {
28 | // ENV.APP.LOG_RESOLVER = true;
29 | ENV.APP.LOG_ACTIVE_GENERATION = true;
30 | // ENV.APP.LOG_TRANSITIONS = true;
31 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
32 | ENV.APP.LOG_VIEW_LOOKUPS = true;
33 | }
34 |
35 | if (environment === 'test') {
36 | // Testem prefers this...
37 | ENV.baseURL = '/';
38 | ENV.locationType = 'none';
39 |
40 | // keep test console output quieter
41 | ENV.APP.LOG_ACTIVE_GENERATION = false;
42 | ENV.APP.LOG_VIEW_LOOKUPS = false;
43 |
44 | ENV.APP.rootElement = '#ember-testing';
45 | }
46 |
47 | if (environment === 'production') {
48 |
49 | }
50 |
51 | return ENV;
52 | };
53 |
--------------------------------------------------------------------------------
/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 |
32 |
33 | {{content-for 'head-footer'}}
34 | {{content-for 'test-head-footer'}}
35 |
36 |
37 | {{content-for 'body'}}
38 | {{content-for 'test-body'}}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | {{content-for 'body-footer'}}
48 | {{content-for 'test-body-footer'}}
49 |
50 |
51 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/link-environment-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Link Environment', function() {
2 | var project;
3 | beforeEach(function() {
4 | project = newProject();
5 | });
6 |
7 | before(function() {
8 | process._chdir = process.chdir;
9 | process.chdir = noop;
10 | });
11 |
12 | after(function() {
13 | process.chdir = process._chdir;
14 | });
15 |
16 | it('removes the cordova/www dir', function() {
17 | var createProject = proxyquire('../../lib/tasks/link-environment', {
18 | './verify-dist': function() { return resolveFn; },
19 | 'fs-extra': {
20 | remove: function(path, callback) {
21 | expect(path).to.eql('project-root/cordova/www');
22 | return callback(null, true);
23 | },
24 | symlink: function(from, to, type, _, callback) {
25 | return callback(null, true);
26 | }
27 | }
28 | });
29 |
30 | return createProject(project)();
31 | });
32 |
33 | it('creates a relative dir symlink', function() {
34 | var createProject = proxyquire('../../lib/tasks/link-environment', {
35 | './verify-dist': function() { return resolveFn; },
36 | 'fs-extra': {
37 | remove: function(path, callback) {
38 | return callback(null, true);
39 | },
40 | symlink: function(from, to, type, _, callback) {
41 | expect(from).to.eql('../dist');
42 | expect(to).to.eql('www');
43 | expect(type).to.eql('dir');
44 | return callback(null, true);
45 | }
46 | }
47 | });
48 |
49 | return createProject(project)();
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/addon/mixins/cordova-events.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import Ember from 'ember';
4 |
5 | // include this mixin to define cordova event listeners with an onCordova object
6 | //
7 | // onCordova supports arrays, strings, and anonymous functions, e.g.:
8 | //
9 | // ```
10 | // export default MyEmberObject.extend({
11 | // onCordova: {
12 | // pause: ['pauseListening', 'disconnectPeripheral'],
13 | // resume: 'resumeListening',
14 | // volumeup: function() { console.log('a little bit louder now'); }
15 | // }
16 | // });
17 | // ```
18 | export default Ember.Mixin.create({
19 | cordova: Ember.inject.service(),
20 |
21 | subscribeToCordovaEvents: Ember.on('init', function() {
22 | var cordova = this.get('cordova'),
23 | onCordova = this.get('onCordova');
24 |
25 | Ember.keys(onCordova).forEach(function(key) {
26 | var func = Ember.get(onCordova, key);
27 |
28 | // subscribe to events
29 | if (func instanceof Array) {
30 | func.forEach(function(fn) {
31 | if (this._validateIsFunction(fn)) {
32 | cordova.on(key, this, fn);
33 | }
34 | }, this);
35 | } else {
36 | if (this._validateIsFunction(func)) {
37 | cordova.on(key, this, func);
38 | }
39 | }
40 | }, this);
41 | }),
42 |
43 | _validateIsFunction: function(func) {
44 | var isFunction = false;
45 |
46 | if (func instanceof Function) {
47 | isFunction = true;
48 | } else if (typeof func === 'string') {
49 | var fn = this.get(func);
50 |
51 | isFunction = fn instanceof Function;
52 | }
53 |
54 | return isFunction;
55 | }
56 | });
57 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "QUnit",
10 | "define",
11 | "console",
12 | "equal",
13 | "notEqual",
14 | "notStrictEqual",
15 | "test",
16 | "asyncTest",
17 | "testBoth",
18 | "testWithDefault",
19 | "raises",
20 | "throws",
21 | "deepEqual",
22 | "start",
23 | "stop",
24 | "ok",
25 | "strictEqual",
26 | "module",
27 | "moduleFor",
28 | "moduleForComponent",
29 | "moduleForModel",
30 | "process",
31 | "expect",
32 | "visit",
33 | "exists",
34 | "fillIn",
35 | "click",
36 | "keyEvent",
37 | "triggerEvent",
38 | "find",
39 | "findWithAssert",
40 | "wait",
41 | "DS",
42 | "keyEvent",
43 | "isolatedContainer",
44 | "startApp",
45 | "andThen",
46 | "currentURL",
47 | "currentPath",
48 | "currentRouteName",
49 | "cordova",
50 | "describe",
51 | "before",
52 | "after",
53 | "it",
54 | "lazy",
55 | "helper",
56 | "sinon"
57 | ],
58 | "node": false,
59 | "browser": false,
60 | "boss": true,
61 | "curly": false,
62 | "debug": false,
63 | "devel": false,
64 | "eqeqeq": true,
65 | "evil": true,
66 | "forin": false,
67 | "immed": false,
68 | "laxbreak": false,
69 | "newcap": true,
70 | "noarg": true,
71 | "noempty": false,
72 | "nonew": false,
73 | "nomen": false,
74 | "onevar": false,
75 | "plusplus": false,
76 | "regexp": false,
77 | "undef": true,
78 | "sub": true,
79 | "strict": false,
80 | "white": false,
81 | "eqnull": true,
82 | "esnext": true
83 | }
84 |
--------------------------------------------------------------------------------
/docs/events.md:
--------------------------------------------------------------------------------
1 | # Events
2 |
3 | ## Description
4 |
5 | ember-cli-cordova creates a service at `services/cordova.js`, which listens for
6 | events defined and emitted by Cordova (e.g. `deviceready`, `pause`, `resume`).
7 |
8 |
9 | ## Usage
10 |
11 | **Simple Usage:**
12 |
13 | Many events require only simple callbacks, e.g. pausing / resuming listener
14 | functions, logging the event, etc.
15 |
16 | In these cases, extend your object/class with the provided mixin, which will
17 | look for an `onCordova` object and run the provided functions when an event
18 | matching the key is emitted. For example:
19 |
20 | ```javascript
21 | import CordovaEventsMixin from 'ember-cli-cordova/mixins/cordova-events';
22 |
23 | export default MyEmberObject.extend(
24 | CordovaEventsMixin, {
25 |
26 | onCordova: {
27 | pause: ['pauseListening', 'disconnectPeripheral'],
28 | resume: 'resumeListening',
29 | volumeup: function() { console.log('a little bit louder now'); }
30 | }
31 | });
32 | ```
33 |
34 | (Yes, `onCordova` supports arrays of named functions, single named functions,
35 | and anonymous functions!)
36 |
37 | **Advanced Usage:**
38 |
39 | If you have more advanced needs, e.g. turning on/off an event subscription when
40 | an `Ember.Route` is activated/deactivated, or just prefer a more manual
41 | approach, you can inject the provided service and tinker away:
42 |
43 | ```javascript
44 | export default MyRoute.extend({
45 | cordova: Ember.inject.service(),
46 |
47 | activate: function() {
48 | // use named function to unsubscribe later
49 | this.get('cordova').on('pause', this, '_resumeListening');
50 | },
51 |
52 | deactivate: function() {
53 | this.get('cordova').off('pause', this, '_resumeListening');
54 | },
55 |
56 | _resumeListening: function() {
57 | console.log('do your thing');
58 | }
59 | });
60 | ```
61 |
--------------------------------------------------------------------------------
/docs/commands.md:
--------------------------------------------------------------------------------
1 | ##Overview
2 |
3 | All commands follow the pattern `ember cordova:{command}`. You can use the `cdv` alias
4 | insted of`cordova`, for example `ember cdv:{command}`.
5 |
6 | ##Open
7 |
8 | ####Description
9 |
10 | Open the native platform project with the default or specified application
11 |
12 | ####Available options
13 | + platform (default:ios)
14 | + application (default:system default application)
15 |
16 | ####Examples
17 | + `ember cordova:open`
18 | + `ember cordova:open --platform=android --application=eclipse`
19 |
20 |
21 | ##Archive
22 |
23 | ####Description
24 |
25 | Build project and create xcode archive. If the tag or commit options are present
26 | they will be performed after archiving.
27 |
28 | ####Available options
29 | + environment (default:staging)
30 | + tag (default:false)
31 | + commit (default:false)
32 |
33 | ####Examples
34 | + `ember cordova:archive`
35 | + `ember cordova:archive 0.0.2 --environment=staging --commit --tag `
36 |
37 | ##Build
38 |
39 | ####Description
40 |
41 | Build the ember and cordova project together running in the simulator or on a device
42 |
43 | ####Available options
44 | + environment (default:development)
45 | + platform (default:ios)
46 |
47 | ####Examples
48 | + `ember cordova:build`
49 | + `ember cordova:build --environment=production --platform=ios`
50 |
51 | ##Prepare
52 |
53 | ####Description
54 |
55 | Needed after cloning or copying a project.
56 |
57 | ###Available options
58 |
59 | ####Examples
60 | + `ember cordova:prepare`
61 |
62 | ##Cordova
63 |
64 | ####Description
65 |
66 | Passes commands(plugin(s), platform(s), run, emulate) and arguments to the cordova command
67 |
68 | ###Available options
69 | + run
70 | + emulate
71 | + platform(s)
72 | + plugin(s)
73 |
74 | ####Examples
75 | + `ember cordova platform`
76 | + `ember cordova platforms`
77 | + `ember cordova run`
78 |
--------------------------------------------------------------------------------
/lib/ext/promise.js:
--------------------------------------------------------------------------------
1 | // https://github.com/stefanpenner/ember-cli/blob/master/lib/ext/promise.js
2 | 'use strict';
3 |
4 | var RSVP = require('rsvp');
5 | var Promise = RSVP.Promise;
6 |
7 | module.exports = PromiseExt;
8 |
9 | // Utility functions on on the native CTOR need some massaging
10 | module.exports.hash = function() {
11 | return this.resolve(RSVP.hash.apply(null, arguments));
12 | };
13 |
14 | module.exports.denodeify = function() {
15 | var fn = RSVP.denodeify.apply(null, arguments);
16 | var Constructor = this;
17 |
18 | return function() {
19 | return Constructor.resolve(fn.apply(null, arguments));
20 | };
21 | };
22 |
23 | module.exports.filter = function() {
24 | return this.resolve(RSVP.filter.apply(null, arguments));
25 | };
26 |
27 | module.exports.map = function() {
28 | return this.resolve(RSVP.map.apply(null, arguments));
29 | };
30 |
31 | function PromiseExt() {
32 | Promise.apply(this, arguments);
33 | }
34 |
35 | PromiseExt.prototype = Object.create(Promise.prototype);
36 | PromiseExt.prototype.constructor = PromiseExt;
37 | PromiseExt.__proto__ = Promise;
38 |
39 | PromiseExt.prototype.returns = function(value) {
40 | return this.then(function() {
41 | return value;
42 | });
43 | };
44 |
45 | PromiseExt.prototype.invoke = function(method) {
46 | var args = Array.prototype.slice(arguments, 1);
47 |
48 | return this.then(function(value) {
49 | return value[method].apply(value, args);
50 | }, undefined, 'invoke: ' + method + ' with: ' + args);
51 | };
52 |
53 | PromiseExt.prototype.map = function(mapFn) {
54 | var Constructor = this.constructor;
55 |
56 | return this.then(function(values) {
57 | return Constructor.map(values, mapFn);
58 | });
59 | };
60 |
61 | PromiseExt.prototype.filter = function(mapFn) {
62 | var Constructor = this.constructor;
63 |
64 | return this.then(function(values) {
65 | return Constructor.filter(values, mapFn);
66 | });
67 | };
68 |
--------------------------------------------------------------------------------
/blueprints/cordova-starter-kit/files/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | var os = require('os');
4 | var ifaces = os.networkInterfaces();
5 |
6 | var addresses = [];
7 | for (var dev in ifaces) {
8 | ifaces[dev].forEach(function(details){
9 | if(details.family === 'IPv4' && details.address !== '127.0.0.1') {
10 | addresses.push(details.address);
11 | }
12 | });
13 | }
14 |
15 | module.exports = function(environment) {
16 | var ENV = {
17 | modulePrefix: '<%= modulePrefix %>',
18 | environment: environment,
19 | baseURL: '/',
20 | defaultLocationType: 'auto',
21 | EmberENV: {
22 | FEATURES: {
23 | // Here you can enable experimental features on an ember canary build
24 | // e.g. 'with-controller': true
25 | }
26 | },
27 |
28 | APP: {
29 | // Here you can pass flags/options to your application instance
30 | // when it is created
31 | },
32 |
33 | cordova: {
34 | rebuildOnChange: false,
35 | emulate: false,
36 | emberUrl: 'http://' + addresses[0] + ':4200',
37 | liveReload: {
38 | enabled: false,
39 | platform: 'ios'
40 | }
41 | }
42 | };
43 |
44 | if (environment === 'development') {
45 | // ENV.APP.LOG_RESOLVER = true;
46 | ENV.APP.LOG_ACTIVE_GENERATION = true;
47 | // ENV.APP.LOG_TRANSITIONS = true;
48 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
49 | ENV.APP.LOG_VIEW_LOOKUPS = true;
50 |
51 | ENV.apiUrl = 'http://' + addresses[0] + ':3000/api/v1';
52 | ENV.development = true;
53 | }
54 |
55 | if (environment === 'test') {
56 | // Testem prefers this...
57 | ENV.baseURL = '/';
58 | ENV.locationType = 'auto';
59 |
60 | // keep test console output quieter
61 | ENV.APP.LOG_ACTIVE_GENERATION = false;
62 | ENV.APP.LOG_VIEW_LOOKUPS = false;
63 |
64 | ENV.APP.rootElement = '#ember-testing';
65 | }
66 |
67 | if (environment === 'staging') {
68 | ENV.apiUrl = 'http://<%= modulePrefix %>-staging.herokuapp.com/api/v1';
69 | ENV.staging = true;
70 | }
71 |
72 |
73 | if (environment === 'production') {
74 | ENV.apiUrl = 'http://<%= modulePrefix %>.herokuapp.com/api/v1';
75 | ENV.production = true;
76 | }
77 |
78 | return ENV;
79 | };
80 |
--------------------------------------------------------------------------------
/addon/mixins/routes/nav-bar.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Mixin.create({
4 | _navController: Ember.computed('nav.controller', function() {
5 | var name = this.get('nav.controller') || 'application';
6 |
7 | return this.controllerFor(name);
8 | }),
9 |
10 | afterModel: function(model) {
11 | this._setDefaults();
12 | this._setNavOptions(model);
13 | this._setNavActions();
14 |
15 | return this._super.apply(this, arguments);
16 | },
17 |
18 | // Since we are using so many nested paths this makes sure they are set to
19 | // null values
20 | _setDefaults: function() {
21 | var ctrl = this.get('_navController');
22 |
23 | if(!ctrl.get('nav')) {
24 | ctrl.send('resetNavBar');
25 |
26 | } else if(!ctrl.get('nav.title')) {
27 | ctrl.set('nav.title', {});
28 |
29 | } else if(!ctrl.get('nav.leftButton')) {
30 | ctrl.set('nav.leftButton', {});
31 |
32 | } else if(!ctrl.get('nav.rightButton')) {
33 | ctrl.set('nav.rightButton', {});
34 | }
35 | },
36 |
37 | _setNavOptions: function(model) {
38 | var ctrl = this.get('_navController');
39 |
40 | var navOptions = Ember.A([
41 | 'title.text',
42 | 'leftButton.text', 'leftButton.icon',
43 | 'rightButton.text', 'rightButton.icon'
44 | ]);
45 |
46 | navOptions.forEach(function(key){
47 | var optionPath = 'nav.' + key;
48 | var value = this.get(optionPath);
49 |
50 | if (value) {
51 | if(Ember.typeOf(value) === 'function') {
52 | value = value.call(this, model);
53 | }
54 |
55 | ctrl.set(optionPath, value);
56 | }
57 | }, this);
58 | },
59 |
60 | _setNavActions: function() {
61 | var ctrl = this.get('_navController');
62 |
63 | Ember.A(['leftButton', 'rightButton']).forEach(function(button) {
64 | var actionPath = 'nav.' + button + '.action';
65 |
66 | var action = this.get(actionPath);
67 | if (action) {
68 | ctrl.set(actionPath, Ember.run.bind(this, action));
69 | }
70 | }, this);
71 | },
72 |
73 | actions: {
74 | willTransition: function() {
75 | this.get('_navController').send('resetNavBar');
76 | return this._super.apply(this, arguments);
77 | }
78 | }
79 | });
80 |
--------------------------------------------------------------------------------
/lib/tasks/archive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var runCommand = require('../utils/run-command');
5 | var Promise = require('../ext/promise');
6 | var defaultPlatform = require('../utils/default-platform');
7 |
8 | module.exports = function(version, options, project, platform) {
9 | var config = project.cordovaConfig;
10 | var updateXml = function() { return Promise.resolve(); };
11 | var archiveProject = function() { return Promise.resolve(); };
12 |
13 | platform = platform || 'ios';
14 |
15 | if (version) {
16 | updateXml = require('./update-config-xml-version')(version, project);
17 | }
18 |
19 | var build = require('./build')(options.environment, platform, project);
20 |
21 | if(platform === 'ios') {
22 | var iosPath = path.join(project.root, 'cordova', 'platforms/ios');
23 | var archiveCommand = 'xcodebuild -scheme ' + config.name + ' archive';
24 | var archiveMessage = 'Archiving project with xcodebuild';
25 | archiveProject = runCommand(archiveCommand, archiveMessage, {
26 | cwd: iosPath
27 | });
28 | }
29 |
30 | if(platform === 'android' && version) {
31 | var __updateXml = updateXml;
32 |
33 | updateXml = function () {
34 | var androidVersionCode = require('./update-config-xml-android-version-code')(project);
35 | return __updateXml().then(androidVersionCode);
36 | }
37 | }
38 |
39 | var commitCommand = 'git add . && git commit -m "archive version: '
40 | + version + '"';
41 | var commitProject = runCommand(commitCommand, 'Commiting changes', {
42 | cwd: project.root
43 | });
44 |
45 | var tagCommand = 'git tag -a -m "' + 'Version ' + version + '" ' + version;
46 | var tagProject = runCommand(tagCommand, 'Tagging with version ' + version, {
47 | cwd: project.root
48 | });
49 |
50 | return function() {
51 | var promises = updateXml().then(build).then(archiveProject);
52 |
53 | if (options.commit && options.tag) {
54 | promises.then(commitProject).then(tagProject);
55 | } else {
56 | if (options.commit) {
57 | promises.then(commitProject)
58 | } else if (options.tag) {
59 | promises.then(tagProject);
60 | }
61 | }
62 |
63 | return promises;
64 | }
65 | };
66 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/open-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Open', function() {
2 | var project;
3 | beforeEach(function() {
4 | project = newProject();
5 | });
6 |
7 | it('rejects when the platform isn\'t supported', function() {
8 | var open = proxyquire('../../lib/tasks/open', {});
9 |
10 | return open(project, 'fake-platform').catch(function(err) {
11 | expect(err.toString()).to.match(/platform is not supported/);
12 | });
13 | });
14 |
15 | describe('runs correct command on each platform', function() {
16 | var platform;
17 | before(function() {
18 | platform = process.platform;
19 | });
20 |
21 | after(function() {
22 | process.platform = platform;
23 | });
24 |
25 | describe('darwin', function() {
26 | beforeEach(function() {
27 | process.platform = 'darwin';
28 | });
29 |
30 | it('ios', function() {
31 | return assertOpenCommand(project, 'ios', 'open project-root/cordova/platforms/ios/*.xcodeproj');
32 | });
33 |
34 | it('android', function() {
35 | return assertOpenCommand(project, 'android', 'open project-root/cordova/platforms/android/.project');
36 | });
37 | });
38 |
39 | describe('win32', function() {
40 | beforeEach(function() {
41 | process.platform = 'win32';
42 | });
43 |
44 | it('ios', function() {
45 | return assertOpenCommand(project, 'ios', 'start project-root/cordova/platforms/ios/*.xcodeproj');
46 | });
47 |
48 | it('android', function() {
49 | return assertOpenCommand(project, 'android', 'start project-root/cordova/platforms/android/.project');
50 | });
51 | });
52 |
53 | describe('other', function() {
54 | beforeEach(function() {
55 | process.platform = 'other';
56 | });
57 |
58 | it('ios', function() {
59 | return assertOpenCommand(project, 'ios', 'xdg-open project-root/cordova/platforms/ios/*.xcodeproj');
60 | });
61 |
62 | it('android', function() {
63 | return assertOpenCommand(project, 'android', 'xdg-open project-root/cordova/platforms/android/.project');
64 | });
65 | });
66 | });
67 | });
68 |
69 | function assertOpenCommand(project, platform, assertion) {
70 | var open = proxyquire('../../lib/tasks/open', {
71 | '../utils/run-command': function(command) {
72 | expect(command).to.eql(assertion);
73 | }
74 | });
75 | return open(project, platform);
76 | }
77 |
--------------------------------------------------------------------------------
/docs/nav-bar.md:
--------------------------------------------------------------------------------
1 | # Nav Bar
2 |
3 | ## Description
4 |
5 | The nav-bar component, partial, and mixins provide an easy to use way of having
6 | a global nav bar that gets updated between routes automatically by defining
7 | options on the route.
8 |
9 | The component itself is very barebones but there is also a partial you can
10 | include within it along with a few mixins to get a full featured nav bar without
11 | much work.
12 |
13 | # Usage
14 |
15 | Add this in your application template
16 |
17 | ```hbs
18 | {{#cdv-nav-bar}}
19 | {{partial 'cdv-generic-nav-bar'}}
20 | {{/cdv-nav-bar }}
21 | ```
22 |
23 | In your application controller, mixin the controller NavBarMixin. If you don't
24 | do this, the actions within the nav-bar won't work. This is where all state for
25 | the nav bar lives.
26 |
27 | ```js
28 | import NavBarMixin from 'ember-cli-cordova/mixins/controllers/nav-bar';
29 |
30 | export default Ember.Controller.extend(NavBarMixin);
31 | ```
32 |
33 | Then in any route you can mixin the route NavBarMixin and set options for the
34 | nav bar. The options will be reset on each transition. This is implemented using
35 | ember's
36 | [willTransition](http://emberjs.com/api/classes/Ember.Route.html#event_willTransition) in the route. All options are optional.
37 |
38 | ```js
39 | import NavBarMixin from 'ember-cli-cordova/mixins/routes/nav-bar';
40 |
41 | export default Ember.Route.extend(NavBarMixin, {
42 | nav: {
43 | // Default: application
44 | // If the cdv-nav-bar is included in something other than the application
45 | // template this needs to be set to that
46 | controller: 'application',
47 |
48 |
49 | // The text or icon option for title, leftButton, or rightButton can be
50 | // a string or function. If it's a function // it will be called in the
51 | // context of the afterModel hook and have the // model passed in as an
52 | // argument
53 |
54 | title: {
55 | text: 'Title'
56 | },
57 |
58 | leftButton: {
59 | // Text to show
60 | text: function(model) {
61 | return model.get('title');
62 | },
63 |
64 | // Class of an icon to display
65 | icon: 'save',
66 |
67 | // Action to trigger when it is clicked. It will trigger in the context of
68 | // the route so you have access to the correct `this`.
69 | action: function() {
70 | // ...
71 | }
72 | },
73 |
74 | // Same options as leftButton
75 | rightButton: {
76 | // ...
77 | },
78 | }
79 | });
80 | ```
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-cordova",
3 | "version": "0.1.0-beta-2",
4 | "description": "A tool for creating hybrid apps using a combination of ember-cli and cordova ",
5 | "homepage": "https://github.com/poetic/ember-cli-cordova",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/poetic/ember-cli-cordova.git"
9 | },
10 | "main": "index.js",
11 | "directories": {
12 | "doc": "docs",
13 | "test": "tests"
14 | },
15 | "scripts": {
16 | "node-test": "mocha --require node-tests/helpers/_helper.js --reporter spec node-tests/**/*-test.js node-tests/**/**/*-test.js",
17 | "ember-test": "ember test",
18 | "test": "npm run node-test && npm run ember-test"
19 | },
20 | "engines": {
21 | "node": ">= 0.10.0"
22 | },
23 | "author": "Jake Craige ",
24 | "license": "MIT",
25 | "ember-addon": {
26 | "configPath": "tests/dummy/config"
27 | },
28 | "keywords": [
29 | "ember-addon"
30 | ],
31 | "dependencies": {
32 | "broccoli-funnel": "^0.2.3",
33 | "broccoli-merge-trees": "^1.1.0",
34 | "chalk": "^0.4.0",
35 | "ember-cli-babel": "^5.1.5",
36 | "findup-sync": "^0.1.3",
37 | "fs-extra": "^0.26.5",
38 | "lodash": "^4.5.1",
39 | "pleasant-progress": "^1.0.1",
40 | "recursive-readdir": "^1.1.1",
41 | "rsvp": "^3.0.6",
42 | "sinon": "^1.17.3",
43 | "underscore.string": "^2.3.3"
44 | },
45 | "devDependencies": {
46 | "broccoli-asset-rev": "^2.2.0",
47 | "chai": "^1.9.1",
48 | "ember-ajax": "0.7.1",
49 | "ember-cli": "2.3.0",
50 | "ember-cli-app-version": "^1.0.0",
51 | "ember-cli-dependency-checker": "^1.2.0",
52 | "ember-cli-htmlbars": "^1.0.1",
53 | "ember-cli-htmlbars-inline-precompile": "^0.3.1",
54 | "ember-cli-inject-live-reload": "^1.3.1",
55 | "ember-cli-qunit": "^1.2.1",
56 | "ember-cli-release": "0.2.8",
57 | "ember-cli-sri": "^2.0.0",
58 | "ember-cli-uglify": "^1.2.0",
59 | "ember-disable-prototype-extensions": "^1.1.0",
60 | "ember-disable-proxy-controllers": "^1.0.1",
61 | "ember-export-application-global": "^1.0.4",
62 | "ember-load-initializers": "^0.5.0",
63 | "ember-resolver": "^2.0.3",
64 | "ember-sinon": "0.5.0",
65 | "ember-try": "^0.1.2",
66 | "glob": "^4.5.3",
67 | "loader.js": "^4.0.0",
68 | "mocha": "^1.20.1",
69 | "mocha-jshint": "0.0.7",
70 | "proxyquire": "^1.0.1",
71 | "qunit-bdd": "jakecraige/qunit-bdd.git#ember-addon",
72 | "tmp-sync": "^1.0.1"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/node-tests/unit/addon-test.js:
--------------------------------------------------------------------------------
1 | var addon = require('../../index');
2 |
3 | function expectWithConfig(config, env, call) {
4 | if (call) {
5 | return expect(addon.config(env || 'development', config));
6 | }
7 | else {
8 | return expect(addon.config.bind(addon, env || 'development', config));
9 | }
10 | }
11 |
12 | var errRegex = /ember-cli-cordova: You must specify the locationType as 'hash' in your environment\.js/;
13 |
14 | describe('Addon', function () {
15 | describe('config', function () {
16 | var savedEnvVar;
17 |
18 | beforeEach(function () {
19 | savedEnvVar = process.env.EMBER_CLI_CORDOVA;
20 | });
21 |
22 | afterEach(function () {
23 | process.env.EMBER_CLI_CORDOVA = savedEnvVar;
24 | });
25 |
26 | describe('validates location type', function () {
27 | it('should throw Error when auto', function () {
28 | expectWithConfig({
29 | locationType: 'auto'
30 | }).to.throw(Error, errRegex);
31 | });
32 |
33 | it('should not throw an error when hash', function () {
34 | expectWithConfig({
35 | locationType: 'hash'
36 | }).to.not.throw(Error, errRegex);
37 | });
38 |
39 | it('should not throw an error with auto in test environment', function () {
40 | expectWithConfig({
41 | locationType: 'auto'
42 | }, 'test').to.not.throw(Error, errRegex);
43 | });
44 |
45 | it('should not throw an error when the env var is set to 0', function () {
46 | process.env.EMBER_CLI_CORDOVA = '0';
47 | expectWithConfig({
48 | locationType: 'auto'
49 | }).to.not.throw(Error, errRegex);
50 | });
51 | });
52 |
53 | describe('should replace the locationType', function () {
54 | it('should use the defaultLocationType when building for test', function () {
55 | expectWithConfig({
56 | defaultLocationType: 'auto'
57 | }, 'test', true).to.have.property('locationType', 'auto');
58 | });
59 |
60 | it('should use the defaultLocationType when the env var is set to 0', function () {
61 | process.env.EMBER_CLI_CORDOVA = '0';
62 | expectWithConfig({
63 | defaultLocationType: 'auto'
64 | }, null, true).to.have.property('locationType', 'auto');
65 | });
66 |
67 | it('should use hash as locationType', function () {
68 | expectWithConfig({
69 | defaultLocationType: 'auto'
70 | }, null, true).to.have.property('locationType', 'hash');
71 | });
72 | });
73 |
74 | });
75 | });
76 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/build-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Build', function() {
2 | var project, commandOffset;
3 | beforeEach(function() {
4 | project = newProject();
5 | commandOffset = 0;
6 | });
7 |
8 | describe('env argument', function() {
9 | it('development - runs proper commands', function() {
10 | var commands = [
11 | 'ember build --environment development',
12 | 'cordova build ios'
13 | ];
14 |
15 | var build = proxyquire('../../lib/tasks/build', {
16 | '../utils/run-command': function(command) {
17 | expect(command).to.eql(commands[commandOffset++]);
18 | return resolveFn;
19 | },
20 | '../tasks/link-environment': function() {
21 | return resolveFn;
22 | }
23 | });
24 |
25 | return build('development', 'ios', project)();
26 | });
27 |
28 | it('production - runs proper commands', function() {
29 | var commands = [
30 | 'ember build --environment production',
31 | 'cordova build ios --release'
32 | ];
33 |
34 | var build = proxyquire('../../lib/tasks/build', {
35 | '../utils/run-command': function(command) {
36 | expect(command).to.eql(commands[commandOffset++]);
37 | return resolveFn;
38 | },
39 | '../tasks/link-environment': function() {
40 | return resolveFn;
41 | }
42 | });
43 |
44 | return build('production', 'ios', project)();
45 | });
46 | });
47 |
48 | describe('platform argument', function() {
49 | it('development - runs proper commands', function() {
50 | var commands = [
51 | 'ember build --environment development',
52 | 'cordova build android'
53 | ];
54 |
55 | var build = proxyquire('../../lib/tasks/build', {
56 | '../utils/run-command': function(command) {
57 | expect(command).to.eql(commands[commandOffset++]);
58 | return resolveFn;
59 | },
60 | '../tasks/link-environment': function() {
61 | return resolveFn;
62 | }
63 | });
64 |
65 | return build('development', 'android', project)();
66 | });
67 |
68 | it('production - runs proper commands', function() {
69 | var commands = [
70 | 'ember build --environment production',
71 | 'cordova build android --release'
72 | ];
73 |
74 | var build = proxyquire('../../lib/tasks/build', {
75 | '../utils/run-command': function(command) {
76 | expect(command).to.eql(commands[commandOffset++]);
77 | return resolveFn;
78 | },
79 | '../tasks/link-environment': function() {
80 | return resolveFn;
81 | }
82 | });
83 |
84 | return build('production', 'android', project)();
85 | });
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/post-build-test.js:
--------------------------------------------------------------------------------
1 | var uiMock = { write: noop };
2 |
3 | describe('Tasks - Post Build', function() {
4 | var project;
5 | beforeEach(function() {
6 | project = newProject();
7 | });
8 |
9 | var options;
10 | describe('rebuildOnChange is false', function() {
11 | beforeEach(function() {
12 | options = { rebuildOnChange: false };
13 | });
14 |
15 | it('return noop', function() {
16 | var postBuild = proxyquire('../../lib/tasks/post-build', {});
17 |
18 | var res = postBuild({}, options);
19 |
20 | expect(res.toString()).to.eql(noop.toString());
21 | });
22 | });
23 |
24 | describe('rebuildOnChange is true', function() {
25 | beforeEach(function() {
26 | options = { rebuildOnChange: true };
27 | });
28 |
29 | it('returns resolving promise and executes correct build', function() {
30 | var postBuild = proxyquire('../../lib/tasks/post-build', {
31 | '../utils/run-command': function() {
32 | return resolveFn;
33 | },
34 | '../ui': uiMock
35 | });
36 |
37 | return postBuild(project, options)().then(function() {
38 | expect(true).to.be.ok;
39 | });
40 | });
41 |
42 | describe('emulate is false', function() {
43 | beforeEach(function() {
44 | options.emulate = false;
45 | });
46 |
47 | it('runs correct command', function() {
48 | var postBuild = proxyquire('../../lib/tasks/post-build', {
49 | '../utils/run-command': function(command){
50 | expect(command).to.eql('cordova build ios');
51 | return resolveFn;
52 | },
53 | '../ui': uiMock
54 | });
55 |
56 | return postBuild(project, options)().then(function() {
57 | expect(true).to.be.ok;
58 | });
59 | });
60 | });
61 |
62 | describe('emulate is true', function() {
63 | beforeEach(function() {
64 | options.emulate = true;
65 | });
66 |
67 | it('runs correct command', function() {
68 | var postBuild = proxyquire('../../lib/tasks/post-build', {
69 | '../utils/run-command': function(command){
70 | expect(command).to.eql('cordova build ios && cordova emulate ios');
71 | return resolveFn;
72 | },
73 | '../ui': uiMock
74 | });
75 |
76 | return postBuild(project, options)().then(function() {
77 | expect(true).to.be.ok;
78 | });
79 | });
80 | });
81 |
82 | describe('platform is android and emulate is true', function() {
83 | beforeEach(function() {
84 | options.platform = 'android';
85 | options.emulate = true;
86 | });
87 |
88 | it('runs correct command', function() {
89 | var postBuild = proxyquire('../../lib/tasks/post-build', {
90 | '../utils/run-command': function(command){
91 | expect(command).to.eql('cordova build android && cordova emulate android');
92 | return resolveFn;
93 | },
94 | '../ui': uiMock
95 | });
96 |
97 | return postBuild(project, options)().then(function() {
98 | expect(true).to.be.ok;
99 | });
100 | });
101 | });
102 | });
103 | });
104 |
105 |
106 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var fs = require('fs');
5 | var commands = require('./lib/commands');
6 | var postBuild = require('./lib/tasks/post-build');
7 | var defaults = require('lodash').defaults;
8 | var chalk = require('chalk');
9 | var mergeTrees = require('broccoli-merge-trees');
10 | var Funnel = require('broccoli-funnel');
11 |
12 | module.exports = {
13 | name: 'ember-cli-cordova',
14 |
15 | _isTargetCordova: function () {
16 | return !process.env.EMBER_CLI_CORDOVA ||
17 | ['0', 'off', 'false', 'no'].indexOf(process.env.EMBER_CLI_CORDOVA.toLowerCase()) === -1;
18 | },
19 |
20 | config: function (env, config) {
21 | var conf = {isCordovaBuild: this._isTargetCordova()};
22 | if (conf.isCordovaBuild && env !== 'test') {
23 | if (config.locationType && config.locationType !== 'hash') {
24 | throw new Error('ember-cli-cordova: You must specify the locationType as \'hash\' in your environment.js or rename it to defaultLocationType.');
25 | }
26 | conf.locationType = 'hash';
27 | }
28 | else if (!conf.locationType) {
29 | conf.locationType = config.defaultLocationType || 'auto';
30 | }
31 | conf.cordova = defaults(config.cordova || {}, {
32 | liveReload: {
33 | enabled: false,
34 | platform: 'ios'
35 | }
36 | });
37 | return conf;
38 | },
39 |
40 | contentFor: function (type) {
41 | if (this._isTargetCordova() && type === 'body') {
42 | return '';
43 | }
44 | },
45 |
46 | includedCommands: function () {
47 | return commands;
48 | },
49 |
50 | cdvConfig: function () {
51 | return this.project.config(process.env.EMBER_ENV || 'development').cordova;
52 | },
53 |
54 | postBuild: function () {
55 | if (this._isTargetCordova()) {
56 | return postBuild(this.project, this.cdvConfig())();
57 | }
58 | else {
59 | return function () {
60 | };
61 | }
62 | },
63 |
64 | treeForPublic: function (tree) {
65 | var config = this.cdvConfig();
66 |
67 | if (this._isTargetCordova() && config.liveReload.enabled) {
68 | if (!config.liveReload.platform) {
69 | throw new Error('ember-cli-cordova: You must specify a liveReload.platform in your environment.js');
70 | }
71 |
72 | var platformsPath = path.join(this.project.root, 'cordova', 'platforms');
73 | var pluginsPath;
74 |
75 | if (config.liveReload.platform === 'ios') {
76 | pluginsPath = path.join(platformsPath, 'ios', 'www');
77 | }
78 | else if (config.liveReload.platform === 'browser') {
79 | pluginsPath = path.join(platformsPath, 'browser', 'www');
80 | }
81 | else if (config.liveReload.platform === 'android') {
82 | pluginsPath = path.join(platformsPath, 'android', 'assets', 'www');
83 | }
84 | else {
85 | pluginsPath = path.join(platformsPath, config.liveReload.platform);
86 | }
87 |
88 | var files = ['cordova.js', 'cordova_plugins.js'];
89 |
90 | files.forEach(function (file) {
91 | var filePath = path.join(pluginsPath, file);
92 | if (!fs.existsSync(filePath)) {
93 | var err = new Error('ember-cli-cordova: ' + filePath + ' did not exist. It is required for Device LiveReload to work.');
94 | err.stack = null;
95 | throw err;
96 | }
97 | });
98 |
99 | if (fs.existsSync(path.join(pluginsPath, 'plugins'))) {
100 | files.push('plugins/**');
101 | }
102 |
103 | var pluginsTree = new Funnel(this.treeGenerator(pluginsPath), {
104 | srcDir: '/',
105 | include: files,
106 | destDir: '/'
107 | });
108 |
109 | console.log(chalk.green('ember-cli-cordova: Device LiveReload is enabled'));
110 |
111 | return mergeTrees([tree, pluginsTree]);
112 | }
113 |
114 | return tree;
115 | }
116 | };
117 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-cli-cordova [](https://travis-ci.org/poetic/ember-cli-cordova) [](https://gitter.im/poetic/ember-cli-cordova?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
2 |
3 | I will not be focusing on backward compatibility with older ember-cli versions
4 | as it's moving too fast and the API is constantly changing. I will always have
5 | this working with the latest stable release of ember-cli.
6 |
7 | ## Goals
8 |
9 | To provide a toolchain tightly integrated with ember-cli to make developing hybrid
10 | apps with cordova and ember as simple as possible.
11 |
12 | ## Supported Platforms
13 |
14 | Android and iOS. While we don't plan on actively supporting other platforms,
15 | feel free to open an issue or submit a pull request.
16 |
17 | ## Required Ember Versions
18 |
19 | Releases as of 0.1.0 require Ember 2.x and ember-cli 2.3.0.
20 |
21 | The lastest release for Ember 1.x is 0.0.19 and requires at least ember-cli >= 0.1.1
22 |
23 | ## Getting Started
24 |
25 | Please see our Getting Started guide
26 | [here](https://github.com/poetic/ember-cli-cordova/blob/master/docs/getting-started.md)
27 |
28 | ## Blueprints
29 | + `ember g cordova-init com.reverse.domain --platform=android` Required generator
30 | that sets up the cordova project with a few tweaks to the ember app
31 | + (optional) `ember g cordova-starter-kit` Adds some packages and files that makes up the
32 | base setup for projects I develop.
33 |
34 | ## Commands
35 | + `ember cordova:open` open xcode project
36 | + `ember cordova:build --environment=production --platform=ios` build cordova project
37 | + `ember cordova:archive 0.0.2 --environment=staging --commit --tag` archive ios project with xcode
38 | + `ember cordova:prepare` needs to be run after cloning a project
39 | + `ember cordova` Passes commands(plugin(s), platform(s), run, emulate) and arguments to the cordova command
40 | + `ember help` ember cli help with a section for addon provided commands as well
41 |
42 | # Docs
43 |
44 | Documentation can be found found in the docs directory [here](https://github.com/poetic/ember-cli-cordova/tree/master/docs).
45 |
46 | - [Getting Started](https://github.com/poetic/ember-cli-cordova/blob/master/docs/getting-started.md)
47 | - [Configuration](https://github.com/poetic/ember-cli-cordova/blob/master/docs/configuration.md)
48 | - [FAQ](https://github.com/poetic/ember-cli-cordova/blob/master/docs/faq.md)
49 |
50 | # ember-cordova
51 |
52 | [ember-cordova](https://github.com/isleofcode/ember-cordova) recently started as a fork of ember-cli-cordova by some
53 | contributors and maintainers. It only supports Ember 2, and includes
54 | added features such as build hooks, native splash screen & icon management,
55 | a platform service (e.g. isIOS) and an ember/cordova plugin ecosystem.
56 |
57 | ember-cli-cordova will still be maintained and active.
58 |
59 | It does not include features such as mobiletouch by default, starter
60 | blueprints and support for Ember <2. For these items, your best bet is
61 | to continue with ember-cli-cordova.
62 |
63 | # Dependency Docs
64 |
65 | - [ember-cli](http://ember-cli.com)
66 | - [cordova](http://cordova.apache.org/docs/en/4.0.0/)
67 |
68 | # Contributing
69 |
70 | ## Working with master
71 |
72 | ``` sh
73 | git clone https://github.com/poetic/ember-cli-cordova.git
74 | cd ember-cli-cordova
75 | npm i && bower i
76 | npm link
77 | ember new CordovaTest
78 | cd CordovaTest
79 | npm install --save-dev ember-cli-cordova
80 | npm link ember-cli-cordova
81 | ```
82 |
83 | After this, any changes you make to the cloned repo will be instantly reflected
84 | in the test app you generated. It just symlinks the node_modules folder.
85 |
86 | # Example App
87 |
88 | You can find an example app using this here:
89 | [jakecraige/ember-cli-cordova-example-app](https://github.com/jakecraige/ember-cli-cordova-example-app)
90 |
91 | # Credits
92 |
93 | [ember-cli](https://github.com/stefanpenner/ember-cli)
94 | [ember](https://github.com/emberjs/emberjs)
95 |
--------------------------------------------------------------------------------
/tests/integration/nav-bar-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import describeApp from '../helpers/describe-app';
3 |
4 | describeApp('Integration - Nav Bar', function() {
5 | describe('Route Mixin', function() {
6 | describe('Template', function() {
7 | it('updates between routes', function() {
8 | visit('nav-bar');
9 |
10 | andThen(function() {
11 | equal(find('header h1').text().trim(), 'Index');
12 | equal(find('header button:first').text().trim(), 'iLeft');
13 | equal(find('header button:last').text().trim(), 'iRight');
14 | });
15 |
16 | visit('nav-bar/page-1');
17 |
18 | andThen(function() {
19 | equal(find('header h1').text().trim(), 'Page 1');
20 | equal(find('header button:first').text().trim(), 'pLeft');
21 | equal(find('header button:last').text().trim(), 'pRight');
22 | });
23 | });
24 |
25 | it('values can be a function', function() {
26 | visit('nav-bar/options-from-model');
27 |
28 | andThen(function() {
29 | var leftButton = find('header button:first');
30 | var title = find('header h1');
31 | var rightButton = find('header button:last');
32 |
33 | equal(title.text().trim(), 'modelOption');
34 |
35 | equal(leftButton.text().trim(), 'modelLeft');
36 | ok(leftButton.find('i').hasClass('leftClass'));
37 |
38 | equal(rightButton.text().trim(), 'modelRight');
39 | ok(rightButton.find('i').hasClass('rightClass'));
40 | });
41 | });
42 | });
43 |
44 | describe('Actions', function() {
45 | before(function() {
46 | var navIndex = this.app.__container__.lookup('route:nav-bar/index');
47 | var page1 = this.app.__container__.lookup('route:nav-bar/page-1');
48 | var spec = this;
49 |
50 | spec.navIndexStub = sinon.stub();
51 | navIndex.setProperties({
52 | 'nav.leftButton.action': function() {
53 | spec.navIndexStub('left');
54 | },
55 | 'nav.rightButton.action': function() {
56 | spec.navIndexStub('right');
57 | }
58 | });
59 |
60 | spec.page1Stub = sinon.stub();
61 | page1.setProperties({
62 | 'nav.leftButton.action': function() {
63 | spec.page1Stub('left');
64 | },
65 | 'nav.rightButton.action': function() {
66 | spec.page1Stub('right');
67 | }
68 | });
69 | });
70 |
71 | it('updates between routes', function() {
72 | visit('nav-bar');
73 |
74 | click('header button:first');
75 |
76 | andThen(Ember.run.bind(this, function() {
77 | ok(this.navIndexStub.calledWith('left'));
78 | ok(!this.navIndexStub.calledWith('right'));
79 | }));
80 |
81 | click('header button:last');
82 |
83 | andThen(Ember.run.bind(this, function() {
84 | ok(this.navIndexStub.calledWith('left'));
85 | ok(this.navIndexStub.calledWith('right'));
86 | }));
87 |
88 | visit('nav-bar/page-1');
89 |
90 | click('header button:first');
91 |
92 | andThen(Ember.run.bind(this, function() {
93 | ok(this.page1Stub.calledWith('left'));
94 | ok(!this.page1Stub.calledWith('right'));
95 | }));
96 |
97 | click('header button:last');
98 |
99 | andThen(Ember.run.bind(this, function() {
100 | ok(this.page1Stub.calledWith('left'));
101 | ok(this.page1Stub.calledWith('right'));
102 | }));
103 | });
104 | });
105 |
106 | describe('willTransiton reset', function() {
107 | it('resets nav options on transition', function() {
108 | visit('nav-bar');
109 |
110 | andThen(function() {
111 | equal(find('header h1').text().trim(), 'Index');
112 | });
113 |
114 | visit('nav-bar/should-reset');
115 |
116 | andThen(Ember.run.bind(this, function() {
117 | var ctrl = this.lookupController('nav-bar');
118 |
119 | equal(find('header h1').text().trim(), '');
120 | equal(find('header button:first').text().trim(), '');
121 | equal(find('header button:last').text().trim(), '');
122 | deepEqual(ctrl.get('nav'), {title: {}, leftButton: {}, rightButton: {}});
123 | }));
124 | });
125 | });
126 | });
127 | });
128 |
--------------------------------------------------------------------------------
/node-tests/unit/tasks/archive-test.js:
--------------------------------------------------------------------------------
1 | describe('Tasks - Archive', function() {
2 | var project;
3 | beforeEach(function() {
4 | project = newProject();
5 | });
6 |
7 | describe('version parameter validation', function() {
8 | it('calls config-xml-version with version', function() {
9 | var archiveVersion = '0.1.0';
10 |
11 | var archive = proxyquire('../../lib/tasks/archive', {
12 | './update-config-xml-version': function(version, project) {
13 | expect(version).to.eql(archiveVersion);
14 | return resolveFn;
15 | },
16 | './build': resolveFn,
17 | '../utils/run-command': resolveFn
18 | });
19 |
20 | return archive(archiveVersion, {}, project)();
21 | });
22 |
23 | it('doesn\'t call config-xml-version with version when undefined', function() {
24 | var archive = proxyquire('../../lib/tasks/archive', {
25 | './update-config-xml-version': function(version, project) {
26 | expect(false, 'should not have called here').to.be.ok;
27 | return resolveFn;
28 | },
29 | './build': resolveFn,
30 | '../utils/run-command': resolveFn
31 | });
32 |
33 | return archive(undefined, {}, project)();
34 | });
35 | });
36 |
37 | it('prepares proper commands', function() {
38 | var archiveVersion = "0.1.0";
39 | var commandOffset = 0;
40 |
41 | var commands = [
42 | 'xcodebuild -scheme ' + project.cordovaConfig.name + ' archive',
43 | 'git add . && git commit -m "archive version: ' + archiveVersion + '"',
44 | 'git tag -a -m "Version ' + archiveVersion + '" ' + archiveVersion
45 | ];
46 |
47 | var archive = proxyquire('../../lib/tasks/archive', {
48 | '../utils/run-command': function(command, msg, options){
49 | expect(command).to.eql(commands[commandOffset++]);
50 | return resolveFn;
51 | },
52 | './update-config-xml-version': function(version, project) {
53 | expect(version).to.eql(archiveVersion)
54 | return resolveFn;
55 | },
56 | './build': resolveFn
57 | });
58 |
59 | return archive(archiveVersion, {}, project);
60 | });
61 |
62 | describe('executes proper commands', function() {
63 | var archiveVersion;
64 | beforeEach(function() {
65 | archiveVersion = '0.1.0';
66 | });
67 |
68 | it('with no options', function() {
69 | var commands = [
70 | 'update-config-xml-version',
71 | 'build',
72 | 'xcodebuild -scheme ' + project.cordovaConfig.name + ' archive'
73 | ];
74 |
75 | var options = {};
76 |
77 | return expectCommandsToBeCalled(
78 | archiveVersion, options, project, commands
79 | );
80 | });
81 |
82 | it('with commit option', function() {
83 | var commands = [
84 | 'update-config-xml-version',
85 | 'build',
86 | 'xcodebuild -scheme ' + project.cordovaConfig.name + ' archive',
87 | 'git add . && git commit -m "archive version: ' + archiveVersion + '"'
88 | ];
89 |
90 | var options = { commit: true };
91 |
92 | return expectCommandsToBeCalled(
93 | archiveVersion, options, project, commands
94 | );
95 | });
96 |
97 | it('with tag option', function() {
98 | var commands = [
99 | 'update-config-xml-version',
100 | 'build',
101 | 'xcodebuild -scheme ' + project.cordovaConfig.name + ' archive',
102 | 'git tag -a -m "Version ' + archiveVersion + '" ' + archiveVersion
103 | ];
104 |
105 | var options = { tag: true };
106 |
107 | return expectCommandsToBeCalled(
108 | archiveVersion, options, project, commands
109 | );
110 | });
111 |
112 | // TODO: It says tag is never called. But I see no reason why it shouldn't
113 | // be. Will need to investigate and fix later
114 | it.skip('with commit and tag option', function() {
115 | var commands = [
116 | 'update-config-xml-version',
117 | 'build',
118 | 'xcodebuild -scheme ' + project.cordovaConfig.name + ' archive',
119 | 'git add . && git commit -m "archive version: ' + archiveVersion + '"',
120 | 'git tag -a -m "Version ' + archiveVersion + '" ' + archiveVersion
121 | ];
122 |
123 | var options = { commit: true, tag: true };
124 |
125 | return expectCommandsToBeCalled(
126 | archiveVersion, options, project, commands
127 | );
128 | });
129 | });
130 | });
131 |
132 | function expectCommandsToBeCalled(archiveVersion, options, project, commands) {
133 | var stubbedArchive = stubArchive();
134 | var stubs = stubbedArchive.stubs;
135 | var archive = stubbedArchive.archive;
136 |
137 | return archive(archiveVersion, options, project)().then(function() {
138 | commands.forEach(function(command, index) {
139 | var stub = stubs[command];
140 | if (stub) {
141 | expect(stub.called, command + ' was never called').to.be.ok;
142 | } else {
143 | expect(false, command + ' was never even stubbed').to.be.ok;
144 | }
145 | });
146 | });
147 | }
148 |
149 | function stubArchive() {
150 | var RSVP = require('rsvp');
151 | var stubs = {};
152 | var archive = proxyquire('../../lib/tasks/archive', {
153 | '../utils/run-command': function(command, msg, options){
154 | return stubs[command] = sinon.stub().returns(RSVP.resolve(command));
155 | },
156 |
157 | './update-config-xml-version': function(version, project) {
158 | return stubs['update-config-xml-version'] = sinon.stub().returns(
159 | Promise.resolve('update-config-xml-version')
160 | );
161 | },
162 |
163 | './build': function(env, platform, project) {
164 | return stubs['build'] = sinon.stub().returns(Promise.resolve('build'));
165 | }
166 | });
167 |
168 | return {
169 | stubs: stubs,
170 | archive: archive
171 | };
172 | }
173 |
--------------------------------------------------------------------------------
/docs/getting-started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | This guide will walk you through setting up your first app with
4 | ember-cli-cordova.
5 |
6 | ## Prerequisites
7 |
8 | - [ember-cli](http://www.ember-cli.com)
9 | - [cordova](https://www.npmjs.org/package/cordova)
10 |
11 | Ember-cli-cordova requires ember-cli and cordova. You may install them as follows:
12 |
13 | ```
14 | npm install -g ember-cli
15 | npm install -g cordova
16 | ```
17 |
18 | ## Setting Up The App
19 |
20 | First, let's set up your ember-cli project:
21 |
22 | ```sh
23 | ember new hello
24 | ```
25 |
26 | After that's set up, we need to add the ember-cli-cordova addon to the application. Go in the freshly generated `hello` folder, then install the addon.
27 |
28 | ```sh
29 | ember install ember-cli-cordova
30 | ```
31 |
32 | Ember cli-cordova requires cordova. If you don't have cordova, use this line to install it.
33 |
34 | ```sh
35 | npm install -g cordova
36 | ```
37 |
38 | To intialize the cordova project we use a generator provided by
39 | ember-cli-cordova. You pass in the com domain identifier that you want to use
40 | with your app. It can be anything you like as long as it's unique. This matters
41 | if you plan on releasing it to the app stores. It takes an optional `platform`
42 | argument that defaults to `ios`. If you want to generate an android project you
43 | would pass in `--platform=android` at the end or set your default platform in [cordova configuration](https://github.com/poetic/ember-cli-cordova/blob/master/docs/configuration.md).
44 |
45 | ```sh
46 | ember generate cordova-init com.poeticsystems.hello
47 | ```
48 |
49 | This will prompt you to overwrite some default files. You should overwrite them
50 | as they provide some required settings and helpful additions.
51 |
52 | This will also create the cordova project for you in the `cordova` directory. If
53 | you ever need raw access to the cordova project you can `cd` into this directory
54 | to run the command or modify files.
55 |
56 | After that, the project is ready to go. There are some configuration options in
57 | your environment config that you can set to enable / disable some features. See
58 | the [configuration](https://github.com/poetic/ember-cli-cordova/blob/master/docs/configuration.md) section for information on that.
59 |
60 | ### Optional Starter Kit
61 |
62 | There's also a starter kit generator. This includes lots of goodies that we use
63 | at our company to develop our cordova apps. things like
64 | [broccoli-sass](https://github.com/joliss/broccoli-sass) for sass support and
65 | [liquid-fire](https://github.com/ef4/liquid-fire) for animations. It also
66 | includes a default application adapter, modal component, style resets and extra
67 | configuration.
68 |
69 | To run this, simple run
70 |
71 | ```sh
72 | ember generate cordova-starter-kit
73 | ```
74 |
75 | ## Developing The App
76 |
77 | Once your project is set up, you're ready to start developing. We've tried to
78 | keep the experience as similar to ember-cli as possible. You just need to move
79 | your `locationType` setting in `config/environment.js` to `defaultLocationType`
80 | so that it'd be used when not building for cordova (cordova needs `hash` as
81 | `locationType`).
82 |
83 | Then you can simply run the `serve` command and begin
84 |
85 | ```sh
86 | ember serve
87 | ```
88 |
89 | This will run the ember server and behave no different than in vanilla
90 | ember-cli. This is the primary place you will be working as it provides the
91 | quickest feedback loop, debugging tools and best experience.
92 |
93 | The one drawback to this is that any cordova plugins you use will not work in
94 | the browser. This means that when you want to test the functionality of
95 | a plugin, you will need to load the app up on a simulator or device.
96 |
97 | When you need to serve or build files for a browser environment (not for cordova)
98 | be sure to override the `EMBER_CLI_CORDOVA` environment variable to set it to a
99 | falsy value (`0`, `no`, `off` or `false`). It'll allow you to use `locationType`
100 | as specified in `defaultLocationType` and will not inject the `cordova.js`
101 | script tag.
102 |
103 | ```sh
104 | EMBER_CLI_CORDOVA=0 ember serve
105 | ```
106 |
107 | ### Running The App On A Simulator Or Device
108 |
109 | When you need to run on a device or simulator, we have some options to automate
110 | this. By default, all features that affect the cordova build are disabled. You
111 | will need to enable the ones you want in the `config/environment.js`.
112 |
113 | #### Normal Cordova Build
114 |
115 | To run a simple cordova build with ember linked up, run
116 |
117 | ```
118 | ember cordova:build
119 | ```
120 |
121 | This will build your ember project, link everything up to cordova and run
122 | a cordova build. If you choose this route, no changes will be reflected in the
123 | running app until you run it again. To simplify, after every change you will
124 | need to run this command. Sometimes that's what you want, but we have an option
125 | to automate this.
126 |
127 | In your `config/environment` you can set `cordova.rebuildOnChange` to true. This
128 | will hook into the ember server and automate this build after every change. Then
129 | when you run the app again, you will be able to see the changes.
130 |
131 | While this is convenient at times(mainly plugin development) it's still not as
132 | quick as we want it to be. We want Livereload on the device!
133 |
134 | #### Livereload
135 |
136 | When enabled, this feature will allow you to use ember-cli's livereload when the
137 | app is running on you device or simulator. This allows you get instant feedback
138 | on a real device which allows you to get the full experience of using the app
139 | and plugins with an instant feedback loop. It is disabled in production...[for
140 | now](https://github.com/poetic/ember-cli-cordova/pull/56).
141 |
142 | Livereload is currently disabled by default and will need to be turned on in
143 | your `config/environment`. To enable it, set `cordova.liveReload.enabled` to
144 | true, and set `cordova.liveReload.platform` to the platform you will be running
145 | the app on.
146 |
147 | **A few things to be aware of**
148 |
149 | - You will need to rebuild with 'ember cordova:build' when you make changes to the
150 | environment config.
151 | - When you add/remove/update plugins or native code you will also need to run
152 | the `ember cordova:build`.
153 | - You will need to set the `emberUrl` in the config if you are running the app
154 | on a device that is not on the same computer or if your ember server is on
155 | a different port. It defaults to `http://localhost:4200`. The reason for this
156 | is that when the app starts up, it redirects to the url your ember server is
157 | running on so it must be set correctly.
158 | - Livereload is a fairly new feature in ember-cli-cordova and we are really
159 | excited about it. If you have any trouble with it please submit an issue or PR
160 | so that we can resolve it.
161 |
--------------------------------------------------------------------------------