From a31f4148af338cec13afa8805e3a15de82f42d12 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 08:30:31 -0800 Subject: [PATCH 001/850] Initial commit --- LICENSE | 20 ++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 24 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..5387be979f --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Drifty + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..00cc6c4f0b --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +ionic-cli +========= + +The Ionic Framework command line utility From f462e727f27dea9272e0bfba2146877aa52f0b40 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 10:34:52 -0600 Subject: [PATCH 002/850] Inital commit --- ionic.js | 90 ++++++++++++++++++++++++++ lib/ionic/start.js | 58 +++++++++++++++++ lib/ionic/task.js | 21 ++++++ npm-debug.log | 154 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 18 ++++++ template/index.html | 0 template/t | 0 7 files changed, 341 insertions(+) create mode 100644 ionic.js create mode 100644 lib/ionic/start.js create mode 100644 lib/ionic/task.js create mode 100644 npm-debug.log create mode 100644 package.json create mode 100644 template/index.html create mode 100644 template/t diff --git a/ionic.js b/ionic.js new file mode 100644 index 0000000000..5585912d22 --- /dev/null +++ b/ionic.js @@ -0,0 +1,90 @@ +/* + __ __ +| / \ |\ | | / ` +| \__/ | \| | \__, + +http://ionicframework.com/ + +A utility for starting and administering Ionic based mobile app projects. +Licensed under the MITlicense. See LICENSE For more. + +Copyright 2013 Drifty (http://drifty.com/) +*/ + +var IonicStartTask = require('./lib/ionic/start.js').IonicStartTask; + +var argv = require('optimist').argv; + +var TASKS = [ + { + title: 'start', + name: 'start', + usage: 'appname', + task: IonicStartTask + } +]; + +Ionic = function() {}; + +Ionic.prototype = { + _tryBuildingTask: function() { + if(argv._.length == 0) { + return false; + } + var taskName = argv._[0]; + + return this._getTaskWithName(taskName); + }, + + _getTaskWithName: function(name) { + for(var i = 0; i < TASKS.length; i++) { + var t = TASKS[i]; + if(t.name === name) { + return t; + } + } + }, + + _printGenericUsage: function() { + this._printIonic(); + process.stderr.write('Usage: ionic task args\n\n===============\n\nAvailable tasks:\n\n'); + + for(var i = 0; i < TASKS.length; i++) { + var task = TASKS[i]; + process.stderr.write(' ' + task.name + '\t\t' + task.task.HELP_LINE + '\n'); + } + + process.exit(1); + }, + + _printIonic: function() { + process.stdout.write('\n __ __ \n'); + process.stdout.write('| / \\ |\\ | | / `\n' + '| \\__/ | \\| | \\__,\n\n'); + }, + + _loadTaskRunner: function(which) { + + }, + + run: function() { + var task = this._tryBuildingTask(); + if(!task) { + return this._printGenericUsage(); + } + + console.log('Running', task.title, 'task...') + + var taskObj = new task.task(); + taskObj.run(this); + }, + + fail: function(msg) { + process.stderr.write(msg + '\n'); + process.exit(1); + }, + +}; + + +var ionic = new Ionic(); +ionic.run(); diff --git a/lib/ionic/start.js b/lib/ionic/start.js new file mode 100644 index 0000000000..e6904f76e0 --- /dev/null +++ b/lib/ionic/start.js @@ -0,0 +1,58 @@ +var fs = require('fs'), + ncp = require('ncp').ncp, + path = require('path'), + IonicTask = require('./task').IonicTask; + +var argv = require('optimist').argv; + +var IonicStartTask = function() { +} + +IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; + +IonicStartTask.prototype = new IonicTask(); + +IonicStartTask.prototype._printUsage = function() { + process.stderr.write('ionic start appname\n'); +} + +IonicStartTask.prototype.run = function(ionic) { + if(argv._.length < 2) { + ionic.fail('No app name specified'); + } + + this.appName = argv._[1]; + this.targetPath = path.resolve(this.appName); + + // Make sure to create this, or ask them if they want to override it + if(this._checkTargetPath() === false) { + process.stderr.write('Not continuing.'); + process.exit(1); + } + + console.log('Creating Ionic app in folder', this.targetPath); + + this._writeTemplateFolder(); +}; + +IonicStartTask.prototype._writeTemplateFolder = function() { + console.log('Copying template to', this.targetPath); + ncp('template', this.appName, function(err) { + if(err) { + this._fail('Unable to build starter folder', err); + } + }); +}; + +IonicStartTask.prototype._checkTargetPath = function() { + if(fs.existsSync(this.targetPath)) { + var resp = this.ask('The ' + this.targetPath + ' directory already exists. Overwrite files? (y/n)') + if(resp === 'y') { + return true; + } + return false; + } + return true; +}; + +exports.IonicStartTask = IonicStartTask; \ No newline at end of file diff --git a/lib/ionic/task.js b/lib/ionic/task.js new file mode 100644 index 0000000000..20b74b4c1f --- /dev/null +++ b/lib/ionic/task.js @@ -0,0 +1,21 @@ +var fs = require('fs'); + +var IonicTask = function() { +}; + +IonicTask.prototype = { + // Prompt the user for a response + ask: function(question) { + var response; + + process.stdout.write(question + ' '); + process.stdin.resume(); + response = fs.readSync(process.stdin.fd, 100, 0, "utf8"); + process.stdin.pause(); + return response[0].trim(); + }, + run: function(ionic) { + } +}; + +exports.IonicTask = IonicTask; \ No newline at end of file diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000000..aee84a0a4b --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,154 @@ +0 info it worked if it ends with ok +1 verbose cli [ 'node', '/usr/local/bin/npm', 'publish' ] +2 info using npm@1.2.32 +3 info using node@v0.10.12 +4 verbose publish [ '.' ] +5 verbose read json /Users/driftyadmin/git/ionic/tools/ionic/package.json +6 warn package.json ionic@0.9.05 No repository field. +7 warn package.json ionic@0.9.05 No readme data. +8 verbose cache add [ '.', null ] +9 verbose cache add name=undefined spec="." args=[".",null] +10 verbose parsed url { protocol: null, +10 verbose parsed url slashes: null, +10 verbose parsed url auth: null, +10 verbose parsed url host: null, +10 verbose parsed url port: null, +10 verbose parsed url hostname: null, +10 verbose parsed url hash: null, +10 verbose parsed url search: null, +10 verbose parsed url query: null, +10 verbose parsed url pathname: '.', +10 verbose parsed url path: '.', +10 verbose parsed url href: '.' } +11 silly lockFile 3a52ce78- . +12 verbose lock . /Users/driftyadmin/.npm/3a52ce78-.lock +13 verbose read json package.json +14 verbose tar pack [ '/var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz', +14 verbose tar pack '.' ] +15 verbose tarball /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +16 verbose folder . +17 info prepublish ionic@0.9.05 +18 silly lockFile 1f1177db-tar tar://. +19 verbose lock tar://. /Users/driftyadmin/.npm/1f1177db-tar.lock +20 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +21 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz /Users/driftyadmin/.npm/74dec091-97226-0-8251332442741841-tmp-tgz.lock +22 silly lockFile 1f1177db-tar tar://. +23 silly lockFile 1f1177db-tar tar://. +24 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +25 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +26 verbose tar unpack /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +27 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +28 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package /Users/driftyadmin/.npm/c4b8a2e3-97226-0-8251332442741841-package.lock +29 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +30 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz /Users/driftyadmin/.npm/74dec091-97226-0-8251332442741841-tmp-tgz.lock +31 silly gunzTarPerm modes [ '755', '644' ] +32 silly gunzTarPerm extractEntry package.json +33 silly gunzTarPerm extractEntry ionic.js +34 silly gunzTarPerm extractEntry lib/ionic/start.js +35 silly gunzTarPerm extractEntry lib/ionic/task.js +36 silly gunzTarPerm extractEntry template/index.html +37 silly gunzTarPerm extractEntry template/t +38 verbose read json /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package/package.json +39 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +40 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +41 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +42 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz +43 verbose from cache /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package/package.json +44 verbose tar pack [ '/Users/driftyadmin/.npm/ionic/0.9.05/package.tgz', +44 verbose tar pack '/var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package' ] +45 verbose tarball /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +46 verbose folder /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +47 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +48 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package /Users/driftyadmin/.npm/c4b8a2e3-97226-0-8251332442741841-package.lock +49 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +50 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz /Users/driftyadmin/.npm/be49939d-min-npm-ionic-0-9-05-package-tgz.lock +51 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +52 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package +53 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +54 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +55 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package +56 verbose lock /Users/driftyadmin/.npm/ionic/0.9.05/package /Users/driftyadmin/.npm/1478df52-tyadmin-npm-ionic-0-9-05-package.lock +57 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package +58 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package +59 verbose tar unpack /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +60 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package +61 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package /Users/driftyadmin/.npm/ce6e26b9-tyadmin-npm-ionic-0-9-05-package.lock +62 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +63 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz /Users/driftyadmin/.npm/be49939d-min-npm-ionic-0-9-05-package-tgz.lock +64 silly gunzTarPerm modes [ '755', '644' ] +65 silly gunzTarPerm extractEntry package.json +66 silly gunzTarPerm extractEntry ionic.js +67 silly gunzTarPerm extractEntry lib/ionic/start.js +68 silly gunzTarPerm extractEntry lib/ionic/task.js +69 silly gunzTarPerm extractEntry template/index.html +70 silly gunzTarPerm extractEntry template/t +71 verbose read json /Users/driftyadmin/.npm/ionic/0.9.05/package/package.json +72 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package +73 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package +74 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +75 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz +76 verbose from cache /Users/driftyadmin/.npm/ionic/0.9.05/package/package.json +77 verbose chmod /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz 644 +78 verbose chown /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz [ 503, 20 ] +79 silly lockFile 3a52ce78- . +80 silly lockFile 3a52ce78- . +81 silly publish { name: 'ionic', +81 silly publish version: '0.9.05', +81 silly publish preferGlobal: true, +81 silly publish description: 'A tool for creating and building Ionic Framework mobile apps.', +81 silly publish homepage: 'http://ionicframework.com/', +81 silly publish main: 'ionic.js', +81 silly publish scripts: { test: 'echo "Error: no test specified" && exit 1' }, +81 silly publish author: { name: 'Max Lynch', email: 'max@drifty.com' }, +81 silly publish license: 'MIT', +81 silly publish dependencies: { cordova: '>=3.1.0', optimist: '0.0.2', wrench: '1.5.1' }, +81 silly publish readme: 'ERROR: No README data found!', +81 silly publish _id: 'ionic@0.9.05', +81 silly publish dist: { shasum: '901fb6f02fcfb8f2944c61b575ba88f70395b720' }, +81 silly publish _from: '.' } +82 verbose url raw ionic +83 verbose url resolving [ 'https://registry.npmjs.org/', './ionic' ] +84 verbose url resolved https://registry.npmjs.org/ionic +85 info trying registry request attempt 1 at 10:29:58 +86 http PUT https://registry.npmjs.org/ionic +87 http 409 https://registry.npmjs.org/ionic +88 verbose url raw ionic +89 verbose url resolving [ 'https://registry.npmjs.org/', './ionic' ] +90 verbose url resolved https://registry.npmjs.org/ionic +91 info trying registry request attempt 1 at 10:29:58 +92 http GET https://registry.npmjs.org/ionic +93 http 200 https://registry.npmjs.org/ionic +94 verbose uploading [ 'ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db', +94 verbose uploading '/Users/driftyadmin/.npm/ionic/0.9.05/package.tgz' ] +95 verbose url raw ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +96 verbose url resolving [ 'https://registry.npmjs.org/', +96 verbose url resolving './ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db' ] +97 verbose url resolved https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +98 info trying registry request attempt 1 at 10:29:59 +99 http PUT https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +100 http 403 https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +101 info trying registry request attempt 1 at 10:29:59 +102 http PUT https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +103 http 403 https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +104 error publish Error uploading package +105 error Error: forbidden user: drifty not authorized to modify ionic +105 error Added: _attachments.ionic-0.9.05.tgz: ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db +105 error at RegClient. (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:272:14) +105 error at Request.self.callback (/usr/local/lib/node_modules/npm/node_modules/request/index.js:148:22) +105 error at Request.EventEmitter.emit (events.js:98:17) +105 error at Request. (/usr/local/lib/node_modules/npm/node_modules/request/index.js:876:14) +105 error at Request.EventEmitter.emit (events.js:117:20) +105 error at IncomingMessage. (/usr/local/lib/node_modules/npm/node_modules/request/index.js:827:12) +105 error at IncomingMessage.EventEmitter.emit (events.js:117:20) +105 error at _stream_readable.js:910:16 +105 error at process._tickCallback (node.js:415:13) +106 error If you need help, you may report this log at: +106 error +106 error or email it to: +106 error +107 error System Darwin 12.5.0 +108 error command "node" "/usr/local/bin/npm" "publish" +109 error cwd /Users/driftyadmin/git/ionic/tools/ionic +110 error node -v v0.10.12 +111 error npm -v 1.2.32 +112 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000000..23b00115a2 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "ionic", + "version": "0.9.05", + "preferGlobal": true, + "description": "A tool for creating and building Ionic Framework mobile apps.", + "homepage": "http://ionicframework.com/", + "main": "ionic.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Max Lynch ", + "license": "MIT", + "dependencies": { + "cordova": ">=3.1.0", + "optimist": "0.0.2", + "wrench": "1.5.1" + } +} diff --git a/template/index.html b/template/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/template/t b/template/t new file mode 100644 index 0000000000..e69de29bb2 From a72f43128adc296cd00fb07a6225942e59c1edcf Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 10:46:41 -0600 Subject: [PATCH 003/850] Fixed package.json --- .gitignore | 1 + lib/ionic/start.js | 2 +- npm-debug.log | 154 --------------------------------------------- package.json | 14 ++++- template/t | 0 5 files changed, 15 insertions(+), 156 deletions(-) create mode 100644 .gitignore delete mode 100644 npm-debug.log delete mode 100644 template/t diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..1ee84da988 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.sw* diff --git a/lib/ionic/start.js b/lib/ionic/start.js index e6904f76e0..9e978bdf93 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -55,4 +55,4 @@ IonicStartTask.prototype._checkTargetPath = function() { return true; }; -exports.IonicStartTask = IonicStartTask; \ No newline at end of file +exports.IonicStartTask = IonicStartTask; diff --git a/npm-debug.log b/npm-debug.log deleted file mode 100644 index aee84a0a4b..0000000000 --- a/npm-debug.log +++ /dev/null @@ -1,154 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ 'node', '/usr/local/bin/npm', 'publish' ] -2 info using npm@1.2.32 -3 info using node@v0.10.12 -4 verbose publish [ '.' ] -5 verbose read json /Users/driftyadmin/git/ionic/tools/ionic/package.json -6 warn package.json ionic@0.9.05 No repository field. -7 warn package.json ionic@0.9.05 No readme data. -8 verbose cache add [ '.', null ] -9 verbose cache add name=undefined spec="." args=[".",null] -10 verbose parsed url { protocol: null, -10 verbose parsed url slashes: null, -10 verbose parsed url auth: null, -10 verbose parsed url host: null, -10 verbose parsed url port: null, -10 verbose parsed url hostname: null, -10 verbose parsed url hash: null, -10 verbose parsed url search: null, -10 verbose parsed url query: null, -10 verbose parsed url pathname: '.', -10 verbose parsed url path: '.', -10 verbose parsed url href: '.' } -11 silly lockFile 3a52ce78- . -12 verbose lock . /Users/driftyadmin/.npm/3a52ce78-.lock -13 verbose read json package.json -14 verbose tar pack [ '/var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz', -14 verbose tar pack '.' ] -15 verbose tarball /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -16 verbose folder . -17 info prepublish ionic@0.9.05 -18 silly lockFile 1f1177db-tar tar://. -19 verbose lock tar://. /Users/driftyadmin/.npm/1f1177db-tar.lock -20 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -21 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz /Users/driftyadmin/.npm/74dec091-97226-0-8251332442741841-tmp-tgz.lock -22 silly lockFile 1f1177db-tar tar://. -23 silly lockFile 1f1177db-tar tar://. -24 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -25 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -26 verbose tar unpack /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -27 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -28 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package /Users/driftyadmin/.npm/c4b8a2e3-97226-0-8251332442741841-package.lock -29 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -30 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz /Users/driftyadmin/.npm/74dec091-97226-0-8251332442741841-tmp-tgz.lock -31 silly gunzTarPerm modes [ '755', '644' ] -32 silly gunzTarPerm extractEntry package.json -33 silly gunzTarPerm extractEntry ionic.js -34 silly gunzTarPerm extractEntry lib/ionic/start.js -35 silly gunzTarPerm extractEntry lib/ionic/task.js -36 silly gunzTarPerm extractEntry template/index.html -37 silly gunzTarPerm extractEntry template/t -38 verbose read json /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package/package.json -39 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -40 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -41 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -42 silly lockFile 74dec091-97226-0-8251332442741841-tmp-tgz tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/tmp.tgz -43 verbose from cache /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package/package.json -44 verbose tar pack [ '/Users/driftyadmin/.npm/ionic/0.9.05/package.tgz', -44 verbose tar pack '/var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package' ] -45 verbose tarball /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -46 verbose folder /var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -47 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -48 verbose lock tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package /Users/driftyadmin/.npm/c4b8a2e3-97226-0-8251332442741841-package.lock -49 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -50 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz /Users/driftyadmin/.npm/be49939d-min-npm-ionic-0-9-05-package-tgz.lock -51 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -52 silly lockFile c4b8a2e3-97226-0-8251332442741841-package tar:///var/folders/yc/wb4ct6qn5vl2r6hv8k3mck_w0000gq/T/npm-51998/1384964997226-0.8251332442741841/package -53 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -54 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -55 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package -56 verbose lock /Users/driftyadmin/.npm/ionic/0.9.05/package /Users/driftyadmin/.npm/1478df52-tyadmin-npm-ionic-0-9-05-package.lock -57 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package -58 silly lockFile 1478df52-tyadmin-npm-ionic-0-9-05-package /Users/driftyadmin/.npm/ionic/0.9.05/package -59 verbose tar unpack /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -60 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package -61 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package /Users/driftyadmin/.npm/ce6e26b9-tyadmin-npm-ionic-0-9-05-package.lock -62 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -63 verbose lock tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz /Users/driftyadmin/.npm/be49939d-min-npm-ionic-0-9-05-package-tgz.lock -64 silly gunzTarPerm modes [ '755', '644' ] -65 silly gunzTarPerm extractEntry package.json -66 silly gunzTarPerm extractEntry ionic.js -67 silly gunzTarPerm extractEntry lib/ionic/start.js -68 silly gunzTarPerm extractEntry lib/ionic/task.js -69 silly gunzTarPerm extractEntry template/index.html -70 silly gunzTarPerm extractEntry template/t -71 verbose read json /Users/driftyadmin/.npm/ionic/0.9.05/package/package.json -72 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package -73 silly lockFile ce6e26b9-tyadmin-npm-ionic-0-9-05-package tar:///Users/driftyadmin/.npm/ionic/0.9.05/package -74 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -75 silly lockFile be49939d-min-npm-ionic-0-9-05-package-tgz tar:///Users/driftyadmin/.npm/ionic/0.9.05/package.tgz -76 verbose from cache /Users/driftyadmin/.npm/ionic/0.9.05/package/package.json -77 verbose chmod /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz 644 -78 verbose chown /Users/driftyadmin/.npm/ionic/0.9.05/package.tgz [ 503, 20 ] -79 silly lockFile 3a52ce78- . -80 silly lockFile 3a52ce78- . -81 silly publish { name: 'ionic', -81 silly publish version: '0.9.05', -81 silly publish preferGlobal: true, -81 silly publish description: 'A tool for creating and building Ionic Framework mobile apps.', -81 silly publish homepage: 'http://ionicframework.com/', -81 silly publish main: 'ionic.js', -81 silly publish scripts: { test: 'echo "Error: no test specified" && exit 1' }, -81 silly publish author: { name: 'Max Lynch', email: 'max@drifty.com' }, -81 silly publish license: 'MIT', -81 silly publish dependencies: { cordova: '>=3.1.0', optimist: '0.0.2', wrench: '1.5.1' }, -81 silly publish readme: 'ERROR: No README data found!', -81 silly publish _id: 'ionic@0.9.05', -81 silly publish dist: { shasum: '901fb6f02fcfb8f2944c61b575ba88f70395b720' }, -81 silly publish _from: '.' } -82 verbose url raw ionic -83 verbose url resolving [ 'https://registry.npmjs.org/', './ionic' ] -84 verbose url resolved https://registry.npmjs.org/ionic -85 info trying registry request attempt 1 at 10:29:58 -86 http PUT https://registry.npmjs.org/ionic -87 http 409 https://registry.npmjs.org/ionic -88 verbose url raw ionic -89 verbose url resolving [ 'https://registry.npmjs.org/', './ionic' ] -90 verbose url resolved https://registry.npmjs.org/ionic -91 info trying registry request attempt 1 at 10:29:58 -92 http GET https://registry.npmjs.org/ionic -93 http 200 https://registry.npmjs.org/ionic -94 verbose uploading [ 'ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db', -94 verbose uploading '/Users/driftyadmin/.npm/ionic/0.9.05/package.tgz' ] -95 verbose url raw ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -96 verbose url resolving [ 'https://registry.npmjs.org/', -96 verbose url resolving './ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db' ] -97 verbose url resolved https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -98 info trying registry request attempt 1 at 10:29:59 -99 http PUT https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -100 http 403 https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -101 info trying registry request attempt 1 at 10:29:59 -102 http PUT https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -103 http 403 https://registry.npmjs.org/ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -104 error publish Error uploading package -105 error Error: forbidden user: drifty not authorized to modify ionic -105 error Added: _attachments.ionic-0.9.05.tgz: ionic/-/ionic-0.9.05.tgz/-rev/3-eaa605a9ad6fae3bb8c301e3127943db -105 error at RegClient. (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:272:14) -105 error at Request.self.callback (/usr/local/lib/node_modules/npm/node_modules/request/index.js:148:22) -105 error at Request.EventEmitter.emit (events.js:98:17) -105 error at Request. (/usr/local/lib/node_modules/npm/node_modules/request/index.js:876:14) -105 error at Request.EventEmitter.emit (events.js:117:20) -105 error at IncomingMessage. (/usr/local/lib/node_modules/npm/node_modules/request/index.js:827:12) -105 error at IncomingMessage.EventEmitter.emit (events.js:117:20) -105 error at _stream_readable.js:910:16 -105 error at process._tickCallback (node.js:415:13) -106 error If you need help, you may report this log at: -106 error -106 error or email it to: -106 error -107 error System Darwin 12.5.0 -108 error command "node" "/usr/local/bin/npm" "publish" -109 error cwd /Users/driftyadmin/git/ionic/tools/ionic -110 error node -v v0.10.12 -111 error npm -v 1.2.32 -112 verbose exit [ 1, true ] diff --git a/package.json b/package.json index 23b00115a2..6790582e9b 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,22 @@ { - "name": "ionic", + "name": "ionic-framework", "version": "0.9.05", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", "main": "ionic.js", + "keywords": [ + "ionic", + "ionic framework", + "mobile", + "html5", + "cordova", + "phonegap" + ], + "repository": { + "type": "git", + "url": "https://github.com/driftyco/ionic-cli.git" + }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/template/t b/template/t deleted file mode 100644 index e69de29bb2..0000000000 From fba2e19291e3132bf52426c4c3f00949ed6ace99 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 10:48:43 -0600 Subject: [PATCH 004/850] Updated optimist --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6790582e9b..2b0ea80abb 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "license": "MIT", "dependencies": { "cordova": ">=3.1.0", - "optimist": "0.0.2", + "optimist": "0.6.0", "wrench": "1.5.1" } } From cd3f536dcf0ae7208e41edc98f6e875a96377e27 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 11:21:57 -0600 Subject: [PATCH 005/850] Updated deps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2b0ea80abb..f15132d587 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "license": "MIT", "dependencies": { "cordova": ">=3.1.0", + "ncp": "0.4.2", "optimist": "0.6.0", "wrench": "1.5.1" } From ad0748bfb7e0c9c95c8bde1dc22ad9a680e16b0d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 11:28:06 -0600 Subject: [PATCH 006/850] Updated git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1ee84da988..be106cacde 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.sw* +node_modules/ From 21ff99d7b24611d9caa19926b58919d90c633f2d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 11:35:31 -0600 Subject: [PATCH 007/850] Created ionic binary: --- bin/ionic | 10 ++++++++++ ionic.js => lib/ionic.js | 8 +++----- package.json | 4 +++- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 bin/ionic rename ionic.js => lib/ionic.js (91%) diff --git a/bin/ionic b/bin/ionic new file mode 100644 index 0000000000..0454b93e1f --- /dev/null +++ b/bin/ionic @@ -0,0 +1,10 @@ +#!/usr/bin/env node + +'use strict'; + +process.title = 'ionic'; + +var Ionic = require('../lib/ionic').Ionic; + +var ionic = new Ionic(); +ionic.run(); diff --git a/ionic.js b/lib/ionic.js similarity index 91% rename from ionic.js rename to lib/ionic.js index 5585912d22..8dc4cbcb5c 100644 --- a/ionic.js +++ b/lib/ionic.js @@ -6,12 +6,12 @@ http://ionicframework.com/ A utility for starting and administering Ionic based mobile app projects. -Licensed under the MITlicense. See LICENSE For more. +Licensed under the MIT license. See LICENSE For more. Copyright 2013 Drifty (http://drifty.com/) */ -var IonicStartTask = require('./lib/ionic/start.js').IonicStartTask; +var IonicStartTask = require('./ionic/start.js').IonicStartTask; var argv = require('optimist').argv; @@ -85,6 +85,4 @@ Ionic.prototype = { }; - -var ionic = new Ionic(); -ionic.run(); +exports.Ionic = Ionic; diff --git a/package.json b/package.json index f15132d587..95cc6d189b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", - "main": "ionic.js", + "bin": { + "ionic": "bin/ionic" + }, "keywords": [ "ionic", "ionic framework", From ce657333766b733bba87ba7da08a3fb9b37f1092 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 15:05:16 -0600 Subject: [PATCH 008/850] Working start --- lib/ionic.js | 1 + lib/ionic/start.js | 73 +++++++++++++++++++++++++++++++++++++++++----- package.json | 5 +++- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 8dc4cbcb5c..2316f539df 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -54,6 +54,7 @@ Ionic.prototype = { process.stderr.write(' ' + task.name + '\t\t' + task.task.HELP_LINE + '\n'); } + process.stderr.write('\n'); process.exit(1); }, diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 9e978bdf93..ec6e01d99a 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -1,10 +1,32 @@ var fs = require('fs'), + os = require('os'), + path = require('path'), + request = require('request'), ncp = require('ncp').ncp, path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), IonicTask = require('./task').IonicTask; var argv = require('optimist').argv; +fs.mkdirParent = function(dirPath, mode, callback) { + //Call the standard fs.mkdir + console.log('MKDIR'); + fs.mkdir(dirPath, mode, function(error) { + //When it fail in this way, do the custom steps + if (error && error.errno === 34) { + //Create all the parents recursively + fs.mkdirParent(path.dirname(dirPath), mode, callback); + //And then the directory + fs.mkdirParent(dirPath, mode, callback); + } + console.log('MKDIR DONE'); + //Manually run the callback since we used our own callback to do all these + callback && callback(error); + }); +}; + var IonicStartTask = function() { } @@ -18,21 +40,61 @@ IonicStartTask.prototype._printUsage = function() { IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No app name specified'); + ionic.fail('No app name specified, exiting.'); } + // Grab the name of the app this.appName = argv._[1]; + + // Grab the target path from the command line, or use this as the app name + var targetPathName = argv._[2] || this.appName; + this.targetPath = path.resolve(this.appName); // Make sure to create this, or ask them if they want to override it if(this._checkTargetPath() === false) { - process.stderr.write('Not continuing.'); + process.stderr.write('Exiting.\n'); process.exit(1); } console.log('Creating Ionic app in folder', this.targetPath); - this._writeTemplateFolder(); + fs.mkdirSync(this.targetPath); + + //this._writeTemplateFolder(); + this._fetchAndWriteSeed(); + +}; + +IonicStartTask.prototype._fetchAndWriteSeed = function() { + var _this = this; + + var templateUrl = 'https://github.com/driftyco/ionic-angular-cordova-seed/archive/master.zip' ; + console.log('Downloading starter template from', templateUrl); + + var tmpFolder = os.tmpdir(); + var tempZipFilePath = tmpFolder + 'ionic-angular-cordova-seed' + new Date().getTime() + '.zip'; + console.log('Writing to', tempZipFilePath); + var tempZipFileStream = fs.createWriteStream(tempZipFilePath) + + var unzipRepo = function(fileName) { + var readStream = fs.createReadStream(fileName); + + var writeStream = unzip.Extract({ path: _this.targetPath }); + writeStream.on('close', function() { + console.log('END'); + //fs.renameSync(_this.targetPath + '/' + 'ionic-angular-cordova-seed-master', _this.targetPath + '/app'); + cp('-R', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', _this.targetPath); + rm('-rf', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); + }); + readStream.pipe(writeStream); + }; + + request({ url: templateUrl, encoding: null }, function(err, res, body) { + tempZipFileStream.write(body); + tempZipFileStream.close(); + unzipRepo(tempZipFilePath); + }); }; IonicStartTask.prototype._writeTemplateFolder = function() { @@ -46,10 +108,7 @@ IonicStartTask.prototype._writeTemplateFolder = function() { IonicStartTask.prototype._checkTargetPath = function() { if(fs.existsSync(this.targetPath)) { - var resp = this.ask('The ' + this.targetPath + ' directory already exists. Overwrite files? (y/n)') - if(resp === 'y') { - return true; - } + process.stderr.write('The directory ' + this.targetPath + ' already exists, please remove it if you would like to create a new ionic project there.\n'); return false; } return true; diff --git a/package.json b/package.json index 95cc6d189b..3c24a5d63d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic-framework", - "version": "0.9.05", + "version": "0.9.06", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -26,6 +26,9 @@ "license": "MIT", "dependencies": { "cordova": ">=3.1.0", + "request": "2.27.0", + "shelljs": "0.2.6", + "unzip": "0.1.9", "ncp": "0.4.2", "optimist": "0.6.0", "wrench": "1.5.1" From e236311e76dee7c5634ce11ab5c2a42dc07bb06a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 15:06:58 -0600 Subject: [PATCH 009/850] Updated debugging message --- lib/ionic/start.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index ec6e01d99a..e057cd5124 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -74,7 +74,6 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { var tmpFolder = os.tmpdir(); var tempZipFilePath = tmpFolder + 'ionic-angular-cordova-seed' + new Date().getTime() + '.zip'; - console.log('Writing to', tempZipFilePath); var tempZipFileStream = fs.createWriteStream(tempZipFilePath) var unzipRepo = function(fileName) { @@ -82,7 +81,6 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { var writeStream = unzip.Extract({ path: _this.targetPath }); writeStream.on('close', function() { - console.log('END'); //fs.renameSync(_this.targetPath + '/' + 'ionic-angular-cordova-seed-master', _this.targetPath + '/app'); cp('-R', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', _this.targetPath); rm('-rf', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); From 6afddb94b0a831296da0049765d8ff4e8d707caa Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 15:08:59 -0600 Subject: [PATCH 010/850] Note --- lib/ionic/start.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index e057cd5124..7170c1df3e 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -84,6 +84,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { //fs.renameSync(_this.targetPath + '/' + 'ionic-angular-cordova-seed-master', _this.targetPath + '/app'); cp('-R', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', _this.targetPath); rm('-rf', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); + console.log('Project created!'); }); readStream.pipe(writeStream); }; From 699dc374abbceb7bc9215e6109703ae648c5d252 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 20 Nov 2013 15:15:33 -0600 Subject: [PATCH 011/850] Better ascii --- lib/ionic.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2316f539df..1c5870f7ce 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -1,7 +1,10 @@ /* - __ __ -| / \ |\ | | / ` -| \__/ | \| | \__, + _ _ +(_) (_) + _ ___ _ __ _ ___ +| |/ _ \| '_ \| |/ __| +| | (_) | | | | | (__ +|_|\___/|_| |_|_|\___| http://ionicframework.com/ From 236a7464de93eb38b8c371b25aca3b0076f25a6f Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 21 Nov 2013 11:40:39 -0600 Subject: [PATCH 012/850] Moved ionic-framework npm to ionic, thanks @jaredhanson --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c24a5d63d..476e893bb9 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "ionic-framework", + "name": "ionic", "version": "0.9.06", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", From 3cbe371e41bd8f9e34695c98a7f7221f54daa54b Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 21 Nov 2013 11:45:05 -0600 Subject: [PATCH 013/850] Updated package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 476e893bb9..6c9d78c74a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.06", + "version": "0.9.08", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 465dea10198e4927457f3c6d130dc770b1a84f03 Mon Sep 17 00:00:00 2001 From: Matt Goodall Date: Thu, 28 Nov 2013 16:42:13 +0000 Subject: [PATCH 014/850] Build seed zip path correctly when temp dir does not end with path separator. --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 7170c1df3e..42f16ebd70 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -73,7 +73,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { console.log('Downloading starter template from', templateUrl); var tmpFolder = os.tmpdir(); - var tempZipFilePath = tmpFolder + 'ionic-angular-cordova-seed' + new Date().getTime() + '.zip'; + var tempZipFilePath = path.join(tmpFolder, 'ionic-angular-cordova-seed' + new Date().getTime() + '.zip'); var tempZipFileStream = fs.createWriteStream(tempZipFilePath) var unzipRepo = function(fileName) { From e264593c81fe0238447fa08b82661cc78b70f135 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 9 Dec 2013 09:12:15 -0600 Subject: [PATCH 015/850] Updated version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c9d78c74a..2a8b42c5ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.08", + "version": "0.9.09", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From c7861ba72326a10529d424c949a372921c1dea90 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 9 Dec 2013 09:15:29 -0600 Subject: [PATCH 016/850] Removed unnecesary path --- lib/ionic/start.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 42f16ebd70..650efb1d7b 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -1,6 +1,5 @@ var fs = require('fs'), os = require('os'), - path = require('path'), request = require('request'), ncp = require('ncp').ncp, path = require('path'), @@ -12,7 +11,6 @@ var argv = require('optimist').argv; fs.mkdirParent = function(dirPath, mode, callback) { //Call the standard fs.mkdir - console.log('MKDIR'); fs.mkdir(dirPath, mode, function(error) { //When it fail in this way, do the custom steps if (error && error.errno === 34) { @@ -21,7 +19,6 @@ fs.mkdirParent = function(dirPath, mode, callback) { //And then the directory fs.mkdirParent(dirPath, mode, callback); } - console.log('MKDIR DONE'); //Manually run the callback since we used our own callback to do all these callback && callback(error); }); From f8516bce8b539de83ab976016957bde6915c13f2 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 9 Dec 2013 09:27:01 -0600 Subject: [PATCH 017/850] Removed unused package --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 2a8b42c5ad..41e12d4066 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,5 @@ "unzip": "0.1.9", "ncp": "0.4.2", "optimist": "0.6.0", - "wrench": "1.5.1" } } From 1dc96637239f0077324203a19b4de2998f75ccaf Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 9 Dec 2013 09:27:19 -0600 Subject: [PATCH 018/850] Updated v --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41e12d4066..b3d59a251e 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,6 @@ "shelljs": "0.2.6", "unzip": "0.1.9", "ncp": "0.4.2", - "optimist": "0.6.0", + "optimist": "0.6.0" } } From d6e30540b832f1036666042e89b76cd0152c1edc Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Fri, 13 Dec 2013 10:42:35 -0600 Subject: [PATCH 019/850] Moved cordova version to 3.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3d59a251e..74e910bd49 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "author": "Max Lynch ", "license": "MIT", "dependencies": { - "cordova": ">=3.1.0", + "cordova": "~3.2.0", "request": "2.27.0", "shelljs": "0.2.6", "unzip": "0.1.9", From a33fac7ed14889415168a23a76eb2077a94dbeff Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 19 Dec 2013 14:04:59 -0600 Subject: [PATCH 020/850] Add initial build task --- bin/ionic | 0 lib/ionic.js | 7 +++++++ lib/ionic/build.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) mode change 100644 => 100755 bin/ionic create mode 100644 lib/ionic/build.js diff --git a/bin/ionic b/bin/ionic old mode 100644 new mode 100755 diff --git a/lib/ionic.js b/lib/ionic.js index 1c5870f7ce..bbac5d4dcb 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -15,6 +15,7 @@ Copyright 2013 Drifty (http://drifty.com/) */ var IonicStartTask = require('./ionic/start.js').IonicStartTask; +var IonicBuildTask = require('./ionic/build.js').IonicBuildTask; var argv = require('optimist').argv; @@ -24,6 +25,12 @@ var TASKS = [ name: 'start', usage: 'appname', task: IonicStartTask + }, + { + title: 'build', + name: 'build', + usage: 'platform', + task: IonicBuildTask } ]; diff --git a/lib/ionic/build.js b/lib/ionic/build.js new file mode 100644 index 0000000000..40e4d5a18a --- /dev/null +++ b/lib/ionic/build.js @@ -0,0 +1,32 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + ncp = require('ncp').ncp, + path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), + IonicTask = require('./task').IonicTask; + +var argv = require('optimist').argv; + +var IonicBuildTask = function() { +} + +IonicBuildTask.HELP_LINE = 'Build an Ionic project for the given plaform.'; + +IonicBuildTask.prototype = new IonicTask(); + +IonicBuildTask.prototype._printUsage = function() { + process.stderr.write('ionic build plaform (eg. android, ios)\n'); +} + +IonicBuildTask.prototype.run = function(ionic) { + if(argv._.length < 2) { + ionic.fail('No plaform specified, exiting.'); + } + + // Grab the name of the app + this.platform = argv._[1]; +}; + +exports.IonicBuildTask = IonicBuildTask; From 95a080a803e08e8b425a527be9a4c819fe20dc34 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 20 Dec 2013 17:45:26 -0600 Subject: [PATCH 021/850] I don't understand the error --- lib/ionic.js | 11 +++++++++-- lib/ionic/build.js | 10 ++-------- lib/ionic/login.js | 29 +++++++++++++++++++++++++++++ lib/ionic/start.js | 3 +-- 4 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 lib/ionic/login.js diff --git a/lib/ionic.js b/lib/ionic.js index bbac5d4dcb..492d2c3ad7 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -14,8 +14,9 @@ Licensed under the MIT license. See LICENSE For more. Copyright 2013 Drifty (http://drifty.com/) */ -var IonicStartTask = require('./ionic/start.js').IonicStartTask; -var IonicBuildTask = require('./ionic/build.js').IonicBuildTask; +var IonicStartTask = require('./ionic/start.js').IonicStartTask, + IonicLoginTask = require('./ionic/login.js').IonicLoginTask, + IonicBuildTask = require('./ionic/build.js').IonicBuildTask; var argv = require('optimist').argv; @@ -26,6 +27,12 @@ var TASKS = [ usage: 'appname', task: IonicStartTask }, + { + title: 'login', + name: 'login', + usage: '[email]', + task: IonicLoginTask + }, { title: 'build', name: 'build', diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 40e4d5a18a..7f94545266 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,14 +1,8 @@ -var fs = require('fs'), - os = require('os'), - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), +var request = require('request'), shelljs = require('shelljs/global'), - unzip = require('unzip'), + argv = require('optimist').argv, IonicTask = require('./task').IonicTask; -var argv = require('optimist').argv; - var IonicBuildTask = function() { } diff --git a/lib/ionic/login.js b/lib/ionic/login.js new file mode 100644 index 0000000000..ed60ab9192 --- /dev/null +++ b/lib/ionic/login.js @@ -0,0 +1,29 @@ +var request = require('request'), + shelljs = require('shelljs/global'), + argv = require('optimist').argv, + IonicTask = require('./task').IonicTask; + +var IonicLoginTask = function() { +} + +IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; + +IonicLoginTask.prototype = new IonicTask(); + +IonicLoginTask.prototype._printUsage = function() { + process.stderr.write('ionic login [email]\n'); +} + +IonicLoginTask.prototype.run = function(ionic) { + if(argv._.length >= 2) { + // Grab the email for login + this.email = argv._[1]; + } else { + this.email = this.ask("Email?"); + } + + this.password = this.ask("Password?", true); + +}; + +exports.IonicLoginTask = IonicLoginTask; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 650efb1d7b..73e8863db4 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -5,10 +5,9 @@ var fs = require('fs'), path = require('path'), shelljs = require('shelljs/global'), unzip = require('unzip'), + argv = require('optimist').argv, IonicTask = require('./task').IonicTask; -var argv = require('optimist').argv; - fs.mkdirParent = function(dirPath, mode, callback) { //Call the standard fs.mkdir fs.mkdir(dirPath, mode, function(error) { From 21e1a21f8c91253b07cb4281dcf4edb3f53def53 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Sat, 21 Dec 2013 00:47:56 -0600 Subject: [PATCH 022/850] Use prompt package --- lib/ionic/build.js | 4 ---- lib/ionic/login.js | 12 ++++-------- lib/ionic/start.js | 4 ---- lib/ionic/task.js | 11 +---------- package.json | 3 ++- 5 files changed, 7 insertions(+), 27 deletions(-) diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 7f94545266..593e624102 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -10,10 +10,6 @@ IonicBuildTask.HELP_LINE = 'Build an Ionic project for the given plaform.'; IonicBuildTask.prototype = new IonicTask(); -IonicBuildTask.prototype._printUsage = function() { - process.stderr.write('ionic build plaform (eg. android, ios)\n'); -} - IonicBuildTask.prototype.run = function(ionic) { if(argv._.length < 2) { ionic.fail('No plaform specified, exiting.'); diff --git a/lib/ionic/login.js b/lib/ionic/login.js index ed60ab9192..42dbb89382 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -1,7 +1,7 @@ var request = require('request'), shelljs = require('shelljs/global'), - argv = require('optimist').argv, - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + argv = require('optimist').argv; var IonicLoginTask = function() { } @@ -10,19 +10,15 @@ IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; IonicLoginTask.prototype = new IonicTask(); -IonicLoginTask.prototype._printUsage = function() { - process.stderr.write('ionic login [email]\n'); -} - IonicLoginTask.prototype.run = function(ionic) { if(argv._.length >= 2) { // Grab the email for login this.email = argv._[1]; } else { - this.email = this.ask("Email?"); + // this.email = this.ask("Email?"); } - this.password = this.ask("Password?", true); + // this.password = this.ask("Password?", true); }; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 73e8863db4..af342fee23 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -30,10 +30,6 @@ IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; IonicStartTask.prototype = new IonicTask(); -IonicStartTask.prototype._printUsage = function() { - process.stderr.write('ionic start appname\n'); -} - IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { ionic.fail('No app name specified, exiting.'); diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 20b74b4c1f..24bbcd9921 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -1,19 +1,10 @@ var fs = require('fs'); var IonicTask = function() { + HELP_LINE: '' }; IonicTask.prototype = { - // Prompt the user for a response - ask: function(question) { - var response; - - process.stdout.write(question + ' '); - process.stdin.resume(); - response = fs.readSync(process.stdin.fd, 100, 0, "utf8"); - process.stdin.pause(); - return response[0].trim(); - }, run: function(ionic) { } }; diff --git a/package.json b/package.json index 74e910bd49..8f994518ed 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "shelljs": "0.2.6", "unzip": "0.1.9", "ncp": "0.4.2", - "optimist": "0.6.0" + "optimist": "0.6.0", + "prompt": "0.2.12" } } From 1986415508ff22a3b0712b1a727e971901971ce5 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Sat, 21 Dec 2013 01:13:37 -0600 Subject: [PATCH 023/850] Initial use of prompt for login --- lib/ionic/login.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 42dbb89382..1fa97c9896 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -1,7 +1,7 @@ var request = require('request'), - shelljs = require('shelljs/global'), - IonicTask = require('./task').IonicTask, - argv = require('optimist').argv; + argv = require('optimist').argv, + prompt = require('prompt'), + IonicTask = require('./task').IonicTask; var IonicLoginTask = function() { } @@ -11,13 +11,32 @@ IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.run = function(ionic) { + var schema = [{ + name: 'password', + hidden: true, + required: true + }]; + if(argv._.length >= 2) { // Grab the email for login this.email = argv._[1]; } else { - // this.email = this.ask("Email?"); + schema.unshift({ + name: 'email', + pattern: /^\w+[@]\w+[\.]\w+$/, // Find a better email regex + message: 'Email for Ionic Studio login', + required: true + }); } + prompt.start(); + + prompt.get(schema, function (err, result) { + console.log('Command-line input received:'); + console.log(' email: ' + result.email); + console.log(' password: ' + result.password); + }); + // this.password = this.ask("Password?", true); }; From ac2b2aea5df0bc7debc8d585aa2f7624d9d8cfb5 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Sun, 22 Dec 2013 21:36:15 -0600 Subject: [PATCH 024/850] Make it cleaner! --- lib/ionic/login.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 1fa97c9896..827993b6cd 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -12,22 +12,23 @@ IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.run = function(ionic) { var schema = [{ + name: 'email', + pattern: /^\w+[@]\w+[\.]\w+$/, // Find a better email regex + message: 'Email for Ionic Studio login', + required: true + }, { name: 'password', hidden: true, required: true }]; + // Grab the email for login if(argv._.length >= 2) { - // Grab the email for login this.email = argv._[1]; - } else { - schema.unshift({ - name: 'email', - pattern: /^\w+[@]\w+[\.]\w+$/, // Find a better email regex - message: 'Email for Ionic Studio login', - required: true - }); - } + schema.shift(); + } + + // prompt.override = optimist.argv; prompt.start(); @@ -37,7 +38,6 @@ IonicLoginTask.prototype.run = function(ionic) { console.log(' password: ' + result.password); }); - // this.password = this.ask("Password?", true); }; From a3c8433d7ee2501b83a5c89602cb154eb0790d64 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Sun, 22 Dec 2013 22:04:04 -0600 Subject: [PATCH 025/850] Awesome sauce. --- lib/ionic/login.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 827993b6cd..f00bcdf441 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -11,31 +11,37 @@ IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.run = function(ionic) { + var _this = this; var schema = [{ name: 'email', - pattern: /^\w+[@]\w+[\.]\w+$/, // Find a better email regex + pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, message: 'Email for Ionic Studio login', required: true }, { - name: 'password', - hidden: true, - required: true + name: 'password', + hidden: true, + required: true }]; // Grab the email for login - if(argv._.length >= 2) { - this.email = argv._[1]; + if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { + this.email = argv._[1].toLowerCase(); schema.shift(); } - // prompt.override = optimist.argv; + prompt.override = argv; prompt.start(); prompt.get(schema, function (err, result) { + if(!_this.email) { + _this.email = result.email.toLowerCase(); + } + _this.password = result.password; + console.log('Command-line input received:'); - console.log(' email: ' + result.email); - console.log(' password: ' + result.password); + console.log(' email: ' + _this.email); + console.log(' password: ' + _this.password); }); From d8757d9c272d149e835a8f56b96b434ea3313d26 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 30 Dec 2013 15:09:28 -0600 Subject: [PATCH 026/850] Initial login request and cookie storage --- lib/ionic/login.js | 8 ++++++++ lib/ionic/task.js | 5 ++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index f00bcdf441..9c8b187281 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -42,6 +42,14 @@ IonicLoginTask.prototype.run = function(ionic) { console.log('Command-line input received:'); console.log(' email: ' + _this.email); console.log(' password: ' + _this.password); + + var jar = request.jar(); + console.log(IonicTask.IONIC_DASH); + // request({url: _this.IONIC_DASH+'login/', jar: jar}, function (error, response, body) { + // console.log(response); + // }); + + }); diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 24bbcd9921..bdd9dde8d1 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -1,10 +1,9 @@ var fs = require('fs'); -var IonicTask = function() { - HELP_LINE: '' -}; +var IonicTask = function() { }; IonicTask.prototype = { + IONIC_DASH: 'http://virt/', run: function(ionic) { } }; From 7c3e7e7f2c6fe1b223df269899a64266c39861a5 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 30 Dec 2013 16:14:31 -0600 Subject: [PATCH 027/850] Logging in with the dash! --- .gitignore | 1 + lib/ionic/login.js | 48 ++++++++++++++++++++++++++++++++++++++-------- lib/ionic/task.js | 1 + 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index be106cacde..ccc574f1f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.sw* +*.cookies node_modules/ diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 9c8b187281..21afc74584 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -1,4 +1,5 @@ -var request = require('request'), +var fs = require('fs'), + request = require('request'), argv = require('optimist').argv, prompt = require('prompt'), IonicTask = require('./task').IonicTask; @@ -34,20 +35,51 @@ IonicLoginTask.prototype.run = function(ionic) { prompt.start(); prompt.get(schema, function (err, result) { + if(err) { + console.log(err); + return; + } + if(!_this.email) { _this.email = result.email.toLowerCase(); } _this.password = result.password; - console.log('Command-line input received:'); - console.log(' email: ' + _this.email); - console.log(' password: ' + _this.password); + // console.log('Command-line input received:'); + // console.log(' email: ' + _this.email); + // console.log(' password: ' + _this.password); var jar = request.jar(); - console.log(IonicTask.IONIC_DASH); - // request({url: _this.IONIC_DASH+'login/', jar: jar}, function (error, response, body) { - // console.log(response); - // }); + console.log(_this.IONIC_DASH); + request({url: _this.IONIC_DASH+'login', jar: jar}, function (err, response, body) { + if(err || jar.cookies.length == 0) { + console.log(err); + return; + } + + request({method: 'POST', url: _this.IONIC_DASH+'login', jar: jar, form: {username: _this.email, password: _this.password, csrfmiddlewaretoken: jar.cookies[0].value}}, function (err, response, body) { + if(err) { + console.log(err); + return; + } + // Should be a 304 redirect status code if correct + if(response.statusCode == 200) { + console.log('Email or Password incorrect. Please visit '+_this.IONIC_DASH+' for help. :)') + return; + } + + fs.writeFile(_this.IONIC_COOKIES, JSON.stringify(jar, null, 2), function(err) { + if(err) { + console.log(err); + } else { + console.log('Logged in! :)'); + } + }); + // console.log(response); + + }); + + }); }); diff --git a/lib/ionic/task.js b/lib/ionic/task.js index bdd9dde8d1..804d5bf0e9 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -4,6 +4,7 @@ var IonicTask = function() { }; IonicTask.prototype = { IONIC_DASH: 'http://virt/', + IONIC_COOKIES: 'ionic.cookies', run: function(ionic) { } }; From dc4ff1d61a3431c900e9b7da9c1671f0e2af650c Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 30 Dec 2013 21:08:22 -0600 Subject: [PATCH 028/850] Login cleanup --- lib/ionic/login.js | 23 ++++++++++++++++------- lib/ionic/task.js | 2 -- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 21afc74584..de76f6dd51 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -45,19 +45,29 @@ IonicLoginTask.prototype.run = function(ionic) { } _this.password = result.password; - // console.log('Command-line input received:'); - // console.log(' email: ' + _this.email); - // console.log(' password: ' + _this.password); - var jar = request.jar(); console.log(_this.IONIC_DASH); - request({url: _this.IONIC_DASH+'login', jar: jar}, function (err, response, body) { + request({ + url: _this.IONIC_DASH+'login', + jar: jar + }, + function (err, response, body) { if(err || jar.cookies.length == 0) { console.log(err); return; } - request({method: 'POST', url: _this.IONIC_DASH+'login', jar: jar, form: {username: _this.email, password: _this.password, csrfmiddlewaretoken: jar.cookies[0].value}}, function (err, response, body) { + request({ + method: 'POST', + url: _this.IONIC_DASH+'login', + jar: jar, + form: { + username: _this.email, + password: _this.password, + csrfmiddlewaretoken: jar.cookies[0].value + } + }, + function (err, response, body) { if(err) { console.log(err); return; @@ -75,7 +85,6 @@ IonicLoginTask.prototype.run = function(ionic) { console.log('Logged in! :)'); } }); - // console.log(response); }); diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 804d5bf0e9..2335cefd14 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -1,5 +1,3 @@ -var fs = require('fs'); - var IonicTask = function() { }; IonicTask.prototype = { From 2d7dfde45131775dff8d4cbd0ff5726d7928eb30 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 30 Dec 2013 21:18:57 -0600 Subject: [PATCH 029/850] Indentation fix --- lib/ionic/login.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index de76f6dd51..b7c3153150 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -14,14 +14,14 @@ IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.run = function(ionic) { var _this = this; var schema = [{ - name: 'email', - pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, - message: 'Email for Ionic Studio login', - required: true - }, { - name: 'password', - hidden: true, - required: true + name: 'email', + pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, + message: 'Email for Ionic Studio login', + required: true + }, { + name: 'password', + hidden: true, + required: true }]; // Grab the email for login @@ -40,11 +40,11 @@ IonicLoginTask.prototype.run = function(ionic) { return; } - if(!_this.email) { - _this.email = result.email.toLowerCase(); - } - _this.password = result.password; - + if(!_this.email) { + _this.email = result.email.toLowerCase(); + } + _this.password = result.password; + var jar = request.jar(); console.log(_this.IONIC_DASH); request({ From 6611930cb4654c53a7c3c506306b01bd2d5f5c54 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 31 Dec 2013 00:36:34 -0600 Subject: [PATCH 030/850] Build task using login! --- lib/ionic.js | 3 +++ lib/ionic/build.js | 9 ++++++- lib/ionic/login.js | 65 +++++++++++++++++++++++++++++----------------- lib/ionic/start.js | 10 +++---- lib/ionic/task.js | 2 -- 5 files changed, 57 insertions(+), 32 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 492d2c3ad7..6ac0cd8e66 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -44,6 +44,9 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { + IONIC_DASH: 'http://virt/', + IONIC_COOKIES: 'ionic.cookies', + _tryBuildingTask: function() { if(argv._.length == 0) { return false; diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 593e624102..cb1915ff19 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,7 +1,8 @@ var request = require('request'), shelljs = require('shelljs/global'), argv = require('optimist').argv, - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + IonicLoginTask = require('./login.js').IonicLoginTask; var IonicBuildTask = function() { } @@ -17,6 +18,12 @@ IonicBuildTask.prototype.run = function(ionic) { // Grab the name of the app this.platform = argv._[1]; + + var login = new IonicLoginTask(); + login.get(ionic, function(jar) { + console.log(jar); + }); + }; exports.IonicBuildTask = IonicBuildTask; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index b7c3153150..a8198f8891 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -11,8 +11,8 @@ IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; IonicLoginTask.prototype = new IonicTask(); -IonicLoginTask.prototype.run = function(ionic) { - var _this = this; +IonicLoginTask.prototype.run = function(ionic, callback) { + var self = this; var schema = [{ name: 'email', pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, @@ -40,18 +40,18 @@ IonicLoginTask.prototype.run = function(ionic) { return; } - if(!_this.email) { - _this.email = result.email.toLowerCase(); + if(!self.email) { + self.email = result.email.toLowerCase(); } - _this.password = result.password; + self.password = result.password; var jar = request.jar(); - console.log(_this.IONIC_DASH); + console.log(ionic.IONIC_DASH); request({ - url: _this.IONIC_DASH+'login', + url: ionic.IONIC_DASH+'login', jar: jar }, - function (err, response, body) { + function(err, response, body) { if(err || jar.cookies.length == 0) { console.log(err); return; @@ -59,11 +59,11 @@ IonicLoginTask.prototype.run = function(ionic) { request({ method: 'POST', - url: _this.IONIC_DASH+'login', + url: ionic.IONIC_DASH+'login', jar: jar, form: { - username: _this.email, - password: _this.password, + username: self.email, + password: self.password, csrfmiddlewaretoken: jar.cookies[0].value } }, @@ -74,26 +74,43 @@ IonicLoginTask.prototype.run = function(ionic) { } // Should be a 304 redirect status code if correct if(response.statusCode == 200) { - console.log('Email or Password incorrect. Please visit '+_this.IONIC_DASH+' for help. :)') + console.log('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') return; } - fs.writeFile(_this.IONIC_COOKIES, JSON.stringify(jar, null, 2), function(err) { - if(err) { - console.log(err); - } else { - console.log('Logged in! :)'); - } - }); + var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); + if(err) { + console.log(err); + return; + } - }); + console.log('Logged in! :)'); + if(callback) { + callback(jar); + } + }); }); - - }); - - }; +IonicLoginTask.prototype.get = function(ionic, callback) { + var self = this; + + if(fs.existsSync(ionic.IONIC_COOKIES)) { + var jar = JSON.parse(fs.readFileSync(ionic.IONIC_COOKIES)); + if(jar.cookies && jar.cookies.length > 0) { + for(i in jar.cookies) { + var cookie = jar.cookies[i]; + if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { + callback(jar); + return; + } + } + } + } + + this.run(ionic, callback); +} + exports.IonicLoginTask = IonicLoginTask; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index af342fee23..5d05f13e84 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -59,7 +59,7 @@ IonicStartTask.prototype.run = function(ionic) { }; IonicStartTask.prototype._fetchAndWriteSeed = function() { - var _this = this; + var self = this; var templateUrl = 'https://github.com/driftyco/ionic-angular-cordova-seed/archive/master.zip' ; console.log('Downloading starter template from', templateUrl); @@ -71,11 +71,11 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { var unzipRepo = function(fileName) { var readStream = fs.createReadStream(fileName); - var writeStream = unzip.Extract({ path: _this.targetPath }); + var writeStream = unzip.Extract({ path: self.targetPath }); writeStream.on('close', function() { - //fs.renameSync(_this.targetPath + '/' + 'ionic-angular-cordova-seed-master', _this.targetPath + '/app'); - cp('-R', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', _this.targetPath); - rm('-rf', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); + //fs.renameSync(self.targetPath + '/' + 'ionic-angular-cordova-seed-master', self.targetPath + '/app'); + cp('-R', self.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', self.targetPath); + rm('-rf', self.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); console.log('Project created!'); }); readStream.pipe(writeStream); diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 2335cefd14..8ac8da9425 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -1,8 +1,6 @@ var IonicTask = function() { }; IonicTask.prototype = { - IONIC_DASH: 'http://virt/', - IONIC_COOKIES: 'ionic.cookies', run: function(ionic) { } }; From f21ccc6bb83935884ade9229d361a8b0c2894b6e Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 2 Jan 2014 20:48:45 -0600 Subject: [PATCH 031/850] Create a custom config file for ionic --- lib/ionic.js | 3 +++ lib/ionic/build.js | 10 ++++++++++ lib/ionic/login.js | 16 +++++----------- lib/ionic/start.js | 16 ++++++++-------- template/index.html | 0 5 files changed, 26 insertions(+), 19 deletions(-) delete mode 100644 template/index.html diff --git a/lib/ionic.js b/lib/ionic.js index 6ac0cd8e66..2462140629 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -46,6 +46,9 @@ Ionic = function() {}; Ionic.prototype = { IONIC_DASH: 'http://virt/', IONIC_COOKIES: 'ionic.cookies', + IONIC_CONFIG: 'ionic.config', + IONIC_API_VERSION: 1, + IONIC_API: 'api/v'+this.IONIC_API_VERSION+'/', _tryBuildingTask: function() { if(argv._.length == 0) { diff --git a/lib/ionic/build.js b/lib/ionic/build.js index cb1915ff19..db350a7121 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -21,6 +21,16 @@ IonicBuildTask.prototype.run = function(ionic) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { + request({ + method: 'POST', + url: ionic.IONIC_DASH+ionic.IONIC_API+'export/', + jar: jar + }, + function(err, response, body) { + if(err) { + ionic.fail(err); + } + }); console.log(jar); }); diff --git a/lib/ionic/login.js b/lib/ionic/login.js index a8198f8891..e1b3b31bc5 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -36,8 +36,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { prompt.get(schema, function (err, result) { if(err) { - console.log(err); - return; + ionic.fail(err); } if(!self.email) { @@ -46,15 +45,13 @@ IonicLoginTask.prototype.run = function(ionic, callback) { self.password = result.password; var jar = request.jar(); - console.log(ionic.IONIC_DASH); request({ url: ionic.IONIC_DASH+'login', jar: jar }, function(err, response, body) { if(err || jar.cookies.length == 0) { - console.log(err); - return; + ionic.fail(err); } request({ @@ -69,19 +66,16 @@ IonicLoginTask.prototype.run = function(ionic, callback) { }, function (err, response, body) { if(err) { - console.log(err); - return; + ionic.fail(err); } // Should be a 304 redirect status code if correct if(response.statusCode == 200) { - console.log('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') - return; + ionic.fail('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') } var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); if(err) { - console.log(err); - return; + ionic.fail(err); } console.log('Logged in! :)'); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 5d05f13e84..e017052ac8 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -53,8 +53,8 @@ IonicStartTask.prototype.run = function(ionic) { fs.mkdirSync(this.targetPath); - //this._writeTemplateFolder(); this._fetchAndWriteSeed(); + this._writeConfig(ionic); }; @@ -88,13 +88,13 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { }); }; -IonicStartTask.prototype._writeTemplateFolder = function() { - console.log('Copying template to', this.targetPath); - ncp('template', this.appName, function(err) { - if(err) { - this._fail('Unable to build starter folder', err); - } - }); +IonicStartTask.prototype._writeConfig = function(ionic) { + console.log('Writing ionic.config', this.targetPath); + var err = fs.writeFileSync(this.targetPath + '/' + ionic.IONIC_CONFIG, JSON.stringify({name: this.appName}, null, 2)); + if(err) { + process.stderr.write('Error writing ' + this.targetPath + '/' + ionic.IONIC_CONFIG + ': ' + err + '\n'); + return; + } }; IonicStartTask.prototype._checkTargetPath = function() { diff --git a/template/index.html b/template/index.html deleted file mode 100644 index e69de29bb2..0000000000 From 481ed35e92052605d534e55346d2c1ae08811a80 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 3 Jan 2014 15:32:29 -0600 Subject: [PATCH 032/850] Load ionic.config for build --- lib/ionic/build.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/ionic/build.js b/lib/ionic/build.js index db350a7121..27bb1bdb89 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,4 +1,5 @@ -var request = require('request'), +var fs = require('fs'), + request = require('request'), shelljs = require('shelljs/global'), argv = require('optimist').argv, IonicTask = require('./task').IonicTask, @@ -16,9 +17,15 @@ IonicBuildTask.prototype.run = function(ionic) { ionic.fail('No plaform specified, exiting.'); } - // Grab the name of the app + // Grab the platform build for the app this.platform = argv._[1]; + if(!fs.existsSync(ionic.IONIC_CONFIG)) { + ionic.fail('Could not find ' + ionic.IONIC_CONFIG + '!'+ + ' Please run this command your root ionic project directory with that file.'); + } + var project = JSON.parse(fs.readFileSync(ionic.IONIC_CONFIG)); + var login = new IonicLoginTask(); login.get(ionic, function(jar) { request({ From 7645df6a3bedd7cfbc0c531d83f20d0cb1576322 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 7 Jan 2014 15:02:07 -0600 Subject: [PATCH 033/850] Initial upload code --- lib/ionic.js | 29 ++++++++++++++++++++++++++--- lib/ionic/build.js | 18 ++++++------------ lib/ionic/login.js | 8 ++++---- lib/ionic/upload.js | 36 ++++++++++++++++++++++++++++++++++++ package.json | 11 ++++++----- 5 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 lib/ionic/upload.js diff --git a/lib/ionic.js b/lib/ionic.js index 2462140629..13b35f118e 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -16,9 +16,11 @@ Copyright 2013 Drifty (http://drifty.com/) var IonicStartTask = require('./ionic/start.js').IonicStartTask, IonicLoginTask = require('./ionic/login.js').IonicLoginTask, + IonicUploadTask = require('./ionic/upload.js').IonicUploadTask, IonicBuildTask = require('./ionic/build.js').IonicBuildTask; -var argv = require('optimist').argv; +var fs = require('fs'), + argv = require('optimist').argv; var TASKS = [ { @@ -33,6 +35,12 @@ var TASKS = [ usage: '[email]', task: IonicLoginTask }, + { + title: 'upload', + name: 'upload', + usage: '', + task: IonicUploadTask + }, { title: 'build', name: 'build', @@ -47,8 +55,7 @@ Ionic.prototype = { IONIC_DASH: 'http://virt/', IONIC_COOKIES: 'ionic.cookies', IONIC_CONFIG: 'ionic.config', - IONIC_API_VERSION: 1, - IONIC_API: 'api/v'+this.IONIC_API_VERSION+'/', + IONIC_API: 'api/v1/', _tryBuildingTask: function() { if(argv._.length == 0) { @@ -107,6 +114,22 @@ Ionic.prototype = { process.exit(1); }, + loadConfig: function() { + if(!fs.existsSync(this.IONIC_CONFIG)) { + this.fail('Could not find ' + this.IONIC_CONFIG + '!'+ + ' Please run this command your root ionic project directory with that file.'); + } + return JSON.parse(fs.readFileSync(this.IONIC_CONFIG)); + }, + + saveConfig: function(project) { + var err = fs.writeFileSync(this.IONIC_CONFIG, JSON.stringify(project, null, 2)); + if(err) { + process.stderr.write('Error writing ' + ionic.IONIC_CONFIG + ': ' + err + '\n'); + } + } + + }; exports.Ionic = Ionic; diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 27bb1bdb89..811d7770fc 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,6 +1,4 @@ -var fs = require('fs'), - request = require('request'), - shelljs = require('shelljs/global'), +var request = require('request'), argv = require('optimist').argv, IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login.js').IonicLoginTask; @@ -20,27 +18,23 @@ IonicBuildTask.prototype.run = function(ionic) { // Grab the platform build for the app this.platform = argv._[1]; - if(!fs.existsSync(ionic.IONIC_CONFIG)) { - ionic.fail('Could not find ' + ionic.IONIC_CONFIG + '!'+ - ' Please run this command your root ionic project directory with that file.'); - } - var project = JSON.parse(fs.readFileSync(ionic.IONIC_CONFIG)); + var project = ionic.loadConfig(); var login = new IonicLoginTask(); login.get(ionic, function(jar) { request({ method: 'POST', - url: ionic.IONIC_DASH+ionic.IONIC_API+'export/', + url: ionic.IONIC_DASH+'export/', jar: jar }, function(err, response, body) { if(err) { - ionic.fail(err); + ionic.fail("Error building: " + err); } }); console.log(jar); - }); - + console.log(project.name); + }); }; exports.IonicBuildTask = IonicBuildTask; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index e1b3b31bc5..c749e61ebe 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -36,7 +36,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { prompt.get(schema, function (err, result) { if(err) { - ionic.fail(err); + ionic.fail('Error logging in: ' + err); } if(!self.email) { @@ -51,7 +51,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { }, function(err, response, body) { if(err || jar.cookies.length == 0) { - ionic.fail(err); + ionic.fail('Error logging in: ' + err); } request({ @@ -66,7 +66,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { }, function (err, response, body) { if(err) { - ionic.fail(err); + ionic.fail('Error logging in: ' + err); } // Should be a 304 redirect status code if correct if(response.statusCode == 200) { @@ -75,7 +75,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); if(err) { - ionic.fail(err); + ionic.fail('Error writing ' + ionic.IONIC_COOKIES + ': ' + err); } console.log('Logged in! :)'); diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js new file mode 100644 index 0000000000..971db5b56c --- /dev/null +++ b/lib/ionic/upload.js @@ -0,0 +1,36 @@ +var request = require('request'), + argv = require('optimist').argv, + zip = require('adm-zip'); + IonicTask = require('./task').IonicTask, + IonicLoginTask = require('./login.js').IonicLoginTask; + +var IonicUploadTask = function() { +} + +IonicUploadTask.HELP_LINE = 'Upload an Ionic project.'; + +IonicUploadTask.prototype = new IonicTask(); + +IonicUploadTask.prototype.run = function(ionic) { + var project = ionic.loadConfig(); + + var login = new IonicLoginTask(); + login.get(ionic, function(jar) { + request({ + method: 'POST', + url: ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''), + jar: jar + }, + function(err, response, body) { + if(err) { + ionic.fail("Error uploading: " + err); + } + + + console.log(response); + }); + }); + +}; + +exports.IonicUploadTask = IonicUploadTask; diff --git a/package.json b/package.json index 8f994518ed..7b4a2f57f1 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,13 @@ "author": "Max Lynch ", "license": "MIT", "dependencies": { - "cordova": "~3.2.0", - "request": "2.27.0", - "shelljs": "0.2.6", - "unzip": "0.1.9", + "adm-zip": "0.4.3", + "cordova": "~3.2.0", "ncp": "0.4.2", "optimist": "0.6.0", - "prompt": "0.2.12" + "prompt": "0.2.12", + "request": "2.27.0", + "shelljs": "0.2.6", + "unzip": "0.1.9" } } From 1ac019c4b8ae57e57b437c72b7559669550c98e4 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 7 Jan 2014 18:28:14 -0600 Subject: [PATCH 034/850] Broken code to upload zip --- lib/ionic/start.js | 1 - lib/ionic/upload.js | 38 ++++++++++++++++++++++++++++++++------ package.json | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index e017052ac8..a9891e92d2 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -3,7 +3,6 @@ var fs = require('fs'), request = require('request'), ncp = require('ncp').ncp, path = require('path'), - shelljs = require('shelljs/global'), unzip = require('unzip'), argv = require('optimist').argv, IonicTask = require('./task').IonicTask; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 971db5b56c..1dd03d0684 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -1,6 +1,9 @@ -var request = require('request'), +var fs = require('fs'), + path = require('path'), + request = require('request'), argv = require('optimist').argv, - zip = require('adm-zip'); + FormData = require('form-data'); + Zip = require('adm-zip'); IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login.js').IonicLoginTask; @@ -16,19 +19,42 @@ IonicUploadTask.prototype.run = function(ionic) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - request({ - method: 'POST', + var zip = new Zip(); + zip.addLocalFolder('www'); + zip.writeZip('www.zip'); + + // var form = new FormData(); + + // form.getLength(function(err,length){ + // console.log(length); + var r = request.post({ + // method: 'POST', url: ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''), - jar: jar + jar: jar, + // headers: { 'content-length': length } + // form: { + // csrfmiddlewaretoken: jar.cookies[0].value, + // app_file: fs.createReadStream('www.zip') + // } }, function(err, response, body) { + // fs.unlinkSync('www.zip'); + if(err) { ionic.fail("Error uploading: " + err); } - console.log(response); }); + + var form = r.form(); + form.append('csrfmiddlewaretoken', jar.cookies[0].value); + form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip'}); + // form.append('app_file', zip.toBuffer(), {filename: 'www.zip'}); + // r._form = form; + // }); + + console.log('poop'); }); }; diff --git a/package.json b/package.json index 7b4a2f57f1..8f9319776d 100644 --- a/package.json +++ b/package.json @@ -27,11 +27,11 @@ "dependencies": { "adm-zip": "0.4.3", "cordova": "~3.2.0", + "form-data": "~0.1.0", "ncp": "0.4.2", "optimist": "0.6.0", "prompt": "0.2.12", "request": "2.27.0", - "shelljs": "0.2.6", "unzip": "0.1.9" } } From 1fbd0468dce7ab943bae844ead0ed018b7c693ac Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 13 Jan 2014 11:35:23 -0600 Subject: [PATCH 035/850] Upload zips! --- lib/ionic/upload.js | 52 ++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 1dd03d0684..e532ce7c77 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -1,9 +1,10 @@ var fs = require('fs'), path = require('path'), + parseUrl = require('url').parse, request = require('request'), argv = require('optimist').argv, - FormData = require('form-data'); - Zip = require('adm-zip'); + FormData = require('form-data'), + Zip = require('adm-zip'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login.js').IonicLoginTask; @@ -23,40 +24,33 @@ IonicUploadTask.prototype.run = function(ionic) { zip.addLocalFolder('www'); zip.writeZip('www.zip'); - // var form = new FormData(); - - // form.getLength(function(err,length){ - // console.log(length); - var r = request.post({ - // method: 'POST', - url: ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''), - jar: jar, - // headers: { 'content-length': length } - // form: { - // csrfmiddlewaretoken: jar.cookies[0].value, - // app_file: fs.createReadStream('www.zip') - // } - }, - function(err, response, body) { + var form = new FormData(); + form.append('csrfmiddlewaretoken', jar.cookies[0].value); + // form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip'}); + form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); + + var url = ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''); + var params = parseUrl(url); + + form.submit({ + host: params.host, + path: params.path, + headers: form.getHeaders({ + cookie: jar.cookies.map(function (c) { + return c.name + "=" + encodeURIComponent(c.value) + }).join("; ") + }) + }, function(err, response, body) { // fs.unlinkSync('www.zip'); + console.log(response); + // console.log(body); if(err) { + console.trace(); ionic.fail("Error uploading: " + err); } - - console.log(response); }); - - var form = r.form(); - form.append('csrfmiddlewaretoken', jar.cookies[0].value); - form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip'}); - // form.append('app_file', zip.toBuffer(), {filename: 'www.zip'}); - // r._form = form; - // }); - - console.log('poop'); }); - }; exports.IonicUploadTask = IonicUploadTask; diff --git a/package.json b/package.json index 8f9319776d..cd652b3163 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, - "author": "Max Lynch ", + "author": "Max Lynch and Peter Collins ", "license": "MIT", "dependencies": { "adm-zip": "0.4.3", From 8906a89c53a560e6f31fd5fce114352537c51bae Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 13 Jan 2014 12:20:55 -0600 Subject: [PATCH 036/850] Save app_id for project when uploaded --- lib/ionic/upload.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index e532ce7c77..d734bcfb43 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -40,15 +40,15 @@ IonicUploadTask.prototype.run = function(ionic) { return c.name + "=" + encodeURIComponent(c.value) }).join("; ") }) - }, function(err, response, body) { - // fs.unlinkSync('www.zip'); - console.log(response); - // console.log(body); - + }, function(err, response) { if(err) { - console.trace(); ionic.fail("Error uploading: " + err); } + if(response.statusCode == 302) { + var redirectPath = parseUrl(response.headers.location); + project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; + ionic.saveConfig(project); + } }); }); }; From a7c6684bdb9e2daafeee20c5b2bcf59372eeec49 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 13 Jan 2014 14:08:50 -0600 Subject: [PATCH 037/850] Don't write zip file --- lib/ionic/upload.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index d734bcfb43..ccc5750702 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -22,7 +22,6 @@ IonicUploadTask.prototype.run = function(ionic) { login.get(ionic, function(jar) { var zip = new Zip(); zip.addLocalFolder('www'); - zip.writeZip('www.zip'); var form = new FormData(); form.append('csrfmiddlewaretoken', jar.cookies[0].value); From c8aedac953ce975366d44fb29259e59a40e68656 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 13 Jan 2014 19:10:55 -0600 Subject: [PATCH 038/850] Added initial plugin install, and build and run --- lib/ionic.js | 23 ++++++++++++++++++++- lib/ionic/build.js | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/ionic/platform.js | 47 +++++++++++++++++++++++++++++++++++++++++++ lib/ionic/run.js | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/ionic/start.js | 11 ++++++++++ package.json | 2 +- 6 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 lib/ionic/build.js create mode 100644 lib/ionic/platform.js create mode 100644 lib/ionic/run.js diff --git a/lib/ionic.js b/lib/ionic.js index 1c5870f7ce..9d1186486a 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -15,6 +15,9 @@ Copyright 2013 Drifty (http://drifty.com/) */ var IonicStartTask = require('./ionic/start.js').IonicStartTask; +var IonicPlatformTask = require('./ionic/platform.js').IonicPlatformTask; +var IonicRunTask = require('./ionic/run.js').IonicRunTask; +var IonicBuildTask = require('./ionic/build.js').IonicBuildTask; var argv = require('optimist').argv; @@ -24,6 +27,24 @@ var TASKS = [ name: 'start', usage: 'appname', task: IonicStartTask + }, + { + title: 'run', + name: 'run', + usage: 'run', + task: IonicRunTask + }, + { + title: 'build', + name: 'build', + usage: 'build', + task: IonicBuildTask + }, + { + title: 'platform', + name: 'platform', + usage: 'platform', + task: IonicPlatformTask } ]; @@ -54,7 +75,7 @@ Ionic.prototype = { for(var i = 0; i < TASKS.length; i++) { var task = TASKS[i]; - process.stderr.write(' ' + task.name + '\t\t' + task.task.HELP_LINE + '\n'); + process.stderr.write(' ' + task.name + ' - ' + task.task.HELP_LINE + '\n'); } process.stderr.write('\n'); diff --git a/lib/ionic/build.js b/lib/ionic/build.js new file mode 100644 index 0000000000..486ffc909a --- /dev/null +++ b/lib/ionic/build.js @@ -0,0 +1,46 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + ncp = require('ncp').ncp, + path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), + IonicTask = require('./task').IonicTask; + +var argv = require('optimist').argv; + +var IonicBuildTask = function() { +} + +IonicBuildTask.HELP_LINE = 'Locally build an ionic project for a given platform'; + +IonicBuildTask.prototype = new IonicTask(); + +IonicBuildTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic build [platform]\n'); +} + +IonicBuildTask.prototype.run = function(ionic) { + var patform; + + if(argv._.length < 2) { + IonicBuildTask.prototype._printUsage(); + ionic.fail('No platforms specified, exiting.'); + } + + var platforms = argv._.slice(1); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } + + for(var i = 0; i < platforms.length; i++) { + platform = platforms[i]; + console.log('Building platform', platform); + if(exec("cordova build " + platform).code !== 0) { + ionic.fail('Unable to build app on platform ' + platform + '. Please see console for more info.'); + } + } +}; + +exports.IonicBuildTask = IonicBuildTask; diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js new file mode 100644 index 0000000000..9993cb3ac1 --- /dev/null +++ b/lib/ionic/platform.js @@ -0,0 +1,47 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + ncp = require('ncp').ncp, + path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), + IonicTask = require('./task').IonicTask; + +var argv = require('optimist').argv; + +var IonicPlatformTask = function() { +} + +IonicPlatformTask.HELP_LINE = 'Configure platform targets for building an Ionic app'; + +IonicPlatformTask.prototype = new IonicTask(); + +IonicPlatformTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic platforms [platform1, platform2]\nSupported platforms currently "ios" and "android"\n\n'); +} + +IonicPlatformTask.prototype.run = function(ionic) { + var patform; + + if(argv._.length < 2) { + IonicPlatformTask.prototype._printUsage(); + ionic.fail('No platforms specified, exiting.'); + } + + // Grab the name of the app + var platforms = argv._.slice(1); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } + + for(var i = 0; i < platforms.length; i++) { + platform = platforms[i]; + console.log('Adding platform', platform); + if(exec("cordova platform add " + platform).code !== 0) { + process.stderr.write('Unable to add platform ' + platform + '. Please see console for more info.\n'); + } + } +}; + +exports.IonicPlatformTask = IonicPlatformTask; diff --git a/lib/ionic/run.js b/lib/ionic/run.js new file mode 100644 index 0000000000..6010728608 --- /dev/null +++ b/lib/ionic/run.js @@ -0,0 +1,46 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + ncp = require('ncp').ncp, + path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), + IonicTask = require('./task').IonicTask; + +var argv = require('optimist').argv; + +var IonicRunTask = function() { +} + +IonicRunTask.HELP_LINE = 'Run an ionic project on a connected device.'; + +IonicRunTask.prototype = new IonicTask(); + +IonicRunTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic run [platform]\n'); +} + +IonicRunTask.prototype.run = function(ionic) { + var patform; + + if(argv._.length < 2) { + IonicRunTask.prototype._printUsage(); + ionic.fail('No platforms specified, exiting.'); + } + + var platforms = argv._.slice(1); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } + + for(var i = 0; i < platforms.length; i++) { + platform = platforms[i]; + console.log('Running app on platform', platform); + if(exec("cordova run " + platform).code !== 0) { + ionic.fail('Unable to run app on platform ' + platform + '. Please see console for more info.'); + } + } +}; + +exports.IonicRunTask = IonicRunTask; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 650efb1d7b..9079838880 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -82,6 +82,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { cp('-R', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', _this.targetPath); rm('-rf', _this.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); console.log('Project created!'); + + _this._finish(); }); readStream.pipe(writeStream); }; @@ -93,6 +95,15 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { }); }; +IonicStartTask.prototype._finish = function() { + cd(this.targetPath); + console.log('Initializing cordova project.'); + if(!exec('cordova plugin add org.apache.cordova.device') || !exec('cordova plugin add org.apache.cordova.console') || + !exec('cordova plugin add org.apache.cordova.statusbar')) { + process.stderr.write('Unable to install one or more cordova plugins.\n'); + } +}; + IonicStartTask.prototype._writeTemplateFolder = function() { console.log('Copying template to', this.targetPath); ncp('template', this.appName, function(err) { diff --git a/package.json b/package.json index 74e910bd49..4cada292c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.09", + "version": "0.9.10", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From bbbba6eb8b9cc4d842f24d2edf6a917a2be42ab5 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 14 Jan 2014 14:25:50 -0600 Subject: [PATCH 039/850] Move build to package and added alt names for commands --- lib/ionic.js | 16 +++++++++++++--- lib/ionic/{build.js => package.js} | 10 +++++----- 2 files changed, 18 insertions(+), 8 deletions(-) rename lib/ionic/{build.js => package.js} (70%) diff --git a/lib/ionic.js b/lib/ionic.js index 13b35f118e..6e3498c172 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -38,14 +38,16 @@ var TASKS = [ { title: 'upload', name: 'upload', + alt: ['up'], usage: '', task: IonicUploadTask }, { - title: 'build', - name: 'build', + title: 'package', + name: 'package', + alt: ['pack'], usage: 'platform', - task: IonicBuildTask + task: IonicPackageTask } ]; @@ -72,6 +74,14 @@ Ionic.prototype = { if(t.name === name) { return t; } + if(t.alt) { + for(var j = 0; j < t.alt.length; j++) { + var alt = t.alt[j]; + if(alt === name) { + return t; + } + } + } } }, diff --git a/lib/ionic/build.js b/lib/ionic/package.js similarity index 70% rename from lib/ionic/build.js rename to lib/ionic/package.js index 811d7770fc..fd93cb1b28 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/package.js @@ -3,14 +3,14 @@ var request = require('request'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login.js').IonicLoginTask; -var IonicBuildTask = function() { +var IonicPackageTask = function() { } -IonicBuildTask.HELP_LINE = 'Build an Ionic project for the given plaform.'; +IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; -IonicBuildTask.prototype = new IonicTask(); +IonicPackageTask.prototype = new IonicTask(); -IonicBuildTask.prototype.run = function(ionic) { +IonicPackageTask.prototype.run = function(ionic) { if(argv._.length < 2) { ionic.fail('No plaform specified, exiting.'); } @@ -37,4 +37,4 @@ IonicBuildTask.prototype.run = function(ionic) { }); }; -exports.IonicBuildTask = IonicBuildTask; +exports.IonicPackageTask = IonicPackageTask; From 025bd8bdc196a6ef796460d3f4367e3757713394 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 14 Jan 2014 14:57:04 -0600 Subject: [PATCH 040/850] Fix formatting and make more consistent code --- lib/ionic/build.js | 16 +++------------- lib/ionic/package.js | 38 +++++++++++++++++++++++--------------- lib/ionic/platform.js | 16 +++------------- lib/ionic/run.js | 16 +++------------- 4 files changed, 32 insertions(+), 54 deletions(-) diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 486ffc909a..eb948aff7d 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,14 +1,6 @@ -var fs = require('fs'), - os = require('os'), - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), +var argv = require('optimist').argv, IonicTask = require('./task').IonicTask; -var argv = require('optimist').argv; - var IonicBuildTask = function() { } @@ -17,12 +9,10 @@ IonicBuildTask.HELP_LINE = 'Locally build an ionic project for a given platform' IonicBuildTask.prototype = new IonicTask(); IonicBuildTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic build [platform]\n'); + process.stderr.write('\nUsage: ionic build platform [more platforms,...]\n'); } IonicBuildTask.prototype.run = function(ionic) { - var patform; - if(argv._.length < 2) { IonicBuildTask.prototype._printUsage(); ionic.fail('No platforms specified, exiting.'); @@ -35,7 +25,7 @@ IonicBuildTask.prototype.run = function(ionic) { } for(var i = 0; i < platforms.length; i++) { - platform = platforms[i]; + var platform = platforms[i]; console.log('Building platform', platform); if(exec("cordova build " + platform).code !== 0) { ionic.fail('Unable to build app on platform ' + platform + '. Please see console for more info.'); diff --git a/lib/ionic/package.js b/lib/ionic/package.js index fd93cb1b28..26b46adec7 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -10,30 +10,38 @@ IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; IonicPackageTask.prototype = new IonicTask(); +IonicPackageTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic package platform [more platforms,...]\n'); +} + IonicPackageTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No plaform specified, exiting.'); + IonicPackageTask.prototype._printUsage(); + ionic.fail('No platforms specified, exiting.'); } - // Grab the platform build for the app - this.platform = argv._[1]; + var platforms = argv._.slice(1); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } var project = ionic.loadConfig(); var login = new IonicLoginTask(); login.get(ionic, function(jar) { - request({ - method: 'POST', - url: ionic.IONIC_DASH+'export/', - jar: jar - }, - function(err, response, body) { - if(err) { - ionic.fail("Error building: " + err); - } - }); - console.log(jar); - console.log(project.name); + for(var i = 0; i < platforms.length; i++) { + request({ + method: 'POST', + url: ionic.IONIC_DASH+'export/', + jar: jar + }, + function(err, response, body) { + if(err) { + ionic.fail("Error building: " + err); + } + }); + } }); }; diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js index 9993cb3ac1..68eb4c5042 100644 --- a/lib/ionic/platform.js +++ b/lib/ionic/platform.js @@ -1,14 +1,6 @@ -var fs = require('fs'), - os = require('os'), - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), +var argv = require('optimist').argv, IonicTask = require('./task').IonicTask; -var argv = require('optimist').argv; - var IonicPlatformTask = function() { } @@ -17,12 +9,10 @@ IonicPlatformTask.HELP_LINE = 'Configure platform targets for building an Ionic IonicPlatformTask.prototype = new IonicTask(); IonicPlatformTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic platforms [platform1, platform2]\nSupported platforms currently "ios" and "android"\n\n'); + process.stderr.write('\nUsage: ionic platform [more platforms,...]\nSupported platforms currently "ios" and "android"\n\n'); } IonicPlatformTask.prototype.run = function(ionic) { - var patform; - if(argv._.length < 2) { IonicPlatformTask.prototype._printUsage(); ionic.fail('No platforms specified, exiting.'); @@ -36,7 +26,7 @@ IonicPlatformTask.prototype.run = function(ionic) { } for(var i = 0; i < platforms.length; i++) { - platform = platforms[i]; + var platform = platforms[i]; console.log('Adding platform', platform); if(exec("cordova platform add " + platform).code !== 0) { process.stderr.write('Unable to add platform ' + platform + '. Please see console for more info.\n'); diff --git a/lib/ionic/run.js b/lib/ionic/run.js index 6010728608..995c801b46 100644 --- a/lib/ionic/run.js +++ b/lib/ionic/run.js @@ -1,14 +1,6 @@ -var fs = require('fs'), - os = require('os'), - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), +var argv = require('optimist').argv, IonicTask = require('./task').IonicTask; -var argv = require('optimist').argv; - var IonicRunTask = function() { } @@ -17,12 +9,10 @@ IonicRunTask.HELP_LINE = 'Run an ionic project on a connected device.'; IonicRunTask.prototype = new IonicTask(); IonicRunTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic run [platform]\n'); + process.stderr.write('\nUsage: ionic run platform [more platforms,...]\n'); } IonicRunTask.prototype.run = function(ionic) { - var patform; - if(argv._.length < 2) { IonicRunTask.prototype._printUsage(); ionic.fail('No platforms specified, exiting.'); @@ -35,7 +25,7 @@ IonicRunTask.prototype.run = function(ionic) { } for(var i = 0; i < platforms.length; i++) { - platform = platforms[i]; + var platform = platforms[i]; console.log('Running app on platform', platform); if(exec("cordova run " + platform).code !== 0) { ionic.fail('Unable to run app on platform ' + platform + '. Please see console for more info.'); From 746055bc6f5984f9c9cdc1fe391ec15c04e9209e Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 15 Jan 2014 14:21:57 -0600 Subject: [PATCH 041/850] Getting ready to export --- lib/ionic.js | 29 +++++++++++++------ lib/ionic/login.js | 12 ++++++++ lib/ionic/package.js | 68 ++++++++++++++++++++++++++++++-------------- lib/ionic/upload.js | 8 ++++-- 4 files changed, 86 insertions(+), 31 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index ca4bd69086..de4e1caecf 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -14,13 +14,13 @@ Licensed under the MIT license. See LICENSE For more. Copyright 2013 Drifty (http://drifty.com/) */ -var IonicStartTask = require('./ionic/start.js').IonicStartTask, - IonicPlatformTask = require('./ionic/platform.js').IonicPlatformTask; - IonicRunTask = require('./ionic/run.js').IonicRunTask; - IonicBuildTask = require('./ionic/build.js').IonicBuildTask; - IonicLoginTask = require('./ionic/login.js').IonicLoginTask, - IonicUploadTask = require('./ionic/upload.js').IonicUploadTask, - IonicPackageTask = require('./ionic/package.js').IonicPackageTask; +var IonicStartTask = require('./ionic/start').IonicStartTask, + IonicPlatformTask = require('./ionic/platform').IonicPlatformTask, + IonicRunTask = require('./ionic/run').IonicRunTask, + IonicBuildTask = require('./ionic/build').IonicBuildTask, + IonicLoginTask = require('./ionic/login').IonicLoginTask, + IonicUploadTask = require('./ionic/upload').IonicUploadTask, + IonicPackageTask = require('./ionic/package').IonicPackageTask; var fs = require('fs'), argv = require('optimist').argv; @@ -67,7 +67,7 @@ var TASKS = [ title: 'package', name: 'package', alt: ['pack'], - usage: 'platform', + usage: 'mode platform', task: IonicPackageTask } ]; @@ -79,6 +79,19 @@ Ionic.prototype = { IONIC_COOKIES: 'ionic.cookies', IONIC_CONFIG: 'ionic.config', IONIC_API: 'api/v1/', + CONFIG_DEFAULT: { + name: '', + email: '', + app_id: '', + package_name: '', + ios_certificate: '', + ios_certificate_password: '', + ios_profile: '', + android_keystore: '', + android_keystore_alias: '', + android_keystore_password: '', + android_key_password: '' + }, _tryBuildingTask: function() { if(argv._.length == 0) { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index c749e61ebe..cb40e3077d 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -24,11 +24,18 @@ IonicLoginTask.prototype.run = function(ionic, callback) { required: true }]; + var project = ionic.loadConfig(); + // Grab the email for login if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { this.email = argv._[1].toLowerCase(); schema.shift(); } + // Assume project email is login email if it exists + else if(project.email && project.email != '') { + this.email = project.email; + schema.shift(); + } prompt.override = argv; @@ -43,6 +50,11 @@ IonicLoginTask.prototype.run = function(ionic, callback) { self.email = result.email.toLowerCase(); } self.password = result.password; + + if(!project.email || project.email == '') { + project.email = self.email; + ionic.saveConfig(project); + } var jar = request.jar(); request({ diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 26b46adec7..1e021438a4 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -1,7 +1,9 @@ var request = require('request'), argv = require('optimist').argv, + prompt = require('prompt'), IonicTask = require('./task').IonicTask, - IonicLoginTask = require('./login.js').IonicLoginTask; + IonicUploadTask = require('./upload').IonicUploadTask; + IonicLoginTask = require('./login').IonicLoginTask; var IonicPackageTask = function() { } @@ -11,38 +13,62 @@ IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; IonicPackageTask.prototype = new IonicTask(); IonicPackageTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic package platform [more platforms,...]\n'); + process.stderr.write('\nUsage: ionic package mode(debug|release) platform [more platforms,...]\n'); } IonicPackageTask.prototype.run = function(ionic) { - if(argv._.length < 2) { + if(argv._.length < 3) { IonicPackageTask.prototype._printUsage(); - ionic.fail('No platforms specified, exiting.'); + ionic.fail('No platforms or build mode specified, exiting.'); } - var platforms = argv._.slice(1); + var mode = argv._[1].toLowerCase(); + if(mode != 'debug' && mode != 'release') { + IonicPackageTask.prototype._printUsage(); + ionic.fail('Package build mode must be debug or release, exiting.'); + } + + var platforms = argv._.slice(2); if(platforms.length < 1) { ionic.fail('No platforms specified, exiting.'); } - var project = ionic.loadConfig(); - - var login = new IonicLoginTask(); - login.get(ionic, function(jar) { - for(var i = 0; i < platforms.length; i++) { - request({ - method: 'POST', - url: ionic.IONIC_DASH+'export/', - jar: jar - }, - function(err, response, body) { - if(err) { - ionic.fail("Error building: " + err); + var upload = new IonicUploadTask(); + upload.run(ionic, function() { + + var login = new IonicLoginTask(); + login.get(ionic, function(jar) { + + var project = ionic.loadConfig(); + + for(var i = 0; i < platforms.length; i++) { + var platform = platforms[i]; + + switch (platform) { + case 'android': + break; + case 'ios': + break; + default: + process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently "ios" and "android"\n\n'); + continue; } - }); - } - }); + + request({ + method: 'POST', + url: ionic.IONIC_DASH+'export/', + jar: jar + }, + function(err, response, body) { + if(err) { + ionic.fail("Error packaging: " + err); + } + }); + } + + }); + }); }; exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index ccc5750702..457cceb099 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -6,7 +6,7 @@ var fs = require('fs'), FormData = require('form-data'), Zip = require('adm-zip'), IonicTask = require('./task').IonicTask, - IonicLoginTask = require('./login.js').IonicLoginTask; + IonicLoginTask = require('./login').IonicLoginTask; var IonicUploadTask = function() { } @@ -15,7 +15,7 @@ IonicUploadTask.HELP_LINE = 'Upload an Ionic project.'; IonicUploadTask.prototype = new IonicTask(); -IonicUploadTask.prototype.run = function(ionic) { +IonicUploadTask.prototype.run = function(ionic, callback) { var project = ionic.loadConfig(); var login = new IonicLoginTask(); @@ -47,6 +47,10 @@ IonicUploadTask.prototype.run = function(ionic) { var redirectPath = parseUrl(response.headers.location); project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; ionic.saveConfig(project); + + if (callback) { + callback(); + }; } }); }); From 3ea1d14780d02df0f77de00cbfd4c71a4f3581d7 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 15 Jan 2014 15:59:57 -0600 Subject: [PATCH 042/850] Use default config for template --- lib/ionic.js | 6 +++--- lib/ionic/package.js | 28 +++++++++++++++++++--------- lib/ionic/start.js | 12 ++++++------ 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index de4e1caecf..da3269216d 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -166,10 +166,10 @@ Ionic.prototype = { return JSON.parse(fs.readFileSync(this.IONIC_CONFIG)); }, - saveConfig: function(project) { - var err = fs.writeFileSync(this.IONIC_CONFIG, JSON.stringify(project, null, 2)); + saveConfig: function(project, targetPath) { + var err = fs.writeFileSync((targetPath?targetPath+'/':'')+this.IONIC_CONFIG, JSON.stringify(project, null, 2)); if(err) { - process.stderr.write('Error writing ' + ionic.IONIC_CONFIG + ': ' + err + '\n'); + process.stderr.write('Error writing ' + (targetPath?targetPath+'/':'')+ ionic.IONIC_CONFIG + ': ' + err + '\n'); } } diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 1e021438a4..8555502843 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -2,7 +2,7 @@ var request = require('request'), argv = require('optimist').argv, prompt = require('prompt'), IonicTask = require('./task').IonicTask, - IonicUploadTask = require('./upload').IonicUploadTask; + IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; var IonicPackageTask = function() { @@ -45,8 +45,12 @@ IonicPackageTask.prototype.run = function(ionic) { for(var i = 0; i < platforms.length; i++) { var platform = platforms[i]; + prompt.override = argv; + prompt.start(); + var schema; + switch (platform) { - case 'android': + case 'android': break; case 'ios': break; @@ -55,15 +59,21 @@ IonicPackageTask.prototype.run = function(ionic) { continue; } - request({ - method: 'POST', - url: ionic.IONIC_DASH+'export/', - jar: jar - }, - function(err, response, body) { + prompt.get(schema, function (err, result) { if(err) { - ionic.fail("Error packaging: " + err); + ionic.fail('Error packaging: ' + err); } + + request({ + method: 'POST', + url: ionic.IONIC_DASH+'export/', + jar: jar + }, + function(err, response, body) { + if(err) { + ionic.fail("Error packaging: " + err); + } + }); }); } diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 5eb8133f7e..516a3a8505 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -95,12 +95,12 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { }; IonicStartTask.prototype._writeConfig = function(ionic) { - console.log('Writing ionic.config', this.targetPath); - var err = fs.writeFileSync(this.targetPath + '/' + ionic.IONIC_CONFIG, JSON.stringify({name: this.appName}, null, 2)); - if(err) { - process.stderr.write('Error writing ' + this.targetPath + '/' + ionic.IONIC_CONFIG + ': ' + err + '\n'); - return; - } + console.log('Writing '+this.targetPath+'/ionic.config'); + + var project = ionic.CONFIG_DEFAULT; + project.name = this.appName; + + ionic.saveConfig(project, this.targetPath); }; IonicStartTask.prototype._checkTargetPath = function() { From 013d6f5f7623e6b8bd226491a31d73b297f562a8 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 15 Jan 2014 19:06:30 -0600 Subject: [PATCH 043/850] Add package properties --- lib/ionic.js | 5 ++++ lib/ionic/package.js | 70 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index da3269216d..9bc2852ffa 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -167,6 +167,11 @@ Ionic.prototype = { }, saveConfig: function(project, targetPath) { + if(!project) { + console.trace(); + this.fail('This should never happen!'); + } + var err = fs.writeFileSync((targetPath?targetPath+'/':'')+this.IONIC_CONFIG, JSON.stringify(project, null, 2)); if(err) { process.stderr.write('Error writing ' + (targetPath?targetPath+'/':'')+ ionic.IONIC_CONFIG + ': ' + err + '\n'); diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 8555502843..113ebea833 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -47,26 +47,88 @@ IonicPackageTask.prototype.run = function(ionic) { prompt.override = argv; prompt.start(); - var schema; + var properties = {}; switch (platform) { - case 'android': + case 'android': + if(mode == 'release') { + properties = { + android_keystore: { + description: 'Android Keystore File (.keystore)', + message: 'Relative path to your release keystore file (eg. release.keystore)', + required: true + }, + android_keystore_alias: { + description: 'Keystore Alias', + message: 'Alias of the Keystore', + required: true + }, + android_keystore_password: { + description: 'Keystore Password', + message: 'Password of the Keystore', + hidden: true, + required: true + }, + android_key_password: { + description: 'Key Password', + message: 'Password for Key (usually same as Keystore Password and if left blank will use it)', + hidden: true, + } + }; + } + break; case 'ios': + properties = { + ios_certificate: { + description: 'iOS Certificate File (.p12)', + message: 'Relative path to your certificate file (eg. cert.p12)', + required: true + }, + ios_certificate_password: { + description: 'Certificate Password', + message: 'Password of the Certificate', + hidden: true, + required: true + }, + ios_profile: { + description: 'iOS Mobile Provisioning Profile (.mobileprofile)', + message: 'Relative path to your Mobile Provisioning Profile (eg. my.mobileprofile)', + required: true + }, + }; break; default: process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently "ios" and "android"\n\n'); continue; } - prompt.get(schema, function (err, result) { + properties.package_name = { + description: 'Package Name (eg. com.mycompany.app)', + message: 'Package Name (eg. com.mycompany.app) not required', + }; + + for (var property in properties) { + if(project[property] && project[project] == '') { + delete properties[property]; + } + } + + prompt.get({properties: properties}, function (err, result) { if(err) { ionic.fail('Error packaging: ' + err); } + + for (var property in properties) { + if(project[property] && project[project] == '') { + project[property] = result[property]; + } + } + ionic.saveConfig(project); request({ method: 'POST', - url: ionic.IONIC_DASH+'export/', + url: ionic.IONIC_DASH+'export/'+project.app_id, jar: jar }, function(err, response, body) { From 23602bd42ee8d4f504700dbc6a1f4c64cd036533 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 16 Jan 2014 14:39:58 -0600 Subject: [PATCH 044/850] Finish package command --- lib/ionic/package.js | 82 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 113ebea833..df39bcd421 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -49,8 +49,10 @@ IonicPackageTask.prototype.run = function(ionic) { prompt.start(); var properties = {}; + // Just prompt for some build properties switch (platform) { case 'android': + // Android debug doesn't require anything if(mode == 'release') { properties = { android_keystore: { @@ -99,15 +101,17 @@ IonicPackageTask.prototype.run = function(ionic) { }; break; default: - process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently "ios" and "android"\n\n'); + process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently are "ios" and "android"\n\n'); continue; } + // Should we just not add this since it's optional? properties.package_name = { - description: 'Package Name (eg. com.mycompany.app)', - message: 'Package Name (eg. com.mycompany.app) not required', + description: 'Package Name (eg. com.mycompany.app) optional', + message: 'Package Name (eg. com.mycompany.app) optional', }; + // Don't prompt for properties we already have in the config for (var property in properties) { if(project[property] && project[project] == '') { delete properties[property]; @@ -119,19 +123,79 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail('Error packaging: ' + err); } + // Overwrite any empty properties with prompt responses for (var property in properties) { if(project[property] && project[project] == '') { project[property] = result[property]; } } ionic.saveConfig(project); + + var form = new FormData(); + form.append('platform', platform); + form.append('build_mode', mode); + form.append('csrfmiddlewaretoken', jar.cookies[0].value); + + // Add the project properties to the post + for (var property in project) { + if(property.indexOf(platform)) { + form.append(property, project[project]); + } + } - request({ - method: 'POST', - url: ionic.IONIC_DASH+'export/'+project.app_id, - jar: jar - }, - function(err, response, body) { + // Gimmie those sweet sweet files + switch(platform) { + case 'android': + var keystoreFilePath = path.resolve(project.android_keystore); + if(mode = 'release') { + if(fs.existsSync(keystoreFilePath)) { + form.append('android_keystore_file', fs.createReadStream(keystoreFilePath)); + } else { + delete project.android_keystore; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); + return; + } + } + break; + case 'ios': + var certificateFilePath = path.resolve(project.ios_certificate); + if(fs.existsSync(certificateFilePath)) { + form.append('ios_certificate_file', fs.createReadStream(certificateFilePath)); + } else { + delete project.ios_certificate; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); + return; + } + var profileFilePath = path.resolve(project.ios_profile); + if(fs.existsSync(profileFilePath)) { + form.append('ios_profile_file', fs.createReadStream(profileFilePath)); + } else { + delete project.ios_profile; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); + return; + } + break; + default: + console.trace(); + process.stderr.write('\nUnknown platform: "'+platform+'"\nWe should never get here"\n\n'); + break; + } + + var url = ionic.IONIC_DASH+'export/'+project.app_id; + var params = parseUrl(url); + + form.submit({ + host: params.host, + path: params.path, + headers: form.getHeaders({ + cookie: jar.cookies.map(function (c) { + return c.name + "=" + encodeURIComponent(c.value) + }).join("; ") + }) + }, function(err, response) { if(err) { ionic.fail("Error packaging: " + err); } From 132e7a47eba46fc19c1bb14d401494c429074e9d Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 16 Jan 2014 15:57:47 -0600 Subject: [PATCH 045/850] Small fixes --- lib/ionic/package.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index df39bcd421..825c1c9297 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -1,6 +1,9 @@ -var request = require('request'), +var fs = require('fs'), + path = require('path'), + parseUrl = require('url').parse, argv = require('optimist').argv, prompt = require('prompt'), + FormData = require('form-data'), IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -132,13 +135,15 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.saveConfig(project); var form = new FormData(); + form.append('email', project.email); form.append('platform', platform); form.append('build_mode', mode); form.append('csrfmiddlewaretoken', jar.cookies[0].value); - // Add the project properties to the post + // Add the platform specific project properties to the post + console.log(project); for (var property in project) { - if(property.indexOf(platform)) { + if(property.indexOf(platform) == 0) { form.append(property, project[project]); } } @@ -146,10 +151,10 @@ IonicPackageTask.prototype.run = function(ionic) { // Gimmie those sweet sweet files switch(platform) { case 'android': - var keystoreFilePath = path.resolve(project.android_keystore); - if(mode = 'release') { + if(mode == 'release') { + var keystoreFilePath = path.resolve(project.android_keystore); if(fs.existsSync(keystoreFilePath)) { - form.append('android_keystore_file', fs.createReadStream(keystoreFilePath)); + form.append('android_keystore_file', fs.createReadStream(keystoreFilePath), {filename: 'www.zip'}); } else { delete project.android_keystore; ionic.saveConfig(project); From e25a00e8b21332f66c0c36ac147fc25a6b2184cc Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 16 Jan 2014 21:19:27 -0600 Subject: [PATCH 046/850] Try using tar.gz doesn't work --- lib/ionic/package.js | 23 +++++++++++++---------- lib/ionic/start.js | 3 ++- lib/ionic/upload.js | 20 ++++++++++++++------ package.json | 4 +++- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 825c1c9297..b5ffb76f05 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -37,8 +37,8 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } - var upload = new IonicUploadTask(); - upload.run(ionic, function() { + //var upload = new IonicUploadTask(); + //upload.run(ionic, function() { var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -75,7 +75,7 @@ IonicPackageTask.prototype.run = function(ionic) { required: true }, android_key_password: { - description: 'Key Password', + description: 'Key Password (optional)', message: 'Password for Key (usually same as Keystore Password and if left blank will use it)', hidden: true, } @@ -109,10 +109,10 @@ IonicPackageTask.prototype.run = function(ionic) { } // Should we just not add this since it's optional? - properties.package_name = { - description: 'Package Name (eg. com.mycompany.app) optional', - message: 'Package Name (eg. com.mycompany.app) optional', - }; + // properties.package_name = { + // description: 'Package Name (eg. com.mycompany.app) optional', + // message: 'Package Name (eg. com.mycompany.app) optional', + // }; // Don't prompt for properties we already have in the config for (var property in properties) { @@ -141,14 +141,13 @@ IonicPackageTask.prototype.run = function(ionic) { form.append('csrfmiddlewaretoken', jar.cookies[0].value); // Add the platform specific project properties to the post - console.log(project); for (var property in project) { if(property.indexOf(platform) == 0) { form.append(property, project[project]); } } - // Gimmie those sweet sweet files + // Gimmie dem sweet sweet files switch(platform) { case 'android': if(mode == 'release') { @@ -201,6 +200,10 @@ IonicPackageTask.prototype.run = function(ionic) { }).join("; ") }) }, function(err, response) { + response.on("data", function(data) { + console.log(data); + }); + if(err) { ionic.fail("Error packaging: " + err); } @@ -209,7 +212,7 @@ IonicPackageTask.prototype.run = function(ionic) { } }); - }); + //}); }; exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 516a3a8505..37ed0fbc63 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -3,6 +3,7 @@ var fs = require('fs'), request = require('request'), ncp = require('ncp').ncp, path = require('path'), + shelljs = require('shelljs/global'), unzip = require('unzip'), argv = require('optimist').argv, IonicTask = require('./task').IonicTask; @@ -77,7 +78,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { rm('-rf', self.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); console.log('Project created!'); - cd(this.targetPath); + cd(self.targetPath); console.log('Initializing cordova project.'); if(!exec('cordova plugin add org.apache.cordova.device') || !exec('cordova plugin add org.apache.cordova.console') || !exec('cordova plugin add org.apache.cordova.statusbar')) { diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 457cceb099..d3724be4ad 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -3,8 +3,11 @@ var fs = require('fs'), parseUrl = require('url').parse, request = require('request'), argv = require('optimist').argv, + shelljs = require('shelljs/global'), + fstream = require('fstream'), + tar = require('tar'), + zlib = require('zlib'), FormData = require('form-data'), - Zip = require('adm-zip'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -20,13 +23,17 @@ IonicUploadTask.prototype.run = function(ionic, callback) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - var zip = new Zip(); - zip.addLocalFolder('www'); - var form = new FormData(); form.append('csrfmiddlewaretoken', jar.cookies[0].value); - // form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip'}); - form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); + + + // Using this http://stackoverflow.com/questions/15530435/node-js-zip-unzip-a-folder + fstream.Reader({ 'path': 'www', 'type': 'Directory' }) /* Read the source directory */ + .pipe(tar.Pack()) /* Convert the directory to a .tar file */ + .pipe(zlib.Gzip()) /* Compress the .tar file */ + .pipe(fstream.Writer({ 'path': 'www.tar.gz', 'type': 'File' })); + form.append('app_file', fs.createReadStream(path.resolve('www.tar.gz')), {filename: 'www.tar.gz', contentType: 'application/x-gzip'}); + // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); var url = ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''); var params = parseUrl(url); @@ -40,6 +47,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { }).join("; ") }) }, function(err, response) { + //rm('-f', 'www.tar.gz'); if(err) { ionic.fail("Error uploading: " + err); } diff --git a/package.json b/package.json index 9ae2025ed9..56cbfad473 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,15 @@ "author": "Max Lynch and Peter Collins ", "license": "MIT", "dependencies": { - "adm-zip": "0.4.3", "cordova": "~3.2.0", "form-data": "~0.1.0", + "fstream": "0.1.25", "ncp": "0.4.2", "optimist": "0.6.0", "prompt": "0.2.12", "request": "2.27.0", + "shelljs": "0.2.6", + "tar": "0.1.19", "unzip": "0.1.9" } } From fe3955c09eae7fdccff4a43df4f7056493c26851 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Thu, 16 Jan 2014 22:01:31 -0600 Subject: [PATCH 047/850] Got zips to work and upload --- lib/ionic/package.js | 7 ++-- lib/ionic/upload.js | 77 ++++++++++++++++++++++++-------------------- package.json | 3 +- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index b5ffb76f05..324d86d242 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -37,8 +37,8 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } - //var upload = new IonicUploadTask(); - //upload.run(ionic, function() { + var upload = new IonicUploadTask(); + upload.run(ionic, function() { var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -210,9 +210,8 @@ IonicPackageTask.prototype.run = function(ionic) { }); }); } - }); - //}); + }); }; exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index d3724be4ad..3e1837f966 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -1,12 +1,8 @@ var fs = require('fs'), path = require('path'), parseUrl = require('url').parse, - request = require('request'), + archiver = require('archiver'), argv = require('optimist').argv, - shelljs = require('shelljs/global'), - fstream = require('fstream'), - tar = require('tar'), - zlib = require('zlib'), FormData = require('form-data'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -23,43 +19,54 @@ IonicUploadTask.prototype.run = function(ionic, callback) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - var form = new FormData(); - form.append('csrfmiddlewaretoken', jar.cookies[0].value); + + var zip = fs.createWriteStream('www.zip'); + var archive = archiver('zip'); + archive.pipe(zip); - // Using this http://stackoverflow.com/questions/15530435/node-js-zip-unzip-a-folder - fstream.Reader({ 'path': 'www', 'type': 'Directory' }) /* Read the source directory */ - .pipe(tar.Pack()) /* Convert the directory to a .tar file */ - .pipe(zlib.Gzip()) /* Compress the .tar file */ - .pipe(fstream.Writer({ 'path': 'www.tar.gz', 'type': 'File' })); - form.append('app_file', fs.createReadStream(path.resolve('www.tar.gz')), {filename: 'www.tar.gz', contentType: 'application/x-gzip'}); - // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); + archive.bulk([ + { expand: true, cwd: 'www/', src: ['**'] } + ]); - var url = ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''); - var params = parseUrl(url); - - form.submit({ - host: params.host, - path: params.path, - headers: form.getHeaders({ - cookie: jar.cookies.map(function (c) { - return c.name + "=" + encodeURIComponent(c.value) - }).join("; ") - }) - }, function(err, response) { - //rm('-f', 'www.tar.gz'); + archive.finalize(function(err, bytes) { if(err) { ionic.fail("Error uploading: " + err); } - if(response.statusCode == 302) { - var redirectPath = parseUrl(response.headers.location); - project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; - ionic.saveConfig(project); + }); - if (callback) { - callback(); - }; - } + zip.on('close', function() { + var form = new FormData(); + form.append('csrfmiddlewaretoken', jar.cookies[0].value); + form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); + // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); + + var url = ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''); + var params = parseUrl(url); + + form.submit({ + host: params.host, + path: params.path, + headers: form.getHeaders({ + cookie: jar.cookies.map(function (c) { + return c.name + "=" + encodeURIComponent(c.value) + }).join("; ") + }) + }, function(err, response) { + rm('-f', 'www.zip'); + if(err) { + ionic.fail("Error uploading: " + err); + } + if(response.statusCode == 302) { + var redirectPath = parseUrl(response.headers.location); + project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; + ionic.saveConfig(project); + + if (callback) { + callback(); + }; + } + }); }); }); }; diff --git a/package.json b/package.json index 56cbfad473..d4c193df28 100644 --- a/package.json +++ b/package.json @@ -25,15 +25,14 @@ "author": "Max Lynch and Peter Collins ", "license": "MIT", "dependencies": { + "archiver": "0.5.1", "cordova": "~3.2.0", "form-data": "~0.1.0", - "fstream": "0.1.25", "ncp": "0.4.2", "optimist": "0.6.0", "prompt": "0.2.12", "request": "2.27.0", "shelljs": "0.2.6", - "tar": "0.1.19", "unzip": "0.1.9" } } From fb79e3a6b8ec17afac7505c159b2af4cc40ac723 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 17 Jan 2014 15:15:14 -0600 Subject: [PATCH 048/850] Handle errors in package --- lib/ionic/package.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 324d86d242..6746589084 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -200,8 +200,15 @@ IonicPackageTask.prototype.run = function(ionic) { }).join("; ") }) }, function(err, response) { + + response.setEncoding('utf8'); response.on("data", function(data) { - console.log(data); + var json = JSON.parse(data); + if(json.errors) { + for (var j = 0; j < json.errors.length; j++) { + process.stderr.write(json.errors[j]); + } + } }); if(err) { From 0cd395a25db282cb826748fb9782d5089a44e6ef Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 17 Jan 2014 16:18:02 -0600 Subject: [PATCH 049/850] Upload name with app --- lib/ionic/package.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 6746589084..7db6b4fbab 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -136,6 +136,7 @@ IonicPackageTask.prototype.run = function(ionic) { var form = new FormData(); form.append('email', project.email); + form.append('name', project.name); form.append('platform', platform); form.append('build_mode', mode); form.append('csrfmiddlewaretoken', jar.cookies[0].value); From 26b034211d575a8555db51706fdc7e64d176e7cc Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 3 Feb 2014 22:38:26 -0600 Subject: [PATCH 050/850] Updated build and emulate --- lib/ionic.js | 8 + lib/ionic/build.js | 5 +- lib/ionic/config.js | 46 ++++ lib/ionic/emulate.js | 49 ++++ lib/ionic/run.js | 5 +- lib/ionic/start.js | 5 +- lib/ionic/stats.js | 542 +++++++++++++++++++++++++++++++++++++++++++ lib/ionic/task.js | 15 +- package.json | 5 +- 9 files changed, 670 insertions(+), 10 deletions(-) create mode 100644 lib/ionic/config.js create mode 100644 lib/ionic/emulate.js create mode 100644 lib/ionic/stats.js diff --git a/lib/ionic.js b/lib/ionic.js index 9d1186486a..ce21f1c517 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -17,6 +17,7 @@ Copyright 2013 Drifty (http://drifty.com/) var IonicStartTask = require('./ionic/start.js').IonicStartTask; var IonicPlatformTask = require('./ionic/platform.js').IonicPlatformTask; var IonicRunTask = require('./ionic/run.js').IonicRunTask; +var IonicEmulateTask = require('./ionic/emulate.js').IonicEmulateTask; var IonicBuildTask = require('./ionic/build.js').IonicBuildTask; var argv = require('optimist').argv; @@ -28,6 +29,12 @@ var TASKS = [ usage: 'appname', task: IonicStartTask }, + { + title: 'emulate', + name: 'emulate', + usage: 'emulate', + task: IonicEmulateTask + }, { title: 'run', name: 'run', @@ -51,6 +58,7 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { + IONIC_CONF: '.ionic', _tryBuildingTask: function() { if(argv._.length == 0) { return false; diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 486ffc909a..1c5cee9200 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -5,7 +5,8 @@ var fs = require('fs'), path = require('path'), shelljs = require('shelljs/global'), unzip = require('unzip'), - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; var argv = require('optimist').argv; @@ -34,6 +35,8 @@ IonicBuildTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } + IonicStats.t('build', { 'platform': platforms.join(',') }); + for(var i = 0; i < platforms.length; i++) { platform = platforms[i]; console.log('Building platform', platform); diff --git a/lib/ionic/config.js b/lib/ionic/config.js new file mode 100644 index 0000000000..af16f1066f --- /dev/null +++ b/lib/ionic/config.js @@ -0,0 +1,46 @@ +var fs = require('fs'), + path = require('path'), + ionic = require('../ionic'); + +var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; + +module.exports = { + CONF_DIR: '.ionic', + CONF_FILE: '.ionic/info.json', + getConfig: function() { + if(fs.existsSync(path.join(home, this.CONF_FILE))) { + var data = JSON.parse(fs.readFileSync(path.join(home, this.CONF_FILE))); + this.data = data; + } else { + this.create(); + } + return this; + }, + get: function(k) { + return this.data[k]; + }, + set: function(k, v) { + if(!this.data) { + this.create(); + } + this.data[k] = v; + this.save(); + }, + save: function() { + if(!this.data) { return; } + + var dirPath = path.join(home, this.CONF_DIR); + var p = path.join(home, this.CONF_FILE); + + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + if(!fs.exists(p)) { + fs.writeFileSync(p, JSON.stringify(this.data)); + } + }, + create: function() { + this.data = {}; + this.save(); + } +}; diff --git a/lib/ionic/emulate.js b/lib/ionic/emulate.js new file mode 100644 index 0000000000..0c1934b12e --- /dev/null +++ b/lib/ionic/emulate.js @@ -0,0 +1,49 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + ncp = require('ncp').ncp, + path = require('path'), + shelljs = require('shelljs/global'), + unzip = require('unzip'), + IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; + +var argv = require('optimist').argv; + +var IonicEmulateTask = function() { +} + +IonicEmulateTask.HELP_LINE = 'Emulate an ionic project on a simulator or emulator.'; + +IonicEmulateTask.prototype = new IonicTask(); + +IonicEmulateTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic emulate [platform]\n'); +} + +IonicEmulateTask.prototype.run = function(ionic) { + var patform; + + if(argv._.length < 2) { + IonicEmulateTask.prototype._printUsage(); + ionic.fail('No platforms specified, exiting.'); + } + + var platforms = argv._.slice(1); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } + + IonicStats.t('emulate', { 'platform': platforms.join(',') }); + + for(var i = 0; i < platforms.length; i++) { + platform = platforms[i]; + console.log('Emulating app on platform', platform); + if(exec("cordova emulate " + platform).code !== 0) { + ionic.fail('Unable to emulate app on platform ' + platform + '. Please see console for more info.'); + } + } +}; + +exports.IonicEmulateTask = IonicEmulateTask; diff --git a/lib/ionic/run.js b/lib/ionic/run.js index 6010728608..cb47f6a8f0 100644 --- a/lib/ionic/run.js +++ b/lib/ionic/run.js @@ -5,7 +5,8 @@ var fs = require('fs'), path = require('path'), shelljs = require('shelljs/global'), unzip = require('unzip'), - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; var argv = require('optimist').argv; @@ -34,6 +35,8 @@ IonicRunTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } + IonicStats.t('run', { 'platform': platforms.join(',') }); + for(var i = 0; i < platforms.length; i++) { platform = platforms[i]; console.log('Running app on platform', platform); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 9079838880..8025e79e0a 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -5,7 +5,8 @@ var fs = require('fs'), path = require('path'), shelljs = require('shelljs/global'), unzip = require('unzip'), - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; var argv = require('optimist').argv; @@ -102,6 +103,8 @@ IonicStartTask.prototype._finish = function() { !exec('cordova plugin add org.apache.cordova.statusbar')) { process.stderr.write('Unable to install one or more cordova plugins.\n'); } + + IonicStats.t('start', {}); }; IonicStartTask.prototype._writeTemplateFolder = function() { diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js new file mode 100644 index 0000000000..7dc7d5948c --- /dev/null +++ b/lib/ionic/stats.js @@ -0,0 +1,542 @@ +var MixpanelAPI, crypto, Buffer, http, querystring, util, path, fs, ionic, os, IonicConfig; +var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __slice = Array.prototype.slice; + +path = require('path'), +http = require('http'); +querystring = require('querystring'); +crypto = require('crypto'); +Buffer = require('buffer').Buffer, +util = require('util'); +es = require('event-stream'); +fs = require('fs'); +os = require('os'); +ionic = require('../ionic'); +IonicConfig = require('./config'); + +/* + Heavily inspired by the original js library copyright Mixpanel, Inc. + (http://mixpanel.com/) + + Copyright (c) 2012 Carl Sverre + + Released under the MIT license. +*/ + +var create_client = function(token, config) { + var metrics = {}; + + if(!token) { + throw new Error("The Mixpanel Client needs a Mixpanel token: `init(token)`"); + } + + metrics.config = { + test: false, + debug: false, + verbose: false + }; + + metrics.token = token; + + /** + send_request(data) + --- + this function sends an async GET request to mixpanel + + data:object the data to send in the request + callback:function(err:Error) callback is called when the request is + finished or an error occurs + */ + metrics.send_request = function(endpoint, data, callback) { + callback = callback || function() {}; + var event_data = new Buffer(JSON.stringify(data)); + var request_data = { + 'data': event_data.toString('base64'), + 'ip': 0, + 'verbose': metrics.config.verbose ? 1 : 0 + }; + + if (endpoint === '/import') { + var key = metrics.config.key; + if (!key) { + throw new Error("The Mixpanel Client needs a Mixpanel api key when importing old events: `init(token, { key: ... })`"); + } + request_data.api_key = key; + } + + var request_options = { + host: 'api.mixpanel.com', + port: 80, + headers: {} + }; + + if (metrics.config.test) { request_data.test = 1; } + + var query = querystring.stringify(request_data); + + request_options.path = [endpoint,"?",query].join(""); + + http.get(request_options, function(res) { + var data = ""; + res.on('data', function(chunk) { + data += chunk; + }); + + res.on('end', function() { + var e; + if(metrics.config.verbose) { + try { + var result = JSON.parse(data); + if(result.status != 1) { + e = new Error("Mixpanel Server Error: " + result.error); + } + } + catch(ex) { + e = new Error("Could not parse response from Mixpanel"); + } + } + else { + e = (data !== '1') ? new Error("Mixpanel Server Error: " + data) : undefined; + } + + callback(e); + }); + }).on('error', function(e) { + if(metrics.config.debug) { + console.log("Got Error: " + e.message); + } + callback(e); + }); + }; + + /** + track(event, properties, callback) + --- + this function sends an event to mixpanel. + + event:string the event name + properties:object additional event properties to send + callback:function(err:Error) callback is called when the request is + finished or an error occurs + */ + metrics.track = function(event, properties, callback) { + if (typeof(properties) === 'function' || !properties) { + callback = properties; + properties = {}; + } + + // if properties.time exists, use import endpoint + var endpoint = (typeof(properties.time) === 'number') ? '/import' : '/track'; + + properties.token = metrics.token; + properties.mp_lib = "node"; + + var data = { + 'event' : event, + 'properties' : properties + }; + + if (metrics.config.debug) { + console.log("Sending the following event to Mixpanel:"); + console.log(data); + } + + metrics.send_request(endpoint, data, callback); + }; + + /** + import(event, properties, callback) + --- + This function sends an event to mixpanel using the import + endpoint. The time argument should be either a Date or Number, + and should signify the time the event occurred. + + It is highly recommended that you specify the distinct_id + property for each event you import, otherwise the events will be + tied to the IP address of the sending machine. + + For more information look at: + https://mixpanel.com/docs/api-documentation/importing-events-older-than-31-days + + event:string the event name + time:date|number the time of the event + properties:object additional event properties to send + callback:function(err:Error) callback is called when the request is + finished or an error occurs + */ + metrics.import = function(event, time, properties, callback) { + if (typeof(properties) === 'function' || !properties) { + callback = properties; + properties = {}; + } + + if (time === void 0) { + throw new Error("The import method requires you to specify the time of the event"); + } else if (Object.prototype.toString.call(time) === '[object Date]') { + time = Math.floor(time.getTime() / 1000); + } + + properties.time = time; + + metrics.track(event, properties, callback); + }; + + /** + alias(distinct_id, alias) + --- + This function creates an alias for distinct_id + + For more information look at: + https://mixpanel.com/docs/integration-libraries/using-mixpanel-alias + + distinct_id:string the current identifier + alias:string the future alias + */ + metrics.alias = function(distinct_id, alias, callback) { + var properties = { + distinct_id: distinct_id, + alias: alias + }; + + metrics.track('$create_alias', properties, callback); + }; + + metrics.people = { + /** people.set_once(distinct_id, prop, to, callback) + --- + The same as people.set but in the words of mixpanel: + mixpanel.people.set_once + + " This method allows you to set a user attribute, only if + it is not currently set. It can be called multiple times + safely, so is perfect for storing things like the first date + you saw a user, or the referrer that brought them to your + website for the first time. " + + */ + set_once: function(distinct_id, prop, to, callback) { + var $set = {}, data = {}; + + if (typeof(prop) === 'object') { + callback = to; + $set = prop; + } else { + $set[prop] = to; + } + + this._set(distinct_id, $set, callback, { set_once: true }); + }, + + /** + people.set(distinct_id, prop, to, callback) + --- + set properties on an user record in engage + + usage: + + mixpanel.people.set('bob', 'gender', 'm'); + + mixpanel.people.set('joe', { + 'company': 'acme', + 'plan': 'premium' + }); + */ + set: function(distinct_id, prop, to, callback) { + var $set = {}, data = {}; + + if (typeof(prop) === 'object') { + callback = to; + $set = prop; + } else { + $set[prop] = to; + } + + this._set(distinct_id, $set, callback); + }, + + // used internally by set and set_once + _set: function(distinct_id, $set, callback, options) { + var set_key = (options && options.set_once) ? "$set_once" : "$set"; + + var data = { + '$token': metrics.token, + '$distinct_id': distinct_id + }; + data[set_key] = $set; + + if ('ip' in $set) { + data.$ip = $set.ip; + delete $set.ip; + } + + if ($set.$ignore_time) { + data.$ignore_time = $set.$ignore_time; + delete $set.$ignore_time; + } + + if(metrics.config.debug) { + console.log("Sending the following data to Mixpanel (Engage):"); + console.log(data); + } + + metrics.send_request('/engage', data, callback); + }, + + /** + people.increment(distinct_id, prop, to, callback) + --- + increment/decrement properties on an user record in engage + + usage: + + mixpanel.people.increment('bob', 'page_views', 1); + + // or, for convenience, if you're just incrementing a counter by 1, you can + // simply do + mixpanel.people.increment('bob', 'page_views'); + + // to decrement a counter, pass a negative number + mixpanel.people.increment('bob', 'credits_left', -1); + + // like mixpanel.people.set(), you can increment multiple properties at once: + mixpanel.people.increment('bob', { + counter1: 1, + counter2: 3, + counter3: -2 + }); + */ + increment: function(distinct_id, prop, by, callback) { + var $add = {}; + + if (typeof(prop) === 'object') { + callback = by; + Object.keys(prop).forEach(function(key) { + var val = prop[key]; + + if (isNaN(parseFloat(val))) { + if (metrics.config.debug) { + console.error("Invalid increment value passed to mixpanel.people.increment - must be a number"); + console.error("Passed " + key + ":" + val); + } + return; + } else { + $add[key] = val; + } + }); + } else { + if (!by) { by = 1; } + $add[prop] = by; + } + + var data = { + '$add': $add, + '$token': metrics.token, + '$distinct_id': distinct_id + }; + + if(metrics.config.debug) { + console.log("Sending the following data to Mixpanel (Engage):"); + console.log(data); + } + + metrics.send_request('/engage', data, callback); + }, + + /** + people.track_charge(distinct_id, amount, properties, callback) + --- + Record that you have charged the current user a certain + amount of money. + + usage: + + // charge a user $29.99 + mixpanel.people.track_charge('bob', 29.99); + + // charge a user $19 on the 1st of february + mixpanel.people.track_charge('bob', 19, { '$time': new Date('feb 1 2012') }); + */ + track_charge: function(distinct_id, amount, properties, callback) { + var $append = {}; + + if (!properties) { properties = {}; } + + if (typeof(amount) !== 'number') { + amount = parseFloat(amount); + if (isNaN(amount)) { + console.error("Invalid value passed to mixpanel.people.track_charge - must be a number"); + return; + } + } + + properties.$amount = amount; + + if (properties.hasOwnProperty('$time')) { + var time = properties.$time; + if (Object.prototype.toString.call(time) === '[object Date]') { + properties.$time = time.toISOString(); + } + } + + var data = { + '$append': { '$transactions': properties }, + '$token': metrics.token, + '$distinct_id': distinct_id + }; + + if(metrics.config.debug) { + console.log("Sending the following data to Mixpanel (Engage):"); + console.log(data); + } + + metrics.send_request('/engage', data, callback); + }, + + /** + people.clear_charges(distinct_id, callback) + --- + Clear all the current user's transactions. + + usage: + + mixpanel.people.clear_charges('bob'); + */ + clear_charges: function(distinct_id, callback) { + var data = { + '$set': { '$transactions': [] }, + '$token': metrics.token, + '$distinct_id': distinct_id + }; + + if(metrics.config.debug) { + console.log("Clearing this user's charges:", distinct_id); + } + + metrics.send_request('/engage', data, callback); + }, + + /** + people.delete_user(distinct_id, callback) + --- + delete an user record in engage + + usage: + + mixpanel.people.delete_user('bob'); + */ + delete_user: function(distinct_id, callback) { + var data = { + '$delete': distinct_id, + '$token': metrics.token, + '$distinct_id': distinct_id + }; + + if(metrics.config.debug) { + console.log("Deleting the user from engage:", distinct_id); + } + + metrics.send_request('/engage', data, callback); + }, + + /** + people.unset(distinct_id, prop, callback) + --- + delete a property on an user record in engage + + usage: + + mixpanel.people.unset('bob', 'page_views'); + + mixpanel.people.unset('bob', ['page_views', 'last_login']); + */ + unset: function(distinct_id, prop, callback) { + var $unset = []; + + if (util.isArray(prop)) { + $unset = prop; + } else if (typeof(prop) === 'string') { + $unset = [prop]; + } else { + if (metrics.config.debug) { + console.error("Invalid argument passed to mixpanel.people.unset - must be a string or array"); + console.error("Passed: " + prop); + } + return; + } + + data = { + '$unset': $unset, + '$token': metrics.token, + '$distinct_id': distinct_id + }; + + if(metrics.config.debug) { + console.log("Sending the following data to Mixpanel (Engage):"); + console.log(data); + } + + metrics.send_request('/engage', data, callback); + } + }; + + /** + set_config(config) + --- + Modifies the mixpanel config + + config:object an object with properties to override in the + mixpanel client config + */ + metrics.set_config = function(config) { + for (var c in config) { + if (config.hasOwnProperty(c)) { + metrics.config[c] = config[c]; + } + } + }; + + if (config) { + metrics.set_config(config); + } + + return metrics; +}; + +// module exporting +/* +module.exports = { + Client: function(token) { + console.warn("The function `Client(token)` is deprecated. It is now called `init(token)`."); + return create_client(token); + }, + init: create_client +}; +*/ + +var mixpanel = create_client('69f7271aa8f3d43f2e1b6baf698159b7'); + +var ionicConfig = IonicConfig.getConfig(); + + +exports.IonicStats = { + t: function(e, d) { + var unique_id = ionicConfig.get('ank'); + if(!unique_id) { + this.createdId(); + unique_id = ionicConfig.get('ank'); + } + d.distinct_id = unique_id; + mixpanel.track(e, d, function(err, data) { + }); + }, + createId: function() { + var d = new Date().getTime(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c=='x' ? r : (r&0x7|0x8)).toString(16); + }); + + ionicConfig.set('ank', uuid); + } +} diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 20b74b4c1f..6a8dcf9d3c 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -5,17 +5,22 @@ var IonicTask = function() { IonicTask.prototype = { // Prompt the user for a response - ask: function(question) { + ask: function(question, cb) { var response; process.stdout.write(question + ' '); + process.stdin.resume(); - response = fs.readSync(process.stdin.fd, 100, 0, "utf8"); - process.stdin.pause(); - return response[0].trim(); + process.stdin.setEncoding('utf8'); + var util = require('util'); + + process.stdin.on('data', function (text) { + cb(util.inspect(text)); + process.stdin.pause(); + }); }, run: function(ionic) { } }; -exports.IonicTask = IonicTask; \ No newline at end of file +exports.IonicTask = IonicTask; diff --git a/package.json b/package.json index 4cada292c0..c1de740772 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.10", + "version": "0.9.11", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -30,6 +30,7 @@ "shelljs": "0.2.6", "unzip": "0.1.9", "ncp": "0.4.2", - "optimist": "0.6.0" + "optimist": "0.6.0", + "event-stream": "3.0.x" } } From 83b36d900e37f0218128f8ed6b0624dd785d33a0 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 3 Feb 2014 22:47:36 -0600 Subject: [PATCH 051/850] Platform --- lib/ionic/platform.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js index 9993cb3ac1..873d7736a4 100644 --- a/lib/ionic/platform.js +++ b/lib/ionic/platform.js @@ -5,7 +5,8 @@ var fs = require('fs'), path = require('path'), shelljs = require('shelljs/global'), unzip = require('unzip'), - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; var argv = require('optimist').argv; @@ -35,6 +36,8 @@ IonicPlatformTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } + IonicStats.t('platform', { 'platform': platforms.join(',') }); + for(var i = 0; i < platforms.length; i++) { platform = platforms[i]; console.log('Adding platform', platform); From bd5546d3e66c55f1e15c0e6033c3800105d51af5 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 3 Feb 2014 22:48:00 -0600 Subject: [PATCH 052/850] version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c1de740772..a46d586acc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.11", + "version": "0.9.12", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 52f84c55e39a0239e2bfe258fc893b7ce3edb048 Mon Sep 17 00:00:00 2001 From: Andy Joslin Date: Tue, 4 Feb 2014 08:56:53 -0500 Subject: [PATCH 053/850] fix(stats): typo s/createdId/createId --- lib/ionic/stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index 7dc7d5948c..bddc6bba87 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -522,7 +522,7 @@ exports.IonicStats = { t: function(e, d) { var unique_id = ionicConfig.get('ank'); if(!unique_id) { - this.createdId(); + this.createId(); unique_id = ionicConfig.get('ank'); } d.distinct_id = unique_id; From 421a035ff09579a96e6d359d6eb468e7f511644e Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 4 Feb 2014 08:13:10 -0600 Subject: [PATCH 054/850] Package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a46d586acc..7e482cd965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.12", + "version": "0.9.13", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 285772fc82b19d2844179a87d7cdc468b1277db0 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 4 Feb 2014 09:51:12 -0600 Subject: [PATCH 055/850] Readme info --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00cc6c4f0b..a6c22c3037 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,44 @@ -ionic-cli +Ionic-Cli ========= -The Ionic Framework command line utility +The Ionic Framework command line utility makes it easy to start, build, run, and emulate Ionic apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. + +## Installing + +```bash +$ sudo npm install -g ionic +``` + +## Starting an Ionic App + +```bash +$ ionic start myApp +``` + +## Adding a platform target + +```bash +$ ionic platform ios android +``` + +## Building your app + +```bash +$ ionic build ios +``` + +## Emulating your app + +```bash +$ ionic emulate ios +``` + +## Running your app + +```bash +$ ionic run ios +``` + +Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. + +Note: we occasionally anonymous usage statistics to the Ionic team to make the tool better. From 7ea32c2acf483545c42206328f140a760714b4f9 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 4 Feb 2014 09:51:28 -0600 Subject: [PATCH 056/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6c22c3037..87439694e8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Ionic-Cli ========= -The Ionic Framework command line utility makes it easy to start, build, run, and emulate Ionic apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. +The Ionic Framework command line utility makes it easy to start, build, run, and emulate [Ionic](http://ionicframework.com/) apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. ## Installing From 78df86502d821d12c42498f6d4afc2bc41ff0abd Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 09:25:26 -0600 Subject: [PATCH 057/850] Added some protection --- lib/ionic/config.js | 18 +++++++++++------- package.json | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/ionic/config.js b/lib/ionic/config.js index af16f1066f..2b9e1b6c67 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -29,14 +29,18 @@ module.exports = { save: function() { if(!this.data) { return; } - var dirPath = path.join(home, this.CONF_DIR); - var p = path.join(home, this.CONF_FILE); + try { + var dirPath = path.join(home, this.CONF_DIR); + var p = path.join(home, this.CONF_FILE); - if(!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath); - } - if(!fs.exists(p)) { - fs.writeFileSync(p, JSON.stringify(this.data)); + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + if(!fs.exists(p)) { + fs.writeFileSync(p, JSON.stringify(this.data)); + } + } catch(e) { + console.error('Unable to save settings file:', e); } }, create: function() { diff --git a/package.json b/package.json index 7e482cd965..db428156d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.13", + "version": "0.9.14", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From eb33cbf47ebe55fd8d39fee632af75cfb206a7cf Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 10:17:51 -0600 Subject: [PATCH 058/850] Unix line endings From 59518ac11c1519376d305855629bc7bb2489092a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 10:18:35 -0600 Subject: [PATCH 059/850] Carriage return --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db428156d9..621b96a50f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.14", + "version": "0.9.15", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From e45c39b660100d71e522f2a194df70c46bf370c1 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 10:22:54 -0600 Subject: [PATCH 060/850] Trying to force line ending fix --- bin/ionic | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/ionic b/bin/ionic index 0454b93e1f..171649cb21 100644 --- a/bin/ionic +++ b/bin/ionic @@ -1,5 +1,6 @@ #!/usr/bin/env node + 'use strict'; process.title = 'ionic'; From 73a66f697a37ef6988f7831a52c84c96696176ae Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 10:42:47 -0600 Subject: [PATCH 061/850] Ban CRLF forever --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..83cb362591 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# FUCK CRLF +* text eol=lf From a44fd0fc4f62d05d9a860d974ab7619e0e0224b6 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 8 Feb 2014 10:44:04 -0600 Subject: [PATCH 062/850] vBump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 621b96a50f..7bd10d86f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.15", + "version": "0.9.16", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From d306ae25d73fcf3648b2e4bb0e4ad50a8d95ceb9 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 10 Feb 2014 11:37:16 -0600 Subject: [PATCH 063/850] Whoops finish merge --- lib/ionic/build.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 5c6eef5e90..04e871ed02 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -1,9 +1,6 @@ -<<<<<<< HEAD -var argv = require('optimist').argv, - IonicTask = require('./task').IonicTask; -======= var fs = require('fs'), os = require('os'), + argv = require('optimist').argv, request = require('request'), ncp = require('ncp').ncp, path = require('path'), @@ -11,7 +8,6 @@ var fs = require('fs'), unzip = require('unzip'), IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats; ->>>>>>> master var IonicBuildTask = function() { } From 224a385e6892a70af5123bd24c6091662c85ef38 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 17 Feb 2014 11:41:51 -0600 Subject: [PATCH 064/850] Change to official package site --- lib/ionic.js | 4 +- lib/ionic/login.js | 244 +++++++++++------------ lib/ionic/package.js | 456 ++++++++++++++++++++++--------------------- lib/ionic/upload.js | 8 + 4 files changed, 363 insertions(+), 349 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index dffbaf246c..1107c92990 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -17,7 +17,7 @@ Copyright 2013 Drifty (http://drifty.com/) var IonicStartTask = require('./ionic/start').IonicStartTask, IonicPlatformTask = require('./ionic/platform').IonicPlatformTask, IonicRunTask = require('./ionic/run').IonicRunTask, - IonicEmulateTask = require('./ionic/emulate.js').IonicEmulateTask; + IonicEmulateTask = require('./ionic/emulate').IonicEmulateTask; IonicBuildTask = require('./ionic/build').IonicBuildTask, IonicLoginTask = require('./ionic/login').IonicLoginTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, @@ -82,7 +82,7 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { - IONIC_DASH: 'http://virt/', + IONIC_DASH: 'http://apps.ionicframework.com/', IONIC_COOKIES: 'ionic.cookies', IONIC_CONFIG: 'ionic.config', IONIC_CONF: '.ionic', diff --git a/lib/ionic/login.js b/lib/ionic/login.js index cb40e3077d..c631b6c353 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -1,122 +1,122 @@ -var fs = require('fs'), - request = require('request'), - argv = require('optimist').argv, - prompt = require('prompt'), - IonicTask = require('./task').IonicTask; - -var IonicLoginTask = function() { -} - -IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; - -IonicLoginTask.prototype = new IonicTask(); - -IonicLoginTask.prototype.run = function(ionic, callback) { - var self = this; - var schema = [{ - name: 'email', - pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, - message: 'Email for Ionic Studio login', - required: true - }, { - name: 'password', - hidden: true, - required: true - }]; - - var project = ionic.loadConfig(); - - // Grab the email for login - if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { - this.email = argv._[1].toLowerCase(); - schema.shift(); - } - // Assume project email is login email if it exists - else if(project.email && project.email != '') { - this.email = project.email; - schema.shift(); - } - - prompt.override = argv; - - prompt.start(); - - prompt.get(schema, function (err, result) { - if(err) { - ionic.fail('Error logging in: ' + err); - } - - if(!self.email) { - self.email = result.email.toLowerCase(); - } - self.password = result.password; - - if(!project.email || project.email == '') { - project.email = self.email; - ionic.saveConfig(project); - } - - var jar = request.jar(); - request({ - url: ionic.IONIC_DASH+'login', - jar: jar - }, - function(err, response, body) { - if(err || jar.cookies.length == 0) { - ionic.fail('Error logging in: ' + err); - } - - request({ - method: 'POST', - url: ionic.IONIC_DASH+'login', - jar: jar, - form: { - username: self.email, - password: self.password, - csrfmiddlewaretoken: jar.cookies[0].value - } - }, - function (err, response, body) { - if(err) { - ionic.fail('Error logging in: ' + err); - } - // Should be a 304 redirect status code if correct - if(response.statusCode == 200) { - ionic.fail('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') - } - - var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); - if(err) { - ionic.fail('Error writing ' + ionic.IONIC_COOKIES + ': ' + err); - } - - console.log('Logged in! :)'); - - if(callback) { - callback(jar); - } - }); - }); - }); -}; - -IonicLoginTask.prototype.get = function(ionic, callback) { - var self = this; - - if(fs.existsSync(ionic.IONIC_COOKIES)) { - var jar = JSON.parse(fs.readFileSync(ionic.IONIC_COOKIES)); - if(jar.cookies && jar.cookies.length > 0) { - for(i in jar.cookies) { - var cookie = jar.cookies[i]; - if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { - callback(jar); - return; - } - } - } - } - - this.run(ionic, callback); -} - -exports.IonicLoginTask = IonicLoginTask; +var fs = require('fs'), + request = require('request'), + argv = require('optimist').argv, + prompt = require('prompt'), + IonicTask = require('./task').IonicTask; + +var IonicLoginTask = function() { +} + +IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; + +IonicLoginTask.prototype = new IonicTask(); + +IonicLoginTask.prototype.run = function(ionic, callback) { + var self = this; + var schema = [{ + name: 'email', + pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, + message: 'Email for Ionic Studio login', + required: true + }, { + name: 'password', + hidden: true, + required: true + }]; + + var project = ionic.loadConfig(); + + // Grab the email for login + if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { + this.email = argv._[1].toLowerCase(); + schema.shift(); + } + // Assume project email is login email if it exists + else if(project.email && project.email != '') { + this.email = project.email; + schema.shift(); + } + + prompt.override = argv; + + prompt.start(); + + prompt.get(schema, function (err, result) { + if(err) { + ionic.fail('Error logging in: ' + err); + } + + if(!self.email) { + self.email = result.email.toLowerCase(); + } + self.password = result.password; + + if(!project.email || project.email == '') { + project.email = self.email; + ionic.saveConfig(project); + } + + var jar = request.jar(); + request({ + url: ionic.IONIC_DASH+'login', + jar: jar + }, + function(err, response, body) { + if(err || jar.cookies.length == 0) { + ionic.fail('Error logging in: ' + err); + } + + request({ + method: 'POST', + url: ionic.IONIC_DASH+'login', + jar: jar, + form: { + username: self.email, + password: self.password, + csrfmiddlewaretoken: jar.cookies[0].value + } + }, + function (err, response, body) { + if(err) { + ionic.fail('Error logging in: ' + err); + } + // Should be a 304 redirect status code if correct + if(response.statusCode == 200) { + ionic.fail('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') + } + + var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); + if(err) { + ionic.fail('Error writing ' + ionic.IONIC_COOKIES + ': ' + err); + } + + console.log('Logged in! :)'); + + if(callback) { + callback(jar); + } + }); + }); + }); +}; + +IonicLoginTask.prototype.get = function(ionic, callback) { + var self = this; + + if(fs.existsSync(ionic.IONIC_COOKIES)) { + var jar = JSON.parse(fs.readFileSync(ionic.IONIC_COOKIES)); + if(jar.cookies && jar.cookies.length > 0) { + for(i in jar.cookies) { + var cookie = jar.cookies[i]; + if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { + callback(jar); + return; + } + } + } + } + + this.run(ionic, callback); +} + +exports.IonicLoginTask = IonicLoginTask; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 7db6b4fbab..113dcb67ff 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -1,225 +1,231 @@ -var fs = require('fs'), - path = require('path'), - parseUrl = require('url').parse, - argv = require('optimist').argv, - prompt = require('prompt'), - FormData = require('form-data'), - IonicTask = require('./task').IonicTask, - IonicUploadTask = require('./upload').IonicUploadTask, - IonicLoginTask = require('./login').IonicLoginTask; - -var IonicPackageTask = function() { -} - -IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; - -IonicPackageTask.prototype = new IonicTask(); - -IonicPackageTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic package mode(debug|release) platform [more platforms,...]\n'); -} - -IonicPackageTask.prototype.run = function(ionic) { - if(argv._.length < 3) { - IonicPackageTask.prototype._printUsage(); - ionic.fail('No platforms or build mode specified, exiting.'); - } - - var mode = argv._[1].toLowerCase(); - if(mode != 'debug' && mode != 'release') { - IonicPackageTask.prototype._printUsage(); - ionic.fail('Package build mode must be debug or release, exiting.'); - } - - var platforms = argv._.slice(2); - - if(platforms.length < 1) { - ionic.fail('No platforms specified, exiting.'); - } - - var upload = new IonicUploadTask(); - upload.run(ionic, function() { - - var login = new IonicLoginTask(); - login.get(ionic, function(jar) { - - var project = ionic.loadConfig(); - - for(var i = 0; i < platforms.length; i++) { - var platform = platforms[i]; - - prompt.override = argv; - prompt.start(); - var properties = {}; - - // Just prompt for some build properties - switch (platform) { - case 'android': - // Android debug doesn't require anything - if(mode == 'release') { - properties = { - android_keystore: { - description: 'Android Keystore File (.keystore)', - message: 'Relative path to your release keystore file (eg. release.keystore)', - required: true - }, - android_keystore_alias: { - description: 'Keystore Alias', - message: 'Alias of the Keystore', - required: true - }, - android_keystore_password: { - description: 'Keystore Password', - message: 'Password of the Keystore', - hidden: true, - required: true - }, - android_key_password: { - description: 'Key Password (optional)', - message: 'Password for Key (usually same as Keystore Password and if left blank will use it)', - hidden: true, - } - }; - } - - break; - case 'ios': - properties = { - ios_certificate: { - description: 'iOS Certificate File (.p12)', - message: 'Relative path to your certificate file (eg. cert.p12)', - required: true - }, - ios_certificate_password: { - description: 'Certificate Password', - message: 'Password of the Certificate', - hidden: true, - required: true - }, - ios_profile: { - description: 'iOS Mobile Provisioning Profile (.mobileprofile)', - message: 'Relative path to your Mobile Provisioning Profile (eg. my.mobileprofile)', - required: true - }, - }; - break; - default: - process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently are "ios" and "android"\n\n'); - continue; - } - - // Should we just not add this since it's optional? - // properties.package_name = { - // description: 'Package Name (eg. com.mycompany.app) optional', - // message: 'Package Name (eg. com.mycompany.app) optional', - // }; - - // Don't prompt for properties we already have in the config - for (var property in properties) { - if(project[property] && project[project] == '') { - delete properties[property]; - } - } - - prompt.get({properties: properties}, function (err, result) { - if(err) { - ionic.fail('Error packaging: ' + err); - } - - // Overwrite any empty properties with prompt responses - for (var property in properties) { - if(project[property] && project[project] == '') { - project[property] = result[property]; - } - } - ionic.saveConfig(project); - - var form = new FormData(); - form.append('email', project.email); - form.append('name', project.name); - form.append('platform', platform); - form.append('build_mode', mode); - form.append('csrfmiddlewaretoken', jar.cookies[0].value); - - // Add the platform specific project properties to the post - for (var property in project) { - if(property.indexOf(platform) == 0) { - form.append(property, project[project]); - } - } - - // Gimmie dem sweet sweet files - switch(platform) { - case 'android': - if(mode == 'release') { - var keystoreFilePath = path.resolve(project.android_keystore); - if(fs.existsSync(keystoreFilePath)) { - form.append('android_keystore_file', fs.createReadStream(keystoreFilePath), {filename: 'www.zip'}); - } else { - delete project.android_keystore; - ionic.saveConfig(project); - process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); - return; - } - } - break; - case 'ios': - var certificateFilePath = path.resolve(project.ios_certificate); - if(fs.existsSync(certificateFilePath)) { - form.append('ios_certificate_file', fs.createReadStream(certificateFilePath)); - } else { - delete project.ios_certificate; - ionic.saveConfig(project); - process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); - return; - } - var profileFilePath = path.resolve(project.ios_profile); - if(fs.existsSync(profileFilePath)) { - form.append('ios_profile_file', fs.createReadStream(profileFilePath)); - } else { - delete project.ios_profile; - ionic.saveConfig(project); - process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); - return; - } - break; - default: - console.trace(); - process.stderr.write('\nUnknown platform: "'+platform+'"\nWe should never get here"\n\n'); - break; - } - - var url = ionic.IONIC_DASH+'export/'+project.app_id; - var params = parseUrl(url); - - form.submit({ - host: params.host, - path: params.path, - headers: form.getHeaders({ - cookie: jar.cookies.map(function (c) { - return c.name + "=" + encodeURIComponent(c.value) - }).join("; ") - }) - }, function(err, response) { - - response.setEncoding('utf8'); - response.on("data", function(data) { - var json = JSON.parse(data); - if(json.errors) { - for (var j = 0; j < json.errors.length; j++) { - process.stderr.write(json.errors[j]); - } - } - }); - - if(err) { - ionic.fail("Error packaging: " + err); - } - }); - }); - } - }); - }); -}; - -exports.IonicPackageTask = IonicPackageTask; +var fs = require('fs'), + path = require('path'), + parseUrl = require('url').parse, + argv = require('optimist').argv, + prompt = require('prompt'), + FormData = require('form-data'), + IonicTask = require('./task').IonicTask, + IonicUploadTask = require('./upload').IonicUploadTask, + IonicLoginTask = require('./login').IonicLoginTask; + +var IonicPackageTask = function() { +} + +IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; + +IonicPackageTask.prototype = new IonicTask(); + +IonicPackageTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic package mode(debug|release) platform [more platforms,...]\n'); +} + +IonicPackageTask.prototype.run = function(ionic) { + if(argv._.length < 3) { + IonicPackageTask.prototype._printUsage(); + ionic.fail('No platforms or build mode specified, exiting.'); + } + + var mode = argv._[1].toLowerCase(); + if(mode != 'debug' && mode != 'release') { + IonicPackageTask.prototype._printUsage(); + ionic.fail('Package build mode must be debug or release, exiting.'); + } + + var platforms = argv._.slice(2); + + if(platforms.length < 1) { + ionic.fail('No platforms specified, exiting.'); + } + + var upload = new IonicUploadTask(); + upload.run(ionic, function() { + + var login = new IonicLoginTask(); + login.get(ionic, function(jar) { + + var project = ionic.loadConfig(); + + for(var i = 0; i < platforms.length; i++) { + var platform = platforms[i]; + + prompt.override = argv; + prompt.start(); + var properties = {}; + + // Just prompt for some build properties + switch (platform) { + case 'android': + // Android debug doesn't require anything + if(mode == 'release') { + properties = { + android_keystore: { + description: 'Android Keystore File (.keystore)', + message: 'Relative path to your release keystore file (eg. release.keystore)', + required: true + }, + android_keystore_alias: { + description: 'Keystore Alias', + message: 'Alias of the Keystore', + required: true + }, + android_keystore_password: { + description: 'Keystore Password', + message: 'Password of the Keystore', + hidden: true, + required: true + }, + android_key_password: { + description: 'Key Password (optional)', + message: 'Password for Key (usually same as Keystore Password and if left blank will use it)', + hidden: true, + } + }; + } + + break; + case 'ios': + properties = { + ios_certificate: { + description: 'iOS Certificate File (.p12)', + message: 'Relative path to your certificate file (eg. cert.p12)', + required: true + }, + ios_certificate_password: { + description: 'Certificate Password', + message: 'Password of the Certificate', + hidden: true, + required: true + }, + ios_profile: { + description: 'iOS Mobile Provisioning Profile (.mobileprovision)', + message: 'Relative path to your Mobile Provisioning Profile (eg. my.mobileprovision)', + required: true + }, + }; + break; + default: + process.stderr.write('\nUnknown platform: "'+platform+'"\nSupported platforms currently are "ios" and "android"\n\n'); + continue; + } + + // Should we just not add this since it's optional? + // properties.package_name = { + // description: 'Package Name (eg. com.mycompany.app) optional', + // message: 'Package Name (eg. com.mycompany.app) optional', + // }; + + // Don't prompt for properties we already have in the config + for (var property in properties) { + if(project[property]) { + delete properties[property]; + } + } + + prompt.get({properties: properties}, function (err, result) { + if(err) { + ionic.fail('Error packaging: ' + err); + } + + // Overwrite any empty properties with prompt responses + for (var property in properties) { + if(result[property] && !project[property]) { + project[property] = result[property]; + } + } + ionic.saveConfig(project); + + console.log('Packaging '+platform+' app...'); + + var form = new FormData(); + form.append('email', project.email); + form.append('name', project.name); + form.append('platform', platform); + form.append('build_mode', mode); + form.append('csrfmiddlewaretoken', jar.cookies[0].value); + + + // Add the platform specific project properties to the post + for (var property in project) { + // console.log(property); + // console.log(project[property]); + if(property.indexOf(platform) == 0) { + form.append(property, project[property]); + } + } + + // Gimmie dem sweet sweet files + switch(platform) { + case 'android': + if(mode == 'release') { + var keystoreFilePath = path.resolve(project.android_keystore); + if(fs.existsSync(keystoreFilePath)) { + form.append('android_keystore_file', fs.createReadStream(keystoreFilePath), {filename: 'www.zip'}); + } else { + delete project.android_keystore; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); + return; + } + } + break; + case 'ios': + var certificateFilePath = path.resolve(project.ios_certificate); + if(fs.existsSync(certificateFilePath)) { + form.append('ios_certificate_file', fs.createReadStream(certificateFilePath)); + } else { + delete project.ios_certificate; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); + return; + } + var profileFilePath = path.resolve(project.ios_profile); + if(fs.existsSync(profileFilePath)) { + form.append('ios_profile_file', fs.createReadStream(profileFilePath)); + } else { + delete project.ios_profile; + ionic.saveConfig(project); + process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); + return; + } + break; + default: + console.trace(); + process.stderr.write('\nUnknown platform: "'+platform+'"\nWe should never get here"\n\n'); + break; + } + + var url = ionic.IONIC_DASH+'export/'+project.app_id; + var params = parseUrl(url); + + form.submit({ + host: params.host, + path: params.path, + headers: form.getHeaders({ + cookie: jar.cookies.map(function (c) { + return c.name + "=" + encodeURIComponent(c.value) + }).join("; ") + }) + }, function(err, response) { + + response.setEncoding('utf8'); + response.on("data", function(data) { + var json = JSON.parse(data); + if(json.errors) { + for (var j = 0; j < json.errors.length; j++) { + process.stderr.write(json.errors[j]); + } + } + }); + + if(err) { + ionic.fail("Error packaging: " + err); + } + console.log('Done'); + }); + }); + } + }); + }); +}; + +exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index e65f01fe0f..31e963f8c7 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -20,6 +20,8 @@ IonicUploadTask.prototype.run = function(ionic, callback) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { + console.log('Zipping...'); + var zip = fs.createWriteStream('www.zip'); var archive = archiver('zip'); @@ -36,6 +38,9 @@ IonicUploadTask.prototype.run = function(ionic, callback) { }); zip.on('close', function() { + console.log('Done'); + console.log('Uploading...'); + var form = new FormData(); form.append('csrfmiddlewaretoken', jar.cookies[0].value); form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); @@ -57,6 +62,9 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(err) { ionic.fail("Error uploading: " + err); } + + console.log('Done'); + if(response.statusCode == 302) { var redirectPath = parseUrl(response.headers.location); project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; From dd99e7c2abf1f6604c592df757292e9786581a77 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 17 Feb 2014 11:51:53 -0600 Subject: [PATCH 065/850] Add signup link --- lib/ionic/login.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index c631b6c353..21ee0e4ccf 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -37,6 +37,8 @@ IonicLoginTask.prototype.run = function(ionic, callback) { schema.shift(); } + console.log('Signup here! http://apps.ionicframework.com/signup'); + prompt.override = argv; prompt.start(); From 540ceb2072bf713677e94f1fcc996f3ffdd50a3e Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 17 Feb 2014 16:07:12 -0600 Subject: [PATCH 066/850] Merge config wip --- lib/ionic.js | 38 +----------------- lib/ionic/config.js | 94 +++++++++++++++++++++++++++++++------------- lib/ionic/login.js | 8 ++-- lib/ionic/package.js | 3 +- lib/ionic/start.js | 7 ++-- lib/ionic/stats.js | 5 +-- lib/ionic/upload.js | 3 +- 7 files changed, 81 insertions(+), 77 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 1107c92990..e5a80ae121 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -84,22 +84,7 @@ Ionic = function() {}; Ionic.prototype = { IONIC_DASH: 'http://apps.ionicframework.com/', IONIC_COOKIES: 'ionic.cookies', - IONIC_CONFIG: 'ionic.config', - IONIC_CONF: '.ionic', - IONIC_API: 'api/v1/', - CONFIG_DEFAULT: { - name: '', - email: '', - app_id: '', - package_name: '', - ios_certificate: '', - ios_certificate_password: '', - ios_profile: '', - android_keystore: '', - android_keystore_alias: '', - android_keystore_password: '', - android_key_password: '' - }, + IONIC_API: 'api/v1/', _tryBuildingTask: function() { if(argv._.length == 0) { return false; @@ -163,28 +148,7 @@ Ionic.prototype = { fail: function(msg) { process.stderr.write(msg + '\n'); process.exit(1); - }, - - loadConfig: function() { - if(!fs.existsSync(this.IONIC_CONFIG)) { - this.fail('Could not find ' + this.IONIC_CONFIG + '!'+ - ' Please run this command your root ionic project directory with that file.'); - } - return JSON.parse(fs.readFileSync(this.IONIC_CONFIG)); - }, - - saveConfig: function(project, targetPath) { - if(!project) { - console.trace(); - this.fail('This should never happen!'); - } - - var err = fs.writeFileSync((targetPath?targetPath+'/':'')+this.IONIC_CONFIG, JSON.stringify(project, null, 2)); - if(err) { - process.stderr.write('Error writing ' + (targetPath?targetPath+'/':'')+ ionic.IONIC_CONFIG + ': ' + err + '\n'); - } } - }; diff --git a/lib/ionic/config.js b/lib/ionic/config.js index 2b9e1b6c67..dafc63e9c7 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -5,46 +5,86 @@ var fs = require('fs'), var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; module.exports = { - CONF_DIR: '.ionic', - CONF_FILE: '.ionic/info.json', - getConfig: function() { - if(fs.existsSync(path.join(home, this.CONF_FILE))) { - var data = JSON.parse(fs.readFileSync(path.join(home, this.CONF_FILE))); - this.data = data; + CONFIG_FILE: '.ionic/ionic.config', + PROJECT_FILE: 'ionic.project', + PROJECT_DEFAULT: { + name: '', + email: '', + app_id: '', + package_name: '', + ios_certificate: '', + ios_certificate_password: '', + ios_profile: '', + android_keystore: '', + android_keystore_alias: '', + android_keystore_password: '', + android_key_password: '' + }, + loadConfig: function() { + this.file = this.CONFIG_FILE; + if(fs.existsSync(path.join(home,this.file))) { + this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); } else { - this.create(); + this.data = {}; } return this; }, - get: function(k) { - return this.data[k]; - }, - set: function(k, v) { - if(!this.data) { - this.create(); + loadProject: function() { + this.file = this.PROJECT_FILE; + if(fs.existsSync(this.file)) { + this.data = JSON.parse(fs.readFileSync(this.file)) + } else { + console.error('Could not find ' + this.file + '!'+ + ' Please run this command in your root ionic project directory with that file.'); } - this.data[k] = v; - this.save(); + return this; }, - save: function() { - if(!this.data) { return; } - + createProject: function(name) { + this.file = this.PROJECT_FILE; + this.data = this.PROJECT_DEFAULT; + this.data.name = name; + return this; + }, + saveConfig: function() { + if(!this.data) { + return; + } try { - var dirPath = path.join(home, this.CONF_DIR); - var p = path.join(home, this.CONF_FILE); + var dirPath = path.join(home, path.dirname(this.CONFIG_FILE)); + var p = path.join(home, this.CONFIG_FILE); if(!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath); } - if(!fs.exists(p)) { - fs.writeFileSync(p, JSON.stringify(this.data)); - } + fs.writeFileSync(p, JSON.stringify(this.data, null, 2)); } catch(e) { console.error('Unable to save settings file:', e); } }, - create: function() { - this.data = {}; - this.save(); - } + saveProject: function(targetPath) { + if(!this.data) { + console.trace(); + console.error('This should never happen!'); + } + try { + fs.writeFileSync((targetPath?targetPath+'/':'')+this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); + } catch(e) { + console.error('Unable to save settings file:', e); + } + }, + get: function(k) { + return this.data[k]; + }, + set: function(k, v) { + if(!this.data) { + this.data = {}; + } + this.data[k] = v; + + if(this.file == this.PROJECT_FILE) { + this.saveProject(); + } else { + this.saveConfig(); + } + } }; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 21ee0e4ccf..245d996e9e 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -2,6 +2,7 @@ var fs = require('fs'), request = require('request'), argv = require('optimist').argv, prompt = require('prompt'), + IonicConfig = require('./config'), IonicTask = require('./task').IonicTask; var IonicLoginTask = function() { @@ -24,7 +25,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { required: true }]; - var project = ionic.loadConfig(); + var project = IonicConfig.loadProject(); // Grab the email for login if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { @@ -53,9 +54,8 @@ IonicLoginTask.prototype.run = function(ionic, callback) { } self.password = result.password; - if(!project.email || project.email == '') { - project.email = self.email; - ionic.saveConfig(project); + if(!project.get('email')) { + project.set('email'); } var jar = request.jar(); diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 113dcb67ff..5a27ad71de 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -4,6 +4,7 @@ var fs = require('fs'), argv = require('optimist').argv, prompt = require('prompt'), FormData = require('form-data'), + IonicConfig = require('./config'), IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -43,7 +44,7 @@ IonicPackageTask.prototype.run = function(ionic) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - var project = ionic.loadConfig(); + var project = IonicConfig.loadProject(); for(var i = 0; i < platforms.length; i++) { var platform = platforms[i]; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 349cafebce..ac118768ec 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -6,6 +6,7 @@ var fs = require('fs'), shelljs = require('shelljs/global'), unzip = require('unzip'), argv = require('optimist').argv, + IonicConfig = require('./config'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -101,10 +102,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { IonicStartTask.prototype._writeConfig = function(ionic) { console.log('Writing '+this.targetPath+'/ionic.config'); - var project = ionic.CONFIG_DEFAULT; - project.name = this.appName; - - ionic.saveConfig(project, this.targetPath); + var project = IonicConfig.createProject(this.appName); + project.saveProject(this.targetPath); }; IonicStartTask.prototype._checkTargetPath = function() { diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index bddc6bba87..ed5313f429 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -1,4 +1,4 @@ -var MixpanelAPI, crypto, Buffer, http, querystring, util, path, fs, ionic, os, IonicConfig; +var MixpanelAPI, crypto, Buffer, http, querystring, util, path, fs, os, IonicConfig; var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = Array.prototype.slice; @@ -11,7 +11,6 @@ util = require('util'); es = require('event-stream'); fs = require('fs'); os = require('os'); -ionic = require('../ionic'); IonicConfig = require('./config'); /* @@ -515,7 +514,7 @@ module.exports = { var mixpanel = create_client('69f7271aa8f3d43f2e1b6baf698159b7'); -var ionicConfig = IonicConfig.getConfig(); +var ionicConfig = IonicConfig.loadConfig(); exports.IonicStats = { diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 31e963f8c7..c06eda379f 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -4,6 +4,7 @@ var fs = require('fs'), archiver = require('archiver'), argv = require('optimist').argv, FormData = require('form-data'), + IonicConfig = require('./config'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -15,7 +16,7 @@ IonicUploadTask.HELP_LINE = 'Upload an Ionic project.'; IonicUploadTask.prototype = new IonicTask(); IonicUploadTask.prototype.run = function(ionic, callback) { - var project = ionic.loadConfig(); + var project = IonicConfig.loadProject(); var login = new IonicLoginTask(); login.get(ionic, function(jar) { From f91d53db31f4cdc717d9b909c34091e05bce0be2 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 17 Feb 2014 17:21:44 -0600 Subject: [PATCH 067/850] Just move them to two different files --- lib/ionic/config.js | 51 +++--------------------------------- lib/ionic/login.js | 10 ++++---- lib/ionic/package.js | 38 +++++++++++++-------------- lib/ionic/project.js | 61 ++++++++++++++++++++++++++++++++++++++++++++ lib/ionic/start.js | 7 ++--- lib/ionic/stats.js | 2 +- lib/ionic/upload.js | 10 ++++---- 7 files changed, 98 insertions(+), 81 deletions(-) create mode 100644 lib/ionic/project.js diff --git a/lib/ionic/config.js b/lib/ionic/config.js index dafc63e9c7..541240d073 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -6,21 +6,7 @@ var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; module.exports = { CONFIG_FILE: '.ionic/ionic.config', - PROJECT_FILE: 'ionic.project', - PROJECT_DEFAULT: { - name: '', - email: '', - app_id: '', - package_name: '', - ios_certificate: '', - ios_certificate_password: '', - ios_profile: '', - android_keystore: '', - android_keystore_alias: '', - android_keystore_password: '', - android_key_password: '' - }, - loadConfig: function() { + load: function() { this.file = this.CONFIG_FILE; if(fs.existsSync(path.join(home,this.file))) { this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); @@ -29,23 +15,7 @@ module.exports = { } return this; }, - loadProject: function() { - this.file = this.PROJECT_FILE; - if(fs.existsSync(this.file)) { - this.data = JSON.parse(fs.readFileSync(this.file)) - } else { - console.error('Could not find ' + this.file + '!'+ - ' Please run this command in your root ionic project directory with that file.'); - } - return this; - }, - createProject: function(name) { - this.file = this.PROJECT_FILE; - this.data = this.PROJECT_DEFAULT; - this.data.name = name; - return this; - }, - saveConfig: function() { + save: function() { if(!this.data) { return; } @@ -61,17 +31,6 @@ module.exports = { console.error('Unable to save settings file:', e); } }, - saveProject: function(targetPath) { - if(!this.data) { - console.trace(); - console.error('This should never happen!'); - } - try { - fs.writeFileSync((targetPath?targetPath+'/':'')+this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); - } catch(e) { - console.error('Unable to save settings file:', e); - } - }, get: function(k) { return this.data[k]; }, @@ -81,10 +40,6 @@ module.exports = { } this.data[k] = v; - if(this.file == this.PROJECT_FILE) { - this.saveProject(); - } else { - this.saveConfig(); - } + this.saveConfig(); } }; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 245d996e9e..5567796ba4 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -2,7 +2,7 @@ var fs = require('fs'), request = require('request'), argv = require('optimist').argv, prompt = require('prompt'), - IonicConfig = require('./config'), + IonicProject = require('./project'), IonicTask = require('./task').IonicTask; var IonicLoginTask = function() { @@ -25,7 +25,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { required: true }]; - var project = IonicConfig.loadProject(); + var project = IonicProject.load(); // Grab the email for login if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { @@ -33,12 +33,12 @@ IonicLoginTask.prototype.run = function(ionic, callback) { schema.shift(); } // Assume project email is login email if it exists - else if(project.email && project.email != '') { - this.email = project.email; + else if(project.get('email')) { + this.email = project.get('email'); schema.shift(); } - console.log('Signup here! http://apps.ionicframework.com/signup'); + console.log('Signup here! '+ionic.IONIC_DASH+'signup'); prompt.override = argv; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 5a27ad71de..a8837fd976 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -4,7 +4,7 @@ var fs = require('fs'), argv = require('optimist').argv, prompt = require('prompt'), FormData = require('form-data'), - IonicConfig = require('./config'), + IonicProject = require('./project'), IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -44,7 +44,7 @@ IonicPackageTask.prototype.run = function(ionic) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - var project = IonicConfig.loadProject(); + var project = IonicProject.load(); for(var i = 0; i < platforms.length; i++) { var platform = platforms[i]; @@ -117,7 +117,7 @@ IonicPackageTask.prototype.run = function(ionic) { // Don't prompt for properties we already have in the config for (var property in properties) { - if(project[property]) { + if(project.get(property)) { delete properties[property]; } } @@ -129,17 +129,17 @@ IonicPackageTask.prototype.run = function(ionic) { // Overwrite any empty properties with prompt responses for (var property in properties) { - if(result[property] && !project[property]) { - project[property] = result[property]; + if(result[property] && !project.get(property)) { + project.set(property, result[property]); } } - ionic.saveConfig(project); + project.save(); console.log('Packaging '+platform+' app...'); var form = new FormData(); - form.append('email', project.email); - form.append('name', project.name); + form.append('email', project.get('email')); + form.append('name', project.get('name')); form.append('platform', platform); form.append('build_mode', mode); form.append('csrfmiddlewaretoken', jar.cookies[0].value); @@ -150,7 +150,7 @@ IonicPackageTask.prototype.run = function(ionic) { // console.log(property); // console.log(project[property]); if(property.indexOf(platform) == 0) { - form.append(property, project[property]); + form.append(property, project.get(property)); } } @@ -158,33 +158,33 @@ IonicPackageTask.prototype.run = function(ionic) { switch(platform) { case 'android': if(mode == 'release') { - var keystoreFilePath = path.resolve(project.android_keystore); + var keystoreFilePath = path.resolve(project.get('android_keystore')); if(fs.existsSync(keystoreFilePath)) { form.append('android_keystore_file', fs.createReadStream(keystoreFilePath), {filename: 'www.zip'}); } else { - delete project.android_keystore; - ionic.saveConfig(project); + project.remove('android_keystore'); + project.save(); process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); return; } } break; case 'ios': - var certificateFilePath = path.resolve(project.ios_certificate); + var certificateFilePath = path.resolve(project.get('ios_certificate')); if(fs.existsSync(certificateFilePath)) { form.append('ios_certificate_file', fs.createReadStream(certificateFilePath)); } else { - delete project.ios_certificate; - ionic.saveConfig(project); + project.remove('ios_certificate'); + project.save(); process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); return; } - var profileFilePath = path.resolve(project.ios_profile); + var profileFilePath = path.resolve(project.get('ios_profile')); if(fs.existsSync(profileFilePath)) { form.append('ios_profile_file', fs.createReadStream(profileFilePath)); } else { - delete project.ios_profile; - ionic.saveConfig(project); + project.remove('ios_profile'); + project.save(); process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); return; } @@ -195,7 +195,7 @@ IonicPackageTask.prototype.run = function(ionic) { break; } - var url = ionic.IONIC_DASH+'export/'+project.app_id; + var url = ionic.IONIC_DASH+'export/'+project.get('app_id'); var params = parseUrl(url); form.submit({ diff --git a/lib/ionic/project.js b/lib/ionic/project.js new file mode 100644 index 0000000000..e04027d52e --- /dev/null +++ b/lib/ionic/project.js @@ -0,0 +1,61 @@ +var fs = require('fs'), + path = require('path'), + ionic = require('../ionic'); + +module.exports = { + PROJECT_FILE: 'ionic.project', + PROJECT_DEFAULT: { + name: '', + email: '', + app_id: '', + package_name: '', + ios_certificate: '', + ios_certificate_password: '', + ios_profile: '', + android_keystore: '', + android_keystore_alias: '', + android_keystore_password: '', + android_key_password: '' + }, + load: function() { + this.file = this.PROJECT_FILE; + if(fs.existsSync(this.file)) { + this.data = JSON.parse(fs.readFileSync(this.file)) + } else { + console.error('Could not find ' + this.file + '!'+ + ' Please run this command in your root ionic project directory with that file.'); + } + return this; + }, + create: function(name) { + this.file = this.PROJECT_FILE; + this.data = this.PROJECT_DEFAULT; + return this; + }, + save: function(targetPath) { + if(!this.data) { + console.trace(); + console.error('This should never happen!'); + } + try { + fs.writeFileSync((targetPath?targetPath+'/':'')+this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); + } catch(e) { + console.error('Unable to save settings file:', e); + } + }, + get: function(k) { + return this.data[k]; + }, + set: function(k, v) { + if(!this.data) { + this.data = PROJECT_DEFAULT; + } + this.data[k] = v; + }, + remove: function(k) { + if(!this.data) { + this.data = PROJECT_DEFAULT; + } + this.data[k] = ''; + } +}; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index ac118768ec..ed6667d65a 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -6,7 +6,7 @@ var fs = require('fs'), shelljs = require('shelljs/global'), unzip = require('unzip'), argv = require('optimist').argv, - IonicConfig = require('./config'), + IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -102,8 +102,9 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { IonicStartTask.prototype._writeConfig = function(ionic) { console.log('Writing '+this.targetPath+'/ionic.config'); - var project = IonicConfig.createProject(this.appName); - project.saveProject(this.targetPath); + var project = IonicProject.create(); + project.set('name', this.appName); + project.save(this.targetPath); }; IonicStartTask.prototype._checkTargetPath = function() { diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index ed5313f429..b4823afbee 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -514,7 +514,7 @@ module.exports = { var mixpanel = create_client('69f7271aa8f3d43f2e1b6baf698159b7'); -var ionicConfig = IonicConfig.loadConfig(); +var ionicConfig = IonicConfig.load(); exports.IonicStats = { diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index c06eda379f..05148f3a79 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -4,7 +4,7 @@ var fs = require('fs'), archiver = require('archiver'), argv = require('optimist').argv, FormData = require('form-data'), - IonicConfig = require('./config'), + IonicProject = require('./project'), IonicTask = require('./task').IonicTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -16,7 +16,7 @@ IonicUploadTask.HELP_LINE = 'Upload an Ionic project.'; IonicUploadTask.prototype = new IonicTask(); IonicUploadTask.prototype.run = function(ionic, callback) { - var project = IonicConfig.loadProject(); + var project = IonicProject.load(); var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -47,7 +47,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); - var url = ionic.IONIC_DASH+'projects/'+(project.app_id?project.app_id:''); + var url = ionic.IONIC_DASH+'projects/'+project.get('app_id'); var params = parseUrl(url); form.submit({ @@ -68,8 +68,8 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(response.statusCode == 302) { var redirectPath = parseUrl(response.headers.location); - project.app_id = redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]; - ionic.saveConfig(project); + project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); + project.save(); if (callback) { callback(); From 751497cb69996acbff9a324c92e829740cdf9785 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 21 Feb 2014 16:39:02 -0600 Subject: [PATCH 068/850] Add name for Timmy --- lib/ionic.js | 2 +- lib/ionic/upload.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ionic.js b/lib/ionic.js index e5a80ae121..5aa09ba996 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -82,7 +82,7 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { - IONIC_DASH: 'http://apps.ionicframework.com/', + IONIC_DASH: 'http://virt/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 05148f3a79..0c292ffa9f 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -43,6 +43,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { console.log('Uploading...'); var form = new FormData(); + form.append('name', project.get('name')); form.append('csrfmiddlewaretoken', jar.cookies[0].value); form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); @@ -68,6 +69,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(response.statusCode == 302) { var redirectPath = parseUrl(response.headers.location); + console.log(redirectPath); project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); project.save(); From 69148a72ef3a595f95b4ef3dd509ae90e1bc61cf Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 21 Feb 2014 16:42:36 -0600 Subject: [PATCH 069/850] Fail when it can't find the project file --- lib/ionic/project.js | 6 +++--- lib/ionic/upload.js | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ionic/project.js b/lib/ionic/project.js index e04027d52e..e437226a73 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -18,11 +18,11 @@ module.exports = { android_key_password: '' }, load: function() { - this.file = this.PROJECT_FILE; - if(fs.existsSync(this.file)) { + this.file = this.PROJECT_FILE; + if(fs.existsSync(this.file)) { this.data = JSON.parse(fs.readFileSync(this.file)) } else { - console.error('Could not find ' + this.file + '!'+ + new Ionic().fail('Could not find ' + this.file + '!'+ ' Please run this command in your root ionic project directory with that file.'); } return this; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 0c292ffa9f..196d98992d 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -69,7 +69,6 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(response.statusCode == 302) { var redirectPath = parseUrl(response.headers.location); - console.log(redirectPath); project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); project.save(); From 6b23b40ef40594aff1ef0099ba8de7d06e77c2af Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 26 Feb 2014 17:20:28 -0600 Subject: [PATCH 070/850] Grab and upload plugins --- lib/ionic/package.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index a8837fd976..660b471acf 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -3,6 +3,7 @@ var fs = require('fs'), parseUrl = require('url').parse, argv = require('optimist').argv, prompt = require('prompt'), + shelljs = require('shelljs/global'), FormData = require('form-data'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask, @@ -144,6 +145,19 @@ IonicPackageTask.prototype.run = function(ionic) { form.append('build_mode', mode); form.append('csrfmiddlewaretoken', jar.cookies[0].value); + console.log('Grabbing plugins...'); + exec('cordova plugins', function(code, output) { + if(code != 0 ) { + process.stderr.write('Unable to read cordova plugin list. Please see console for more info.\n'); + } else { + output = output.replace(/'/g, '"'); + var plugins = JSON.parse(output); + for (var i = 0; i < plugins.length; i++) { + form.append('plugin_'+i, plugins[i]); + }; + } + }); + // Add the platform specific project properties to the post for (var property in project) { From 5609783ba407cfdfe4b78dc9ad166553dcbfa47e Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Fri, 28 Feb 2014 12:19:00 -0600 Subject: [PATCH 071/850] Whoops do the plugin grab sychronously --- lib/ionic.js | 2 +- lib/ionic/package.js | 30 ++++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 5aa09ba996..e5a80ae121 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -82,7 +82,7 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { - IONIC_DASH: 'http://virt/', + IONIC_DASH: 'http://apps.ionicframework.com/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 660b471acf..a695dc48bc 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -47,6 +47,16 @@ IonicPackageTask.prototype.run = function(ionic) { var project = IonicProject.load(); + console.log('Grabbing plugins...'); + var plugins = []; + var pluginExec = exec('cordova plugins'); + if(pluginExec.code != 0 ) { + process.stderr.write('Unable to read cordova plugin list. Please see console for more info.\n'); + } else { + pluginExec.output = pluginExec.output.replace(/'/g, '"'); + plugins = JSON.parse(pluginExec.output); + } + for(var i = 0; i < platforms.length; i++) { var platform = platforms[i]; @@ -145,24 +155,12 @@ IonicPackageTask.prototype.run = function(ionic) { form.append('build_mode', mode); form.append('csrfmiddlewaretoken', jar.cookies[0].value); - console.log('Grabbing plugins...'); - exec('cordova plugins', function(code, output) { - if(code != 0 ) { - process.stderr.write('Unable to read cordova plugin list. Please see console for more info.\n'); - } else { - output = output.replace(/'/g, '"'); - var plugins = JSON.parse(output); - for (var i = 0; i < plugins.length; i++) { - form.append('plugin_'+i, plugins[i]); - }; - } - }); - + for (var i = 0; i < plugins.length; i++) { + form.append('plugin_'+i, plugins[i]); + }; // Add the platform specific project properties to the post for (var property in project) { - // console.log(property); - // console.log(project[property]); if(property.indexOf(platform) == 0) { form.append(property, project.get(property)); } @@ -236,7 +234,7 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail("Error packaging: " + err); } console.log('Done'); - }); + }); }); } }); From b0438e30e32c0bc165812dfa951f4c3c26af06df Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 3 Mar 2014 12:35:21 -0600 Subject: [PATCH 072/850] Why wasn't this ever committed? --- lib/ionic/config.js | 2 +- lib/ionic/package.js | 8 ++++---- lib/ionic/project.js | 6 +++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/ionic/config.js b/lib/ionic/config.js index 541240d073..b1c2e648e6 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -40,6 +40,6 @@ module.exports = { } this.data[k] = v; - this.saveConfig(); + this.save(); } }; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index a695dc48bc..f555ef577f 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -39,8 +39,8 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } - var upload = new IonicUploadTask(); - upload.run(ionic, function() { + //var upload = new IonicUploadTask(); + //upload.run(ionic, function() { var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -160,7 +160,7 @@ IonicPackageTask.prototype.run = function(ionic) { }; // Add the platform specific project properties to the post - for (var property in project) { + for (var property in project.get()) { if(property.indexOf(platform) == 0) { form.append(property, project.get(property)); } @@ -238,7 +238,7 @@ IonicPackageTask.prototype.run = function(ionic) { }); } }); - }); + //}); }; exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/project.js b/lib/ionic/project.js index e437226a73..c227284b10 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -44,7 +44,11 @@ module.exports = { } }, get: function(k) { - return this.data[k]; + if(k) { + return this.data[k]; + } else { + return this.data; + } }, set: function(k, v) { if(!this.data) { From 1f27d375f2834028dfe3152c06f1ce0e61494737 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 3 Mar 2014 12:41:09 -0600 Subject: [PATCH 073/850] Tim's wish is my command --- lib/ionic/login.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 5567796ba4..5064e38eab 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -39,6 +39,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { } console.log('Signup here! '+ionic.IONIC_DASH+'signup'); + console.log('Login Info:'); prompt.override = argv; From 001d4d43042ea2ae291febf22435ad5dcf9f5a31 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 3 Mar 2014 16:20:51 -0600 Subject: [PATCH 074/850] Should upload when packaging --- lib/ionic/package.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index f555ef577f..bf66b47b42 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -39,8 +39,8 @@ IonicPackageTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } - //var upload = new IonicUploadTask(); - //upload.run(ionic, function() { + var upload = new IonicUploadTask(); + upload.run(ionic, function() { var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -238,7 +238,7 @@ IonicPackageTask.prototype.run = function(ionic) { }); } }); - //}); + }); }; exports.IonicPackageTask = IonicPackageTask; From b8af9dd2b5c7de9c631b05b36bd5850afd1d1e8f Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 10 Mar 2014 14:37:00 -0500 Subject: [PATCH 075/850] Ignore add keyword for platform --- lib/ionic/platform.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js index d8a1a76d99..671c76ff8a 100644 --- a/lib/ionic/platform.js +++ b/lib/ionic/platform.js @@ -33,10 +33,14 @@ IonicPlatformTask.prototype.run = function(ionic) { ionic.fail('No platforms specified, exiting.'); } + if(platforms[0].toLowerCase() == 'add') { + platforms.shift(); + } + IonicStats.t('platform', { 'platform': platforms.join(',') }); for(var i = 0; i < platforms.length; i++) { - var platform = platforms[i]; + var platform = platforms[i].toLowerCase(); console.log('Adding platform', platform); if(exec("cordova platform add " + platform).code !== 0) { process.stderr.write('Unable to add platform ' + platform + '. Please see console for more info.\n'); From 477e79456fd5088388f1c820f9abbcc940413156 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Fri, 21 Mar 2014 14:48:35 -0500 Subject: [PATCH 076/850] Added support for starter project naming --- lib/ionic.js | 2 +- lib/ionic/config.js | 2 +- lib/ionic/login.js | 11 ++++++----- lib/ionic/start.js | 29 ++++++++++++++++++++--------- lib/ionic/upload.js | 3 +++ 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 5aa09ba996..e5a80ae121 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -82,7 +82,7 @@ var TASKS = [ Ionic = function() {}; Ionic.prototype = { - IONIC_DASH: 'http://virt/', + IONIC_DASH: 'http://apps.ionicframework.com/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/config.js b/lib/ionic/config.js index 541240d073..b1c2e648e6 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -40,6 +40,6 @@ module.exports = { } this.data[k] = v; - this.saveConfig(); + this.save(); } }; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 5567796ba4..41fd38e57b 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -17,7 +17,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { var schema = [{ name: 'email', pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, - message: 'Email for Ionic Studio login', + message: 'Email for Ionic Apps login', required: true }, { name: 'password', @@ -38,12 +38,13 @@ IonicLoginTask.prototype.run = function(ionic, callback) { schema.shift(); } - console.log('Signup here! '+ionic.IONIC_DASH+'signup'); + console.log('To continue, please login to your Ionic Apps account (Create a free account here: ' + ionic.IONIC_DASH + 'signup)'); prompt.override = argv; prompt.start(); + prompt.get(schema, function (err, result) { if(err) { ionic.fail('Error logging in: ' + err); @@ -60,7 +61,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { var jar = request.jar(); request({ - url: ionic.IONIC_DASH+'login', + url: ionic.IONIC_DASH + 'login', jar: jar }, function(err, response, body) { @@ -70,7 +71,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { request({ method: 'POST', - url: ionic.IONIC_DASH+'login', + url: ionic.IONIC_DASH + 'login', jar: jar, form: { username: self.email, @@ -84,7 +85,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { } // Should be a 304 redirect status code if correct if(response.statusCode == 200) { - ionic.fail('Email or Password incorrect. Please visit '+ionic.IONIC_DASH+' for help. :)') + ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.') } var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index ed6667d65a..09b615ff8a 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -43,6 +43,8 @@ IonicStartTask.prototype.run = function(ionic) { // Grab the target path from the command line, or use this as the app name var targetPathName = argv._[2] || this.appName; + var starterProject = argv._[3] || 'tabs'; + this.targetPath = path.resolve(this.appName); // Make sure to create this, or ask them if they want to override it @@ -51,23 +53,30 @@ IonicStartTask.prototype.run = function(ionic) { process.exit(1); } - console.log('Creating Ionic app in folder', this.targetPath); + console.log('Creating Ionic app in folder', this.targetPath, 'based on', starterProject, 'project'); fs.mkdirSync(this.targetPath); - this._fetchAndWriteSeed(); + this._fetchAndWriteSeed(starterProject); this._writeConfig(ionic); }; -IonicStartTask.prototype._fetchAndWriteSeed = function() { +IonicStartTask.prototype._getStarterUrl = function(repo) { + return 'https://github.com/driftyco/' + repo + '/archive/master.zip' ; +}; + +IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var self = this; - var templateUrl = 'https://github.com/driftyco/ionic-angular-cordova-seed/archive/master.zip' ; + var repoName = 'ionic-starter-' + projectType; + var repoFolderName = repoName + '-master'; + var templateUrl = this._getStarterUrl(repoName); + console.log('Downloading starter template from', templateUrl); var tmpFolder = os.tmpdir(); - var tempZipFilePath = path.join(tmpFolder, 'ionic-angular-cordova-seed' + new Date().getTime() + '.zip'); + var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); var tempZipFileStream = fs.createWriteStream(tempZipFilePath) var unzipRepo = function(fileName) { @@ -76,8 +85,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { var writeStream = unzip.Extract({ path: self.targetPath }); writeStream.on('close', function() { //fs.renameSync(self.targetPath + '/' + 'ionic-angular-cordova-seed-master', self.targetPath + '/app'); - cp('-R', self.targetPath + '/' + 'ionic-angular-cordova-seed-master/.', self.targetPath); - rm('-rf', self.targetPath + '/' + 'ionic-angular-cordova-seed-master/'); + cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); console.log('Project created!'); cd(self.targetPath); @@ -93,6 +102,10 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { }; request({ url: templateUrl, encoding: null }, function(err, res, body) { + if(res.statusCode !== 200) { + console.log('Unable to fetch project: HTTP', res.statusCode); + return; + } tempZipFileStream.write(body); tempZipFileStream.close(); unzipRepo(tempZipFilePath); @@ -100,8 +113,6 @@ IonicStartTask.prototype._fetchAndWriteSeed = function() { }; IonicStartTask.prototype._writeConfig = function(ionic) { - console.log('Writing '+this.targetPath+'/ionic.config'); - var project = IonicProject.create(); project.set('name', this.appName); project.save(this.targetPath); diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 196d98992d..7378de53a1 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -6,6 +6,7 @@ var fs = require('fs'), FormData = require('form-data'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats, IonicLoginTask = require('./login').IonicLoginTask; var IonicUploadTask = function() { @@ -23,6 +24,8 @@ IonicUploadTask.prototype.run = function(ionic, callback) { console.log('Zipping...'); + IonicStats.t('upload', {}); + var zip = fs.createWriteStream('www.zip'); var archive = archiver('zip'); From 41cf47dfd3e289c5cf808b1bfec90d577cf4a021 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 12:42:25 -0500 Subject: [PATCH 077/850] Updated ascii art and added ability to specify starter project --- lib/ionic.js | 14 ++++++++++++-- lib/ionic/start.js | 11 ++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index e5a80ae121..41a59c0ab9 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -125,8 +125,17 @@ Ionic.prototype = { }, _printIonic: function() { - process.stdout.write('\n __ __ \n'); - process.stdout.write('| / \\ |\\ | | / `\n' + '| \\__/ | \\| | \\__,\n\n'); + var w = function(s) { + process.stdout.write(s); + }; + + w(' _ _ \n'); + w(' (_) (_) \n'); + w(' _ ___ _ __ _ ___ \n'); + w(' | |/ _ \\| \'_ \\| |/ __|\n'); + w(' | | (_) | | | | | (__ \n'); + w(' |_|\\___/|_| |_|_|\\___|\n'); + }, _loadTaskRunner: function(which) { @@ -146,6 +155,7 @@ Ionic.prototype = { }, fail: function(msg) { + process.stderr.write('Error, exiting:'); process.stderr.write(msg + '\n'); process.exit(1); } diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 09b615ff8a..128cc98d9e 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -32,6 +32,10 @@ IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; IonicStartTask.prototype = new IonicTask(); +IonicStartTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic start appName [starterProject(blank,tabs,sidemenu)]\n'); +}; + IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { ionic.fail('No app name specified, exiting.'); @@ -41,9 +45,9 @@ IonicStartTask.prototype.run = function(ionic) { this.appName = argv._[1]; // Grab the target path from the command line, or use this as the app name - var targetPathName = argv._[2] || this.appName; + var targetPathName = this.appName; - var starterProject = argv._[3] || 'tabs'; + var starterProject = argv._[2] || 'tabs'; this.targetPath = path.resolve(this.appName); @@ -103,7 +107,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { request({ url: templateUrl, encoding: null }, function(err, res, body) { if(res.statusCode !== 200) { - console.log('Unable to fetch project: HTTP', res.statusCode); + console.error('Error: Unable to fetch project: HTTP', res.statusCode); + console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'); return; } tempZipFileStream.write(body); From 035114ae6dede65aff3fb0475eab877cccc08f95 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 16:40:33 -0500 Subject: [PATCH 078/850] New starter project sourcing --- bin/ionic | 3 +- lib/ionic.js | 68 ++++++++++++++++++++++++++--- lib/ionic/start.js | 105 +++++++++++++++++++++++++++++++-------------- package.json | 8 ++-- 4 files changed, 140 insertions(+), 44 deletions(-) diff --git a/bin/ionic b/bin/ionic index 171649cb21..3b444affe9 100755 --- a/bin/ionic +++ b/bin/ionic @@ -7,5 +7,4 @@ process.title = 'ionic'; var Ionic = require('../lib/ionic').Ionic; -var ionic = new Ionic(); -ionic.run(); +Ionic.run(); diff --git a/lib/ionic.js b/lib/ionic.js index 41a59c0ab9..e2d3e406a8 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -21,7 +21,29 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicBuildTask = require('./ionic/build').IonicBuildTask, IonicLoginTask = require('./ionic/login').IonicLoginTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, - IonicPackageTask = require('./ionic/package').IonicPackageTask; + IonicPackageTask = require('./ionic/package').IonicPackageTask, + path = require('path'), + request = require('request'), + os = require('os'), + unzip = require('unzip'), + colors = require('colors'), + Q = require('q'); + + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + small: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'white', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + var fs = require('fs'), argv = require('optimist').argv; @@ -79,9 +101,7 @@ var TASKS = [ } ]; -Ionic = function() {}; - -Ionic.prototype = { +Ionic = { IONIC_DASH: 'http://apps.ionicframework.com/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', @@ -148,7 +168,7 @@ Ionic.prototype = { return this._printGenericUsage(); } - console.log('Running', task.title, 'task...') + console.log('Running', task.title.info.bold, 'task...') var taskObj = new task.task(); taskObj.run(this); @@ -158,8 +178,44 @@ Ionic.prototype = { process.stderr.write('Error, exiting:'); process.stderr.write(msg + '\n'); process.exit(1); - } + }, + + /** + * Fetch a repo from GitHub, unzip it to a specific folder. + */ + fetchRepo: function(targetPath, repoName, repoUrl) { + var q = Q.defer(); + + // The folder name the project will be downloaded and extracted to + var repoFolderName = repoName + '-master'; + console.log('Fetching repo:', repoUrl); + + var tmpFolder = os.tmpdir(); + var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); + var tempZipFileStream = fs.createWriteStream(tempZipFilePath) + var unzipRepo = function(fileName) { + var readStream = fs.createReadStream(fileName); + + var writeStream = unzip.Extract({ path: targetPath }); + writeStream.on('close', function() { + q.resolve(repoFolderName); + }); + readStream.pipe(writeStream); + }; + + request({ url: repoUrl, encoding: null }, function(err, res, body) { + if(res.statusCode !== 200) { + q.reject(res); + return; + } + tempZipFileStream.write(body); + tempZipFileStream.close(); + unzipRepo(tempZipFilePath); + }); + + return q.promise; + } }; exports.Ionic = Ionic; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 128cc98d9e..a07f8b359b 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -6,6 +6,9 @@ var fs = require('fs'), shelljs = require('shelljs/global'), unzip = require('unzip'), argv = require('optimist').argv, + colors = require('colors'), + Q = require('q'), + IonicProject = require('../ionic'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -28,6 +31,9 @@ fs.mkdirParent = function(dirPath, mode, callback) { var IonicStartTask = function() { } +// The URL for the cordova wrapper project +IonicStartTask.WRAPPER_REPO_NAME = 'ionic-cordova-wrapper'; + IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; IonicStartTask.prototype = new IonicTask(); @@ -53,11 +59,11 @@ IonicStartTask.prototype.run = function(ionic) { // Make sure to create this, or ask them if they want to override it if(this._checkTargetPath() === false) { - process.stderr.write('Exiting.\n'); + process.stderr.write('\nExiting.\n'); process.exit(1); } - console.log('Creating Ionic app in folder', this.targetPath, 'based on', starterProject, 'project'); + console.log('Creating Ionic app in folder', this.targetPath, 'based on', starterProject.info.bold, 'project'); fs.mkdirSync(this.targetPath); @@ -70,51 +76,84 @@ IonicStartTask.prototype._getStarterUrl = function(repo) { return 'https://github.com/driftyco/' + repo + '/archive/master.zip' ; }; +IonicStartTask.prototype._fetchWrapper = function() { + var q = Q.defer(); + var self = this; + + var repoName = IonicStartTask.WRAPPER_REPO_NAME; + var repoUrl = 'https://github.com/driftyco/' + IonicStartTask.WRAPPER_REPO_NAME + '/archive/master.zip'; + console.log('Fetching', 'Cordova'.info.bold, 'wrapper'); + + Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { + cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); + cd(self.targetPath); + + q.resolve(self.targetPath); + }, function(err) { + q.reject(err); + }); + + return q.promise; +}; + IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var self = this; - var repoName = 'ionic-starter-' + projectType; - var repoFolderName = repoName + '-master'; - var templateUrl = this._getStarterUrl(repoName); + // First, grab the wrapper project. - console.log('Downloading starter template from', templateUrl); + var wrapperPromise = this._fetchWrapper(); - var tmpFolder = os.tmpdir(); - var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); - var tempZipFileStream = fs.createWriteStream(tempZipFilePath) + wrapperPromise.then(function(targetPath) { + // Get the starter project repo name: + var repoName = 'ionic-starter-' + projectType; - var unzipRepo = function(fileName) { - var readStream = fs.createReadStream(fileName); + // The folder name the project will be downloaded and extracted to + var repoFolderName = repoName + '-master'; - var writeStream = unzip.Extract({ path: self.targetPath }); - writeStream.on('close', function() { - //fs.renameSync(self.targetPath + '/' + 'ionic-angular-cordova-seed-master', self.targetPath + '/app'); - cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); - rm('-rf', self.targetPath + '/' + repoFolderName + '/'); - console.log('Project created!'); + // Get the URL for the starter project repo: + var repoUrl = self._getStarterUrl(repoName); - cd(self.targetPath); - console.log('Initializing cordova project.'); + Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { + // Move the content of this repo into the www folder + cp('-R', targetPath + '/' + repoFolderName + '/.', 'www'); + + // Copy the root config file to the www folder + cp(targetPath + '/config.xml', 'www'); + + // Clean up start template folder + rm('-rf', targetPath + '/' + repoFolderName + '/'); + + console.log('Initializing cordova project.'.info.bold); if(!exec('cordova plugin add org.apache.cordova.device') || !exec('cordova plugin add org.apache.cordova.console') || !exec('cordova plugin add org.apache.cordova.statusbar')) { - process.stderr.write('Unable to install one or more cordova plugins.\n'); + process.stderr.write('Unable to install one or more cordova plugins.\n'.error.bold); } + self._printQuickHelp(); + IonicStats.t('start', {}); + }, function(err) { + console.error('Error: Unable to fetch project: HTTP'.error.bold, res.statusCode); + console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'.error.bold); + Ionic.fail(''); }); - readStream.pipe(writeStream); - }; - - request({ url: templateUrl, encoding: null }, function(err, res, body) { - if(res.statusCode !== 200) { - console.error('Error: Unable to fetch project: HTTP', res.statusCode); - console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'); - return; - } - tempZipFileStream.write(body); - tempZipFileStream.close(); - unzipRepo(tempZipFilePath); + + }, function(err) { + Ionic.fail('Unable to grab wrapper project:'.error.bold, err); }); + +}; + +IonicStartTask.prototype._printQuickHelp = function() { + console.log('\nYour Ionic project is ready to go!'.green.bold); + console.log('\nSome quick tips:'); + console.log(' * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); + console.log(' Note: iOS development requires OS X currently'.small); + console.log('\n * To build your project, run', 'ionic build [platform]'.info.bold); + console.log('\n * To emulate your project in a simulator or emulator, run', 'ionic emulate [platform]'.info.bold); + console.log('\n * To run your project on a device, run', 'ionic run [platform]'.info.bold); + console.log('\n\nFor more help, visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold); }; IonicStartTask.prototype._writeConfig = function(ionic) { @@ -125,7 +164,7 @@ IonicStartTask.prototype._writeConfig = function(ionic) { IonicStartTask.prototype._checkTargetPath = function() { if(fs.existsSync(this.targetPath)) { - process.stderr.write('The directory ' + this.targetPath + ' already exists, please remove it if you would like to create a new ionic project there.\n'); + process.stderr.write('The directory '.error.bold + this.targetPath + ' already exists, please remove it if you would like to create a new ionic project there.\n'.error.bold); return false; } return true; diff --git a/package.json b/package.json index f6598e9c05..1ba7e6295f 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,16 @@ "license": "MIT", "dependencies": { "archiver": "0.5.1", - "cordova": "~3.2.0", - "event-stream": "3.0.x", + "cordova": "~3.2.0", + "event-stream": "3.0.x", "form-data": "~0.1.0", "ncp": "0.4.2", "optimist": "0.6.0", "prompt": "0.2.12", "request": "2.27.0", "shelljs": "0.2.6", - "unzip": "0.1.9" + "unzip": "0.1.9", + "q": "^1.0.1", + "colors": "^0.6.2" } } From 79c4842421c77fecae36c5e1f7e602ff4f6f7a6a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 16:53:24 -0500 Subject: [PATCH 079/850] Updated package --- package.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/package.json b/package.json index 1ba7e6295f..d276025bc6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "0.9.16", + "version": "1.0.0-beta", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -19,14 +19,10 @@ "type": "git", "url": "https://github.com/driftyco/ionic-cli.git" }, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, "author": "Max Lynch and Peter Collins ", "license": "MIT", "dependencies": { "archiver": "0.5.1", - "cordova": "~3.2.0", "event-stream": "3.0.x", "form-data": "~0.1.0", "ncp": "0.4.2", From c33048227d34aeaf0741e0615326e67eb786531c Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 16:55:03 -0500 Subject: [PATCH 080/850] Added note --- lib/ionic/start.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index a07f8b359b..3e8019be36 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -150,6 +150,7 @@ IonicStartTask.prototype._printQuickHelp = function() { console.log('\nSome quick tips:'); console.log(' * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); + console.log('\n * cd into your project directory before running any of the following commands'.info.bold); console.log('\n * To build your project, run', 'ionic build [platform]'.info.bold); console.log('\n * To emulate your project in a simulator or emulator, run', 'ionic emulate [platform]'.info.bold); console.log('\n * To run your project on a device, run', 'ionic run [platform]'.info.bold); From 9c4b9eeee815e61e7cede5f6953b44b9c1a9f4ab Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 16:58:17 -0500 Subject: [PATCH 081/850] Added note --- lib/ionic/start.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 3e8019be36..1cc218e738 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -130,7 +130,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { process.stderr.write('Unable to install one or more cordova plugins.\n'.error.bold); } - self._printQuickHelp(); + self._printQuickHelp(targetPath); IonicStats.t('start', {}); }, function(err) { @@ -145,12 +145,12 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { }; -IonicStartTask.prototype._printQuickHelp = function() { +IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\nYour Ionic project is ready to go!'.green.bold); console.log('\nSome quick tips:'); + console.log('\n * cd into your project directory before running any of the following commands', ('(cd ' + projectDirectory + ')').info.bold); console.log(' * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); - console.log('\n * cd into your project directory before running any of the following commands'.info.bold); console.log('\n * To build your project, run', 'ionic build [platform]'.info.bold); console.log('\n * To emulate your project in a simulator or emulator, run', 'ionic emulate [platform]'.info.bold); console.log('\n * To run your project on a device, run', 'ionic run [platform]'.info.bold); From 915fab6957e9a329010038ef7706dabdb8787256 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 16:59:47 -0500 Subject: [PATCH 082/850] Added note --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 1cc218e738..2651f8b484 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -130,7 +130,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { process.stderr.write('Unable to install one or more cordova plugins.\n'.error.bold); } - self._printQuickHelp(targetPath); + self._printQuickHelp(self.targetPath); IonicStats.t('start', {}); }, function(err) { From 1baed22745eb99fa8cafcea1c18491836bcb0082 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 17:01:00 -0500 Subject: [PATCH 083/850] Added note --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 2651f8b484..4c70aa52e4 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -130,7 +130,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { process.stderr.write('Unable to install one or more cordova plugins.\n'.error.bold); } - self._printQuickHelp(self.targetPath); + self._printQuickHelp(self.appName); IonicStats.t('start', {}); }, function(err) { From d9e40ff0f77937df0739ff55469b4c60cf025555 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 24 Mar 2014 17:16:18 -0500 Subject: [PATCH 084/850] Updated --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 4c70aa52e4..2a0942f7bf 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -149,7 +149,7 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\nYour Ionic project is ready to go!'.green.bold); console.log('\nSome quick tips:'); console.log('\n * cd into your project directory before running any of the following commands', ('(cd ' + projectDirectory + ')').info.bold); - console.log(' * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); + console.log('\n * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); console.log('\n * To build your project, run', 'ionic build [platform]'.info.bold); console.log('\n * To emulate your project in a simulator or emulator, run', 'ionic emulate [platform]'.info.bold); From a297872e673aa8d479b390806d548d7178df86dd Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 00:45:18 -0500 Subject: [PATCH 085/850] Moved to base project --- lib/ionic.js | 4 ++-- lib/ionic/start.js | 37 ++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index e2d3e406a8..f8d4ee9481 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -175,8 +175,8 @@ Ionic = { }, fail: function(msg) { - process.stderr.write('Error, exiting:'); - process.stderr.write(msg + '\n'); + process.stderr.write('ERROR: '); + process.stderr.write(msg.error.bold + '\nExiting.\n'); process.exit(1); }, diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 2a0942f7bf..6d79baaeb9 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -32,7 +32,7 @@ var IonicStartTask = function() { } // The URL for the cordova wrapper project -IonicStartTask.WRAPPER_REPO_NAME = 'ionic-cordova-wrapper'; +IonicStartTask.WRAPPER_REPO_NAME = 'ionic-app-base'; IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; @@ -104,7 +104,11 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var wrapperPromise = this._fetchWrapper(); - wrapperPromise.then(function(targetPath) { + wrapperPromise.then(function() { + exec('npm install'); + exec('gulp bootstrap --sass'); + }) + .then(function() { // Get the starter project repo name: var repoName = 'ionic-starter-' + projectType; @@ -115,22 +119,33 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var repoUrl = self._getStarterUrl(repoName); Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { + var pluginQ = Q.defer(); + // Move the content of this repo into the www folder - cp('-R', targetPath + '/' + repoFolderName + '/.', 'www'); + cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); // Copy the root config file to the www folder - cp(targetPath + '/config.xml', 'www'); + cp(self.targetPath + '/config.xml', 'www'); // Clean up start template folder - rm('-rf', targetPath + '/' + repoFolderName + '/'); + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); console.log('Initializing cordova project.'.info.bold); - if(!exec('cordova plugin add org.apache.cordova.device') || !exec('cordova plugin add org.apache.cordova.console') || - !exec('cordova plugin add org.apache.cordova.statusbar')) { - process.stderr.write('Unable to install one or more cordova plugins.\n'.error.bold); - } - - self._printQuickHelp(self.appName); + exec('cordova plugin add org.apache.cordova.device && ' + + 'cordova plugin add org.apache.cordova.console && ' + + 'cordova plugin add org.apache.cordova.statusbar', function(err, stdout, stderr) { + if(err) { + pluginQ.reject(stderr); + } else { + pluginQ.resolve(stdout); + } + }) + + pluginQ.promise.then(function() { + self._printQuickHelp(self.appName); + }, function(err) { + Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); + }); IonicStats.t('start', {}); }, function(err) { From c75e86049451701ad24ac827ef2ef33fa7bf57fa Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 00:59:30 -0500 Subject: [PATCH 086/850] Tweaked install order, fixed error handler --- lib/ionic/start.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 6d79baaeb9..f9d708ed17 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -105,10 +105,6 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var wrapperPromise = this._fetchWrapper(); wrapperPromise.then(function() { - exec('npm install'); - exec('gulp bootstrap --sass'); - }) - .then(function() { // Get the starter project repo name: var repoName = 'ionic-starter-' + projectType; @@ -121,6 +117,9 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { var pluginQ = Q.defer(); + exec('npm install'); + exec('gulp bootstrap --sass'); + // Move the content of this repo into the www folder cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); @@ -148,8 +147,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { }); IonicStats.t('start', {}); - }, function(err) { - console.error('Error: Unable to fetch project: HTTP'.error.bold, res.statusCode); + }).catch(function(err) { + console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode); console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'.error.bold); Ionic.fail(''); }); From 34e506b2054da92ba6094061de03604af9695a79 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 10:07:33 -0500 Subject: [PATCH 087/850] Run init instead of bootstrap --- lib/ionic/start.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index f9d708ed17..f2e35398c6 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -117,8 +117,9 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { var pluginQ = Q.defer(); + // Install dependencies for the starter project exec('npm install'); - exec('gulp bootstrap --sass'); + exec('gulp init --sass'); // Move the content of this repo into the www folder cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); From 48af5213f38d647eb6c3a155ee954fdfe8978c90 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 15:56:55 -0500 Subject: [PATCH 088/850] Delay release of login stuff --- lib/ionic.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ionic.js b/lib/ionic.js index f8d4ee9481..f8dbeccfc2 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -79,6 +79,7 @@ var TASKS = [ usage: 'platform', task: IonicPlatformTask }, + /* { title: 'login', name: 'login', @@ -99,6 +100,7 @@ var TASKS = [ usage: 'mode platform', task: IonicPackageTask } + */ ]; Ionic = { From ea41deb4e3daa2f7890ab7dcae071da7666fb588 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 22:47:24 -0500 Subject: [PATCH 089/850] Fixed upload task --- lib/ionic.js | 5 ++--- lib/ionic/login.js | 6 +++--- lib/ionic/package.js | 14 +++++++------- lib/ionic/project.js | 6 +++--- lib/ionic/upload.js | 23 ++++++++++++++++++----- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index f8dbeccfc2..50e25c698b 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -79,7 +79,6 @@ var TASKS = [ usage: 'platform', task: IonicPlatformTask }, - /* { title: 'login', name: 'login', @@ -100,11 +99,11 @@ var TASKS = [ usage: 'mode platform', task: IonicPackageTask } - */ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com/', + //IONIC_DASH: 'http://apps.ionicframework.com/', + IONIC_DASH: 'http://127.0.0.1:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 41fd38e57b..1b11ea70b0 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -8,7 +8,7 @@ var fs = require('fs'), var IonicLoginTask = function() { } -IonicLoginTask.HELP_LINE = 'Login to Ionic Studio'; +IonicLoginTask.HELP_LINE = 'Login to the Ionic Platform'; IonicLoginTask.prototype = new IonicTask(); @@ -17,7 +17,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { var schema = [{ name: 'email', pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, - message: 'Email for Ionic Apps login', + message: 'Email for your Ionic Platform login', required: true }, { name: 'password', @@ -38,7 +38,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { schema.shift(); } - console.log('To continue, please login to your Ionic Apps account (Create a free account here: ' + ionic.IONIC_DASH + 'signup)'); + console.log('To continue, please login to your Ionic Platform account (Create a free account here: ' + ionic.IONIC_DASH + 'signup)'); prompt.override = argv; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index bf66b47b42..0a958a33be 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -13,7 +13,7 @@ var fs = require('fs'), var IonicPackageTask = function() { } -IonicPackageTask.HELP_LINE = 'Package an Ionic project for the given plaform.'; +IonicPackageTask.HELP_LINE = 'Package an Ionic project using the Ionic Platform Build service (requires login)'; IonicPackageTask.prototype = new IonicTask(); @@ -146,7 +146,7 @@ IonicPackageTask.prototype.run = function(ionic) { } project.save(); - console.log('Packaging '+platform+' app...'); + console.log('Packaging ' + platform + ' app...'); var form = new FormData(); form.append('email', project.get('email')); @@ -156,7 +156,7 @@ IonicPackageTask.prototype.run = function(ionic) { form.append('csrfmiddlewaretoken', jar.cookies[0].value); for (var i = 0; i < plugins.length; i++) { - form.append('plugin_'+i, plugins[i]); + form.append('plugin_' + i, plugins[i]); }; // Add the platform specific project properties to the post @@ -176,7 +176,7 @@ IonicPackageTask.prototype.run = function(ionic) { } else { project.remove('android_keystore'); project.save(); - process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); + process.stderr.write('\nCan\'t find file: "' + keystoreFilePath + '"\nSkipping build..."\n\n'); return; } } @@ -188,7 +188,7 @@ IonicPackageTask.prototype.run = function(ionic) { } else { project.remove('ios_certificate'); project.save(); - process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); + process.stderr.write('\nCan\'t find file: "' + certificateFilePath + '"\nSkipping build..."\n\n'); return; } var profileFilePath = path.resolve(project.get('ios_profile')); @@ -197,13 +197,13 @@ IonicPackageTask.prototype.run = function(ionic) { } else { project.remove('ios_profile'); project.save(); - process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); + process.stderr.write('\nCan\'t find file: "' + profileFilePath + '"\nSkipping build..."\n\n'); return; } break; default: console.trace(); - process.stderr.write('\nUnknown platform: "'+platform+'"\nWe should never get here"\n\n'); + process.stderr.write('\nUnknown platform: "' + platform + '"\nWe should never get here"\n\n'); break; } diff --git a/lib/ionic/project.js b/lib/ionic/project.js index c227284b10..36a6f246bb 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -22,8 +22,8 @@ module.exports = { if(fs.existsSync(this.file)) { this.data = JSON.parse(fs.readFileSync(this.file)) } else { - new Ionic().fail('Could not find ' + this.file + '!'+ - ' Please run this command in your root ionic project directory with that file.'); + Ionic.fail('Could not find your ' + this.file + ' file!'+ + ' Please run this command in the root of your ionic project.'); } return this; }, @@ -38,7 +38,7 @@ module.exports = { console.error('This should never happen!'); } try { - fs.writeFileSync((targetPath?targetPath+'/':'')+this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); + fs.writeFileSync((targetPath?targetPath + '/':'') + this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); } catch(e) { console.error('Unable to save settings file:', e); } diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 7378de53a1..a170318251 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -7,17 +7,19 @@ var fs = require('fs'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats, - IonicLoginTask = require('./login').IonicLoginTask; + IonicLoginTask = require('./login').IonicLoginTask, + Q = require('q'); var IonicUploadTask = function() { } -IonicUploadTask.HELP_LINE = 'Upload an Ionic project.'; +IonicUploadTask.HELP_LINE = 'Upload an Ionic project to the Ionic Platform (requires login)'; IonicUploadTask.prototype = new IonicTask(); IonicUploadTask.prototype.run = function(ionic, callback) { var project = IonicProject.load(); + var q = Q.defer(); var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -51,7 +53,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); - var url = ionic.IONIC_DASH+'projects/'+project.get('app_id'); + var url = ionic.IONIC_DASH + 'projects/' + project.get('app_id'); var params = parseUrl(url); form.submit({ @@ -67,9 +69,9 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(err) { ionic.fail("Error uploading: " + err); } - - console.log('Done'); + console.log('Done uploading'.info.bold); + if(response.statusCode == 302) { var redirectPath = parseUrl(response.headers.location); project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); @@ -78,10 +80,21 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if (callback) { callback(); }; + } else { + callback && callback(); } + + q.resolve(callback); }); }); }); + + q.promise.then(function(callback) { + // Exit if there was no callback + if(!callback) { + process.exit(0); + } + }); }; exports.IonicUploadTask = IonicUploadTask; From 735a2fe870a2663810e200694af3c13faa14bff5 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 23:04:54 -0500 Subject: [PATCH 090/850] Spacing around quotes --- lib/ionic/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 0a958a33be..8213893389 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -207,7 +207,7 @@ IonicPackageTask.prototype.run = function(ionic) { break; } - var url = ionic.IONIC_DASH+'export/'+project.get('app_id'); + var url = ionic.IONIC_DASH + 'export/' + project.get('app_id'); var params = parseUrl(url); form.submit({ From cbd212092f1398ef82994e11b6dafdc98afbcb97 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 25 Mar 2014 23:07:10 -0500 Subject: [PATCH 091/850] Removing some stuff --- lib/ionic.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ionic.js b/lib/ionic.js index 50e25c698b..b234f32f0e 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -79,6 +79,7 @@ var TASKS = [ usage: 'platform', task: IonicPlatformTask }, + /* { title: 'login', name: 'login', @@ -99,6 +100,7 @@ var TASKS = [ usage: 'mode platform', task: IonicPackageTask } + */ ]; Ionic = { From 2c3f9c5c4980a7ca7b299ee038bcf9a59c9b6e98 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 26 Mar 2014 14:56:33 -0500 Subject: [PATCH 092/850] Initial private settings for projects --- lib/ionic/package.js | 32 +++++++++++---------- lib/ionic/private.js | 67 ++++++++++++++++++++++++++++++++++++++++++++ lib/ionic/project.js | 7 ----- lib/ionic/upload.js | 2 +- 4 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 lib/ionic/private.js diff --git a/lib/ionic/package.js b/lib/ionic/package.js index bf66b47b42..b227526a31 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -6,6 +6,7 @@ var fs = require('fs'), shelljs = require('shelljs/global'), FormData = require('form-data'), IonicProject = require('./project'), + IonicProjectPrivate = require('./private'), IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; @@ -46,6 +47,7 @@ IonicPackageTask.prototype.run = function(ionic) { login.get(ionic, function(jar) { var project = IonicProject.load(); + var projectPrivate = IonicProjectPrivate.load(project.get('app_id')); console.log('Grabbing plugins...'); var plugins = []; @@ -128,7 +130,7 @@ IonicPackageTask.prototype.run = function(ionic) { // Don't prompt for properties we already have in the config for (var property in properties) { - if(project.get(property)) { + if(projectPrivate.get(property)) { delete properties[property]; } } @@ -140,11 +142,11 @@ IonicPackageTask.prototype.run = function(ionic) { // Overwrite any empty properties with prompt responses for (var property in properties) { - if(result[property] && !project.get(property)) { - project.set(property, result[property]); + if(result[property] && !projectPrivate.get(property)) { + projectPrivate.set(property, result[property]); } } - project.save(); + projectPrivate.save(project.get('app_id')); console.log('Packaging '+platform+' app...'); @@ -160,9 +162,9 @@ IonicPackageTask.prototype.run = function(ionic) { }; // Add the platform specific project properties to the post - for (var property in project.get()) { + for (var property in projectPrivate.get()) { if(property.indexOf(platform) == 0) { - form.append(property, project.get(property)); + form.append(property, projectPrivate.get(property)); } } @@ -170,33 +172,33 @@ IonicPackageTask.prototype.run = function(ionic) { switch(platform) { case 'android': if(mode == 'release') { - var keystoreFilePath = path.resolve(project.get('android_keystore')); + var keystoreFilePath = path.resolve(projectPrivate.get('android_keystore')); if(fs.existsSync(keystoreFilePath)) { form.append('android_keystore_file', fs.createReadStream(keystoreFilePath), {filename: 'www.zip'}); } else { - project.remove('android_keystore'); - project.save(); + projectPrivate.remove('android_keystore'); + projectPrivate.save(project.get('app_id')); process.stderr.write('\nCan\'t find file: "'+keystoreFilePath+'"\nSkipping build..."\n\n'); return; } } break; case 'ios': - var certificateFilePath = path.resolve(project.get('ios_certificate')); + var certificateFilePath = path.resolve(projectPrivate.get('ios_certificate')); if(fs.existsSync(certificateFilePath)) { form.append('ios_certificate_file', fs.createReadStream(certificateFilePath)); } else { - project.remove('ios_certificate'); - project.save(); + projectPrivate.remove('ios_certificate'); + projectPrivate.save(project.get('app_id')); process.stderr.write('\nCan\'t find file: "'+certificateFilePath+'"\nSkipping build..."\n\n'); return; } - var profileFilePath = path.resolve(project.get('ios_profile')); + var profileFilePath = path.resolve(projectPrivate.get('ios_profile')); if(fs.existsSync(profileFilePath)) { form.append('ios_profile_file', fs.createReadStream(profileFilePath)); } else { - project.remove('ios_profile'); - project.save(); + projectPrivate.remove('ios_profile'); + projectPrivate.save(project.get('app_id')); process.stderr.write('\nCan\'t find file: "'+profileFilePath+'"\nSkipping build..."\n\n'); return; } diff --git a/lib/ionic/private.js b/lib/ionic/private.js new file mode 100644 index 0000000000..63a3377a64 --- /dev/null +++ b/lib/ionic/private.js @@ -0,0 +1,67 @@ +var fs = require('fs'), + path = require('path'), + ionic = require('../ionic'); + +var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; + +module.exports = { + PRIVATE_PATH: '.ionic/', + PRIVATE_EXT: '.project', + PRIVATE_DEFAULT: { + ios_certificate: '', + ios_certificate_password: '', + ios_profile: '', + android_keystore: '', + android_keystore_alias: '', + android_keystore_password: '', + android_key_password: '' + }, + load: function(app_id) { + if(app_id) { + this.file = this.PRIVATE_PATH+app_id+this.PRIVATE_EXT; + if(fs.existsSync(path.join(home,this.file))) { + this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); + } else { + this.data = {}; + } + } + return this; + }, + create: function(name) { + this.data = this.PRIVATE_DEFAULT; + return this; + }, + save: function(app_id) { + if(!this.data) { + console.trace(); + console.error('This should never happen!'); + } + if(app_id) { + this.file = this.PRIVATE_PATH+app_id+this.PRIVATE_EXT; + try { + fs.writeFileSync(path.join(home,this.file), JSON.stringify(this.data, null, 2)); + } catch(e) { + console.error('Unable to save private settings file:', e); + } + } + }, + get: function(k) { + if(k) { + return this.data[k]; + } else { + return this.data; + } + }, + set: function(k, v) { + if(!this.data) { + this.data = PRIVATE_DEFAULT; + } + this.data[k] = v; + }, + remove: function(k) { + if(!this.data) { + this.data = PRIVATE_DEFAULT; + } + this.data[k] = ''; + } +}; diff --git a/lib/ionic/project.js b/lib/ionic/project.js index c227284b10..180757375c 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -9,13 +9,6 @@ module.exports = { email: '', app_id: '', package_name: '', - ios_certificate: '', - ios_certificate_password: '', - ios_profile: '', - android_keystore: '', - android_keystore_alias: '', - android_keystore_password: '', - android_key_password: '' }, load: function() { this.file = this.PROJECT_FILE; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 196d98992d..997de2bbe4 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -72,7 +72,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); project.save(); - if (callback) { + if(callback) { callback(); }; } From 7b2cda1c5bdf49282d6a299b231bbf0358c4dad5 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 26 Mar 2014 15:42:54 -0500 Subject: [PATCH 093/850] Finish privatizing passwords --- lib/ionic/package.js | 4 ++-- lib/ionic/private.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index b227526a31..10acd4e397 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -41,7 +41,7 @@ IonicPackageTask.prototype.run = function(ionic) { } var upload = new IonicUploadTask(); - upload.run(ionic, function() { + //upload.run(ionic, function() { var login = new IonicLoginTask(); login.get(ionic, function(jar) { @@ -240,7 +240,7 @@ IonicPackageTask.prototype.run = function(ionic) { }); } }); - }); + //}); }; exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/private.js b/lib/ionic/private.js index 63a3377a64..e58d810c4f 100644 --- a/lib/ionic/private.js +++ b/lib/ionic/private.js @@ -22,12 +22,12 @@ module.exports = { if(fs.existsSync(path.join(home,this.file))) { this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); } else { - this.data = {}; + this.data = this.PRIVATE_DEFAULT; } } return this; }, - create: function(name) { + create: function() { this.data = this.PRIVATE_DEFAULT; return this; }, From ce6aea76023eeda0b85fb6bd286fc670770753ed Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 27 Mar 2014 18:53:32 -0500 Subject: [PATCH 094/850] Removed dep on gulp and bower --- lib/ionic.js | 32 ++++++++++++++++++++- lib/ionic/start.js | 69 +++++++++++++++++++++++++--------------------- package.json | 4 +-- 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index b234f32f0e..2578e279a8 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -27,6 +27,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, os = require('os'), unzip = require('unzip'), colors = require('colors'), + spawn = require('child_process').spawn, Q = require('q'); @@ -183,6 +184,35 @@ Ionic = { process.exit(1); }, + spawnPromise: function(cmd, args, onStdOut, onStdErr) { + var q = Q.defer(); + console.log('\nRUNNING:'.info.bold, cmd, args.join(' ')); + try { + var child = spawn(cmd, args); + } catch(e) { + } + child.stdout.setEncoding('utf8'); + child.stderr.setEncoding('utf8'); + child.stdout.on('data', function(data) { + process.stdout.write(data); + onStdOut && onStdOut(data); + }); + child.stderr.on('data', function(data) { + process.stderr.write(data); + onStdErr && onStdErr(data); + }); + child.on('error', function(err) { + q.reject(err); + }); + child.on('exit', function(code) { + if(code === 0) { + q.resolve(); + } else { + q.reject(code); + } + }); + return q.promise; + }, /** * Fetch a repo from GitHub, unzip it to a specific folder. */ @@ -191,7 +221,7 @@ Ionic = { // The folder name the project will be downloaded and extracted to var repoFolderName = repoName + '-master'; - console.log('Fetching repo:', repoUrl); + console.log('\nDOWNLOADING:'.info.bold, repoUrl); var tmpFolder = os.tmpdir(); var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index f2e35398c6..b15b700769 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -7,6 +7,7 @@ var fs = require('fs'), unzip = require('unzip'), argv = require('optimist').argv, colors = require('colors'), + spawn = require('child_process').spawn, Q = require('q'), IonicProject = require('../ionic'), IonicProject = require('./project'), @@ -82,7 +83,6 @@ IonicStartTask.prototype._fetchWrapper = function() { var repoName = IonicStartTask.WRAPPER_REPO_NAME; var repoUrl = 'https://github.com/driftyco/' + IonicStartTask.WRAPPER_REPO_NAME + '/archive/master.zip'; - console.log('Fetching', 'Cordova'.info.bold, 'wrapper'); Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); @@ -115,41 +115,46 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var repoUrl = self._getStarterUrl(repoName); Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { + var npmQ = Q.defer(); + var gulpQ = Q.defer(); var pluginQ = Q.defer(); - // Install dependencies for the starter project - exec('npm install'); - exec('gulp init --sass'); - - // Move the content of this repo into the www folder - cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); - - // Copy the root config file to the www folder - cp(self.targetPath + '/config.xml', 'www'); - - // Clean up start template folder - rm('-rf', self.targetPath + '/' + repoFolderName + '/'); - - console.log('Initializing cordova project.'.info.bold); - exec('cordova plugin add org.apache.cordova.device && ' + - 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add org.apache.cordova.statusbar', function(err, stdout, stderr) { - if(err) { - pluginQ.reject(stderr); - } else { - pluginQ.resolve(stdout); - } - }) - - pluginQ.promise.then(function() { - self._printQuickHelp(self.appName); - }, function(err) { - Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); - }); - IonicStats.t('start', {}); + //Ionic.spawnPromise('npm', ['install', '--quiet']).then(function() { + // Move the content of this repo into the www folder + cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); + + // Copy the root config file to the www folder + cp(self.targetPath + '/config.xml', 'www'); + + // Clean up start template folder + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); + + console.log('Initializing cordova project.'.info.bold); + exec('cordova plugin add org.apache.cordova.device && ' + + 'cordova plugin add org.apache.cordova.console && ' + + 'cordova plugin add org.apache.cordova.statusbar', function(err, stdout, stderr) { + if(err) { + pluginQ.reject(stderr); + } else { + pluginQ.resolve(stdout); + } + }) + + pluginQ.promise.then(function() { + self._printQuickHelp(self.appName); + }, function(err) { + Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); + }); + + IonicStats.t('start', {}); + /* + }).fail(function(err, stderr) {; + Ionic.fail('Unable to install Ionic dependencies. Please make sure you\'ve installed cordova, and gulp globally by running:\nsudo npm install -g cordova gulp. Error:\n'.error.bold + err + '\n' + stderr); + }); + */ }).catch(function(err) { - console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode); + console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode, err); console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'.error.bold); Ionic.fail(''); }); diff --git a/package.json b/package.json index d276025bc6..a09d323b0a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "request": "2.27.0", "shelljs": "0.2.6", "unzip": "0.1.9", - "q": "^1.0.1", - "colors": "^0.6.2" + "colors": "^0.6.2", + "q": "^1.0.1" } } From 556374c1e7c1256adab642dd8cbf2cb00536365a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 27 Mar 2014 18:59:04 -0500 Subject: [PATCH 095/850] vNum Update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a09d323b0a..0d780a255e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.0-beta", + "version": "1.0.0-beta.1", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 0c683eca716fa6bc9a34de3ab0c656f5f8e28efe Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 27 Mar 2014 18:59:51 -0500 Subject: [PATCH 096/850] idk --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d780a255e..902e99e824 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.0-beta.1", + "version": "1.0.1-beta", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 15933b01a3e27f969afa89269416a2f570b8fc09 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Wed, 2 Apr 2014 11:44:34 -0500 Subject: [PATCH 097/850] Just lowercase all starter projects by default --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index b15b700769..1a74914dfa 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -68,7 +68,7 @@ IonicStartTask.prototype.run = function(ionic) { fs.mkdirSync(this.targetPath); - this._fetchAndWriteSeed(starterProject); + this._fetchAndWriteSeed(starterProject.toLowerCase()); this._writeConfig(ionic); }; From 269804a6542243613daef18455c8d5293d528d85 Mon Sep 17 00:00:00 2001 From: Peter C Date: Fri, 18 Apr 2014 14:34:29 -0500 Subject: [PATCH 098/850] Don't copy config.xml into www anymore People were getting confused on new versions of cordova with config.xml files appearing in the www folder and the project parent directory. --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 1a74914dfa..17fd663948 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -125,7 +125,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); // Copy the root config file to the www folder - cp(self.targetPath + '/config.xml', 'www'); + // cp(self.targetPath + '/config.xml', 'www'); // Clean up start template folder rm('-rf', self.targetPath + '/' + repoFolderName + '/'); From c218c3f4f15347dfdf5b53cb89dc7283daf75b49 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 24 Apr 2014 15:55:22 -0700 Subject: [PATCH 099/850] Removed statusbar plugin by default --- lib/ionic/start.js | 4 ++-- package.json | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 17fd663948..ed46b18347 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -132,8 +132,8 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { console.log('Initializing cordova project.'.info.bold); exec('cordova plugin add org.apache.cordova.device && ' + - 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add org.apache.cordova.statusbar', function(err, stdout, stderr) { + 'cordova plugin add org.apache.cordova.console' + , function(err, stdout, stderr) { if(err) { pluginQ.reject(stderr); } else { diff --git a/package.json b/package.json index 902e99e824..5f87238aca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.1-beta", + "version": "1.0.3-beta", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -32,6 +32,7 @@ "shelljs": "0.2.6", "unzip": "0.1.9", "colors": "^0.6.2", - "q": "^1.0.1" + "q": "^1.0.1", + "npm": "^1.4.6" } } From 278d0051e65886e31c0d9d1b03cd768d8148f12c Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 28 Apr 2014 12:33:40 -0500 Subject: [PATCH 100/850] Proxy support --- lib/ionic.js | 5 ++++- lib/ionic/project.js | 3 +++ lib/ionic/start.js | 12 ++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2578e279a8..91bea82f99 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -22,6 +22,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicLoginTask = require('./ionic/login').IonicLoginTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, + IonicProject = require('./ionic/project'), path = require('path'), request = require('request'), os = require('os'), @@ -219,6 +220,8 @@ Ionic = { fetchRepo: function(targetPath, repoName, repoUrl) { var q = Q.defer(); + var proxy = process.env.PROXY || null; + // The folder name the project will be downloaded and extracted to var repoFolderName = repoName + '-master'; console.log('\nDOWNLOADING:'.info.bold, repoUrl); @@ -237,7 +240,7 @@ Ionic = { readStream.pipe(writeStream); }; - request({ url: repoUrl, encoding: null }, function(err, res, body) { + request({ url: repoUrl, encoding: null, proxy: proxy }, function(err, res, body) { if(res.statusCode !== 200) { q.reject(res); return; diff --git a/lib/ionic/project.js b/lib/ionic/project.js index 0494f94ef1..8390466d82 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -37,6 +37,9 @@ module.exports = { } }, get: function(k) { + if(!this.data) { + return null; + } if(k) { return this.data[k]; } else { diff --git a/lib/ionic/start.js b/lib/ionic/start.js index ed46b18347..7b9d7c79a8 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -9,7 +9,6 @@ var fs = require('fs'), colors = require('colors'), spawn = require('child_process').spawn, Q = require('q'), - IonicProject = require('../ionic'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -168,12 +167,13 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\nYour Ionic project is ready to go!'.green.bold); console.log('\nSome quick tips:'); - console.log('\n * cd into your project directory before running any of the following commands', ('(cd ' + projectDirectory + ')').info.bold); - console.log('\n * Make sure to add a platform (ios or Android):', 'ionic platform add android [ios]'.info.bold); + console.log('\n * cd into your project:', ('$ cd ' + projectDirectory).info.bold); + console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); - console.log('\n * To build your project, run', 'ionic build [platform]'.info.bold); - console.log('\n * To emulate your project in a simulator or emulator, run', 'ionic emulate [platform]'.info.bold); - console.log('\n * To run your project on a device, run', 'ionic run [platform]'.info.bold); + console.log(' See the Android Platform Guid for full Android installation instructions: https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); + console.log('\n * Build your app:', 'ionic build [platform]'.info.bold); + console.log('\n * Simulate your app:', 'ionic emulate [platform]'.info.bold); + console.log('\n * Run your app on a device:', 'ionic run [platform]'.info.bold); console.log('\n\nFor more help, visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold); }; From 3ad53647fca5f64399de9d602107bcbae70bbd19 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 28 Apr 2014 12:33:57 -0500 Subject: [PATCH 101/850] Proxy support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f87238aca..c2d3b2ad24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.3-beta", + "version": "1.0.4", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 5e298d1fd40d1feaf302deff87c47b36b544e299 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 09:51:50 -0500 Subject: [PATCH 102/850] Alpha features --- lib/ionic.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 91bea82f99..7dde3ff159 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -81,7 +81,6 @@ var TASKS = [ usage: 'platform', task: IonicPlatformTask }, - /* { title: 'login', name: 'login', @@ -94,7 +93,8 @@ var TASKS = [ alt: ['up'], usage: '', task: IonicUploadTask - }, + } + /* { title: 'package', name: 'package', diff --git a/package.json b/package.json index c2d3b2ad24..c6fab60902 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.4", + "version": "1.0.5", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 995a0218b22bc22f311eb5454a2401a1971957b8 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 11:54:06 -0500 Subject: [PATCH 103/850] Fixed URL --- lib/ionic.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 7dde3ff159..756365d872 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -106,8 +106,8 @@ var TASKS = [ ]; Ionic = { - //IONIC_DASH: 'http://apps.ionicframework.com/', - IONIC_DASH: 'http://127.0.0.1:8000/', + IONIC_DASH: 'http://apps.ionicframework.com/', + //IONIC_DASH: 'http://127.0.0.1:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { From 5ff69acc57dc5268a962f91bc09da6567285ed4c Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 11:54:27 -0500 Subject: [PATCH 104/850] v --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6fab60902..123e1357e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.5", + "version": "1.0.6", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 08ab635933ad353ac39c3b4159abef23aebe2ee2 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 12:26:07 -0500 Subject: [PATCH 105/850] Ionic serve --- lib/ionic.js | 13 ++++++++++--- lib/ionic/serve.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 ++++-- 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 lib/ionic/serve.js diff --git a/lib/ionic.js b/lib/ionic.js index 756365d872..bf56c3606a 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -22,6 +22,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicLoginTask = require('./ionic/login').IonicLoginTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, + IonicServeTask = require('./ionic/serve'), IonicProject = require('./ionic/project'), path = require('path'), request = require('request'), @@ -51,6 +52,12 @@ var fs = require('fs'), argv = require('optimist').argv; var TASKS = [ + { + title: 'serve', + name: 'serve', + usage: '', + task: IonicServeTask + }, { title: 'start', name: 'start', @@ -93,7 +100,7 @@ var TASKS = [ alt: ['up'], usage: '', task: IonicUploadTask - } + }, /* { title: 'package', @@ -106,8 +113,8 @@ var TASKS = [ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com/', - //IONIC_DASH: 'http://127.0.0.1:8000/', + //IONIC_DASH: 'http://apps.ionicframework.com/', + IONIC_DASH: 'http://127.0.0.1:8002/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js new file mode 100644 index 0000000000..1c5768bcaa --- /dev/null +++ b/lib/ionic/serve.js @@ -0,0 +1,45 @@ +var fs = require('fs'), + argv = require('optimist').argv, + connect = require('connect'), + open = require('open'), + Q = require('q'), + IonicProject = require('./project'), + IonicTask = require('./task').IonicTask; + IonicStats = require('./stats').IonicStats; + +var IonicServeTask = function() {} + +IonicServeTask.HELP_LINE = 'Start a local development server for easy app development and testing'; + +IonicServeTask.prototype = new IonicTask(); + +IonicServeTask.prototype._printUsage = function() { + process.stderr.write('\nUsage: ionic serve [port] [options]\n'); + process.stderr.write('\nUse --nobrowser to disable auto browser launch\n'); +}; + +IonicServeTask.prototype.run = function(ionic) { + var project = IonicProject.load(); + + // Grab the name of the app + this.port = argv._[1] || '8100'; + + this.launchBrowser = typeof argv['nobrowser'] === 'undefined'; + + this._start(); +}; + +IonicServeTask.prototype._start = function() { + var self = this; + + console.log('Running local development server at', ('http://0.0.0.0:' + this.port).info.bold); + + setTimeout(function() { + if(self.launchBrowser) { + open('http://localhost:' + self.port); + } + }); + connect().use(connect.static('www')).listen(this.port); +}; + +module.exports = IonicServeTask; diff --git a/package.json b/package.json index 123e1357e5..cdc985d42d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.6", + "version": "1.0.7", "preferGlobal": true, "description": "A tool for creating and building Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -33,6 +33,8 @@ "unzip": "0.1.9", "colors": "^0.6.2", "q": "^1.0.1", - "npm": "^1.4.6" + "npm": "^1.4.6", + "connect": "^2.14.5", + "open": "0.0.5" } } From ee87fb0fce90f8ff8b31424aa82674e575bf0103 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 14:36:25 -0500 Subject: [PATCH 106/850] Livereload --- lib/ionic.js | 15 +++++++++++ lib/ionic/serve.js | 67 +++++++++++++++++++++++++++++++++++++++------- package.json | 9 ++++--- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index bf56c3606a..c4b7b2c61d 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -258,6 +258,21 @@ Ionic = { }); return q.promise; + }, + + getLocalIps: function() { + var interfaces = os.networkInterfaces(); + var addresses = []; + for (k in interfaces) { + for (k2 in interfaces[k]) { + var address = interfaces[k][k2]; + if (address.family == 'IPv4' && !address.internal) { + addresses.push(address.address) + } + } + } + + return addresses; } }; diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 1c5768bcaa..ac6f8129f8 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -2,6 +2,10 @@ var fs = require('fs'), argv = require('optimist').argv, connect = require('connect'), open = require('open'), + tinylr = require('tiny-lr-fork'), + lr = require('connect-livereload'), + vfs = require('vinyl-fs'), + request = require('request'), Q = require('q'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask; @@ -14,7 +18,7 @@ IonicServeTask.HELP_LINE = 'Start a local development server for easy app develo IonicServeTask.prototype = new IonicTask(); IonicServeTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic serve [port] [options]\n'); + process.stderr.write('\nUsage: ionic serve [http-port] [livereload-port] [options]\n'); process.stderr.write('\nUse --nobrowser to disable auto browser launch\n'); }; @@ -22,24 +26,67 @@ IonicServeTask.prototype.run = function(ionic) { var project = IonicProject.load(); // Grab the name of the app - this.port = argv._[1] || '8100'; + this.port = argv._[1] || 8100; + this.liveReloadPort = argv._[2] || 35729; this.launchBrowser = typeof argv['nobrowser'] === 'undefined'; + this.runLivereload = typeof argv['nolivereload'] === 'undefined'; - this._start(); + this._start(ionic); }; -IonicServeTask.prototype._start = function() { - var self = this; +IonicServeTask.prototype._changed = function(path) { + // Cleanup the path a bit + var pwd = process.cwd() + path = path.replace(pwd + '/', ''); - console.log('Running local development server at', ('http://0.0.0.0:' + this.port).info.bold); + console.log('Changed', path); - setTimeout(function() { - if(self.launchBrowser) { - open('http://localhost:' + self.port); + var req = request.post('http://localhost:' + this.liveReloadPort + '/changed', { + path: '/changed', + method: 'POST', + body: JSON.stringify({ + files: [path] + }) + }, function(err, res, body) { + if(err) { + console.error('Unable to update live reload:', err); } }); - connect().use(connect.static('www')).listen(this.port); +}; + +IonicServeTask.prototype._start = function(ionic) { + var self = this; + + var app = connect(); + + if(this.runLivereload) { + vfs.watch('www/**/*', { + }, function(f) { + self._changed(f.path); + }); + + server = tinylr(); + server.listen(this.liveReloadPort, function(err) { + if(err) { + ionic.fail('Unable to start server:', err); + } else { + console.log('Running live reload server at', ('http://0.0.0.0:' + self.liveReloadPort).info.bold); + if(self.launchBrowser) { + open('http://localhost:' + self.port); + } + } + }); + + app.use(require('connect-livereload')({ + port: this.liveReloadPort + })) + } + + app.use(connect.static('www')) + .listen(this.port); + + console.log('Running dev server at', ('http://0.0.0.0:' + this.port).info.bold); }; module.exports = IonicServeTask; diff --git a/package.json b/package.json index cdc985d42d..c6652a11f4 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "ionic", - "version": "1.0.7", + "version": "1.0.8", "preferGlobal": true, - "description": "A tool for creating and building Ionic Framework mobile apps.", + "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", "bin": { "ionic": "bin/ionic" @@ -35,6 +35,9 @@ "q": "^1.0.1", "npm": "^1.4.6", "connect": "^2.14.5", - "open": "0.0.5" + "open": "0.0.5", + "tiny-lr-fork": "0.0.5", + "connect-livereload": "^0.4.0", + "vinyl-fs": "^0.1.4" } } From 60b53d8276f11f4ff6990aa28048fa64abd6ad7a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 29 Apr 2014 14:43:06 -0500 Subject: [PATCH 107/850] Version and info --- lib/ionic.js | 8 +++++++- lib/ionic/start.js | 1 + package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index c4b7b2c61d..ed0654e997 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -30,7 +30,8 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, unzip = require('unzip'), colors = require('colors'), spawn = require('child_process').spawn, - Q = require('q'); + Q = require('q'), + settings = require('../package.json') colors.setTheme({ @@ -175,6 +176,11 @@ Ionic = { }, run: function() { + if(argv.version) { + console.log('Ionic CLI version ' + settings.version); + process.exit(0); + } + var task = this._tryBuildingTask(); if(!task) { return this._printGenericUsage(); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 7b9d7c79a8..567de82265 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -174,6 +174,7 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\n * Build your app:', 'ionic build [platform]'.info.bold); console.log('\n * Simulate your app:', 'ionic emulate [platform]'.info.bold); console.log('\n * Run your app on a device:', 'ionic run [platform]'.info.bold); + console.log('\n * Develop in the browser with live reload:', 'ionic serve'.info.bold); console.log('\n\nFor more help, visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold); }; diff --git a/package.json b/package.json index c6652a11f4..03356c04db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.8", + "version": "1.0.9", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From af86a7a1a1d0b82960297f8fca610470ca1ca372 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sun, 11 May 2014 17:03:40 -0500 Subject: [PATCH 108/850] Fixed login and upload --- lib/ionic.js | 4 ++-- lib/ionic/login.js | 2 +- lib/ionic/upload.js | 31 ++++++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index ed0654e997..0304ab98d6 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -114,8 +114,8 @@ var TASKS = [ ]; Ionic = { - //IONIC_DASH: 'http://apps.ionicframework.com/', - IONIC_DASH: 'http://127.0.0.1:8002/', + IONIC_DASH: 'http://apps.ionicframework.com/', + //IONIC_DASH: 'http://localhost:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 1b11ea70b0..69faedac1d 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -38,7 +38,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { schema.shift(); } - console.log('To continue, please login to your Ionic Platform account (Create a free account here: ' + ionic.IONIC_DASH + 'signup)'); + console.log('To continue, please login to your Ionic account.\nDon\'t have one? Create a one here: ' + (ionic.IONIC_DASH + 'signup').info.bold + '\n'); prompt.override = argv; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index c90a541b67..9af0f1a85e 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -45,7 +45,11 @@ IonicUploadTask.prototype.run = function(ionic, callback) { zip.on('close', function() { console.log('Done'); - console.log('Uploading...'); + if(project.get('app_id')) { + console.log('Uploading app (id: ' + project.get('app_id') + ')'); + } else { + console.log('Uploading app.'); + } var form = new FormData(); form.append('name', project.get('name')); @@ -57,7 +61,8 @@ IonicUploadTask.prototype.run = function(ionic, callback) { var params = parseUrl(url); form.submit({ - host: params.host, + hostname: params.hostname, + port: params.port, path: params.path, headers: form.getHeaders({ cookie: jar.cookies.map(function (c) { @@ -70,9 +75,14 @@ IonicUploadTask.prototype.run = function(ionic, callback) { ionic.fail("Error uploading: " + err); } - console.log('Done uploading'.info.bold); - if(response.statusCode == 302) { + if(response.headers.location.indexOf('login?next=') >= 0) { + console.error('Session expired. Please log in again and run this command again.'); + q.reject('not_logged_in'); + return; + } + console.log('Done!'.info.bold); + var redirectPath = parseUrl(response.headers.location); project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); project.save(); @@ -80,8 +90,17 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(callback) { callback(); }; - } else { + } else if(response.statusCode === 200) { + console.log('Got response', response.statusCode); callback && callback(); + } else { + if(response.headers['content-type'] == 'application/json') { + response.on('data', function(chunk) { + console.log(String(chunk)); + }); + } + console.error('Unable to upload. HTTP response:', response.statusCode); + q.reject(response); } q.resolve(callback); @@ -94,6 +113,8 @@ IonicUploadTask.prototype.run = function(ionic, callback) { if(!callback) { process.exit(0); } + }, function(err) { + process.exit(1); }); }; From d9944a752320d8a5ef386de151635333b9d5196d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sun, 11 May 2014 17:03:58 -0500 Subject: [PATCH 109/850] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03356c04db..cc685c4aaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.9", + "version": "1.0.10", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 29199e5fb8f8ed21cc292d429fdc78d89f6e39f6 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 14 May 2014 10:05:41 -0500 Subject: [PATCH 110/850] Added keyboard plugin by default --- lib/ionic.js | 4 ++-- lib/ionic/start.js | 33 +++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 0304ab98d6..3fe3689bf5 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -114,8 +114,8 @@ var TASKS = [ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com/', - //IONIC_DASH: 'http://localhost:8000/', + //IONIC_DASH: 'http://apps.ionicframework.com/', + IONIC_DASH: 'http://localhost:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 567de82265..e21c5fb5b7 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -96,6 +96,24 @@ IonicStartTask.prototype._fetchWrapper = function() { return q.promise; }; +IonicStartTask.prototype._installCordovaPlugins = function() { + var q = Q.defer(); + + console.log('Initializing cordova project.'.info.bold); + exec('cordova plugin add org.apache.cordova.device && ' + + 'cordova plugin add org.apache.cordova.console && ' + + 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard' + , function(err, stdout, stderr) { + if(err) { + q.reject(stderr); + } else { + q.resolve(stdout); + } + }); + + return q.promise; +}; + IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var self = this; @@ -129,16 +147,11 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { // Clean up start template folder rm('-rf', self.targetPath + '/' + repoFolderName + '/'); - console.log('Initializing cordova project.'.info.bold); - exec('cordova plugin add org.apache.cordova.device && ' + - 'cordova plugin add org.apache.cordova.console' - , function(err, stdout, stderr) { - if(err) { - pluginQ.reject(stderr); - } else { - pluginQ.resolve(stdout); - } - }) + self._installCordovaPlugins().then(function(output) { + pluginQ.resolve(stdout); + }, function(err) { + pluginQ.reject(err); + }); pluginQ.promise.then(function() { self._printQuickHelp(self.appName); From bd36f49b6ea6cc8bcb175badc4f183702f1a6c7d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 14 May 2014 10:06:11 -0500 Subject: [PATCH 111/850] v bump --- lib/ionic.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 3fe3689bf5..0304ab98d6 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -114,8 +114,8 @@ var TASKS = [ ]; Ionic = { - //IONIC_DASH: 'http://apps.ionicframework.com/', - IONIC_DASH: 'http://localhost:8000/', + IONIC_DASH: 'http://apps.ionicframework.com/', + //IONIC_DASH: 'http://localhost:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/package.json b/package.json index cc685c4aaf..413a0f89a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.10", + "version": "1.0.11", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From fb5468087c0d874f0b558603fb7ebb9284e6c913 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 20 May 2014 13:12:12 -0500 Subject: [PATCH 112/850] USERPROFILE should take priority over HOMEPATH on Windows --- lib/ionic/config.js | 2 +- lib/ionic/private.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ionic/config.js b/lib/ionic/config.js index b1c2e648e6..14ede659a1 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -2,7 +2,7 @@ var fs = require('fs'), path = require('path'), ionic = require('../ionic'); -var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; +var home = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH; module.exports = { CONFIG_FILE: '.ionic/ionic.config', diff --git a/lib/ionic/private.js b/lib/ionic/private.js index e58d810c4f..68a83c7952 100644 --- a/lib/ionic/private.js +++ b/lib/ionic/private.js @@ -2,7 +2,7 @@ var fs = require('fs'), path = require('path'), ionic = require('../ionic'); -var home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; +var home = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH; module.exports = { PRIVATE_PATH: '.ionic/', From 703205cda20c3f45bc04c0b9a54ae74ba18cac05 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 21 May 2014 15:34:55 -0500 Subject: [PATCH 113/850] Bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 413a0f89a6..731b282ce5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.11", + "version": "1.0.12", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From d408435ab227395bbd4a1837987cb9f7b44253d3 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 22 May 2014 14:50:46 -0500 Subject: [PATCH 114/850] Auto create project file --- lib/ionic/project.js | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/ionic/project.js b/lib/ionic/project.js index 8390466d82..ebf6130b4d 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -15,14 +15,26 @@ module.exports = { if(fs.existsSync(this.file)) { this.data = JSON.parse(fs.readFileSync(this.file)) } else { + if(fs.existsSync('www')) { + var parts = path.resolve('./').split(path.sep); + var dirname = parts[parts.length-1]; + console.log('We have a www folder in the', dirname, 'project'); + this.create(dirname); + this.save('./'); + } + /* Ionic.fail('Could not find your ' + this.file + ' file!'+ ' Please run this command in the root of your ionic project.'); + */ } return this; }, create: function(name) { this.file = this.PROJECT_FILE; this.data = this.PROJECT_DEFAULT; + if(name) { + this.set('name', name); + } return this; }, save: function(targetPath) { diff --git a/package.json b/package.json index 731b282ce5..96a419daa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.12", + "version": "1.0.13", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 8b306097952386c764f6a2da4feb93163e615b1e Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 22 May 2014 14:57:58 -0500 Subject: [PATCH 115/850] License tweak --- lib/ionic.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 0304ab98d6..a4f3ba0349 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -11,7 +11,7 @@ http://ionicframework.com/ A utility for starting and administering Ionic based mobile app projects. Licensed under the MIT license. See LICENSE For more. -Copyright 2013 Drifty (http://drifty.com/) +Copyright 2014 Drifty (http://drifty.com/) */ var IonicStartTask = require('./ionic/start').IonicStartTask, @@ -114,8 +114,8 @@ var TASKS = [ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com/', - //IONIC_DASH: 'http://localhost:8000/', + //IONIC_DASH: 'http://apps.ionicframework.com/', + IONIC_DASH: 'http://localhost:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { From d9781e425463bc844e0270d513a6fb520aa78650 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 22 May 2014 15:00:06 -0500 Subject: [PATCH 116/850] Paderp --- lib/ionic.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index a4f3ba0349..c95f4f6007 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -114,8 +114,8 @@ var TASKS = [ ]; Ionic = { - //IONIC_DASH: 'http://apps.ionicframework.com/', - IONIC_DASH: 'http://localhost:8000/', + IONIC_DASH: 'http://apps.ionicframework.com/', + //IONIC_DASH: 'http://localhost:8000/', IONIC_COOKIES: 'ionic.cookies', IONIC_API: 'api/v1/', _tryBuildingTask: function() { diff --git a/package.json b/package.json index 96a419daa4..c02d9aaa19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.13", + "version": "1.0.14", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From b2d1cf9d2f094aac67b6e99e0fbc4605c72791b9 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Wed, 28 May 2014 16:19:46 -0400 Subject: [PATCH 117/850] Added serve and template description --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 87439694e8..29122bc7b1 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,20 @@ $ sudo npm install -g ionic ## Starting an Ionic App ```bash -$ ionic start myApp +$ ionic start myApp [template] ``` +There are three choices of templates. + +* Side-Menu (sidemenu) +* Tabs (tabs) +* Blank (blank) + +## Testing in a Browser + +```bash +$ ionic serve +``` + ## Adding a platform target From 087a5d5a3bcd99fa82c3ea3830b95b6bc6464844 Mon Sep 17 00:00:00 2001 From: Ryan Schumacher Date: Wed, 11 Jun 2014 14:10:38 -0400 Subject: [PATCH 118/850] Update language of failure with live reload --- lib/ionic/serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index ac6f8129f8..e8614755a3 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -69,7 +69,7 @@ IonicServeTask.prototype._start = function(ionic) { server = tinylr(); server.listen(this.liveReloadPort, function(err) { if(err) { - ionic.fail('Unable to start server:', err); + ionic.fail('Unable to start live reload server:', err); } else { console.log('Running live reload server at', ('http://0.0.0.0:' + self.liveReloadPort).info.bold); if(self.launchBrowser) { From fd3ae5f90d389735177e481680a13da4fbf60a30 Mon Sep 17 00:00:00 2001 From: Perry Govier Date: Tue, 24 Jun 2014 10:43:34 -0500 Subject: [PATCH 119/850] fixing typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 29122bc7b1..ce6a934579 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ $ ionic run ios Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. -Note: we occasionally anonymous usage statistics to the Ionic team to make the tool better. +Note: we occasionally collect anonymous usage statistics to the Ionic team to make the tool better. From 361878fcf48506cf39e6caf2a81461abdae37f53 Mon Sep 17 00:00:00 2001 From: Perry Govier Date: Tue, 24 Jun 2014 10:44:53 -0500 Subject: [PATCH 120/850] when fixing a typo, it is often best to read the whole sentence --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce6a934579..20031cea44 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ $ ionic run ios Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. -Note: we occasionally collect anonymous usage statistics to the Ionic team to make the tool better. +Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better. From 45297dcb85b9ec8ce56d4b3eb89a51e61dbd6c61 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 9 Jul 2014 11:23:33 -0500 Subject: [PATCH 121/850] ionic package --- lib/ionic.js | 69 +++-- lib/ionic/config.js | 10 +- lib/ionic/login.js | 70 ++--- lib/ionic/package.js | 670 ++++++++++++++++++++++++++++++------------- lib/ionic/private.js | 67 ----- lib/ionic/project.js | 20 +- lib/ionic/store.js | 55 ++++ lib/ionic/upload.js | 84 +++--- package.json | 35 ++- 9 files changed, 680 insertions(+), 400 deletions(-) delete mode 100644 lib/ionic/private.js create mode 100644 lib/ionic/store.js diff --git a/lib/ionic.js b/lib/ionic.js index c95f4f6007..6604d4a192 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -1,9 +1,9 @@ /* - _ _ -(_) (_) - _ ___ _ __ _ ___ + _ _ +(_) (_) + _ ___ _ __ _ ___ | |/ _ \| '_ \| |/ __| -| | (_) | | | | | (__ +| | (_) | | | | | (__ |_|\___/|_| |_|_|\___| http://ionicframework.com/ @@ -13,7 +13,7 @@ Licensed under the MIT license. See LICENSE For more. Copyright 2014 Drifty (http://drifty.com/) */ - + var IonicStartTask = require('./ionic/start').IonicStartTask, IonicPlatformTask = require('./ionic/platform').IonicPlatformTask, IonicRunTask = require('./ionic/run').IonicRunTask, @@ -31,25 +31,25 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, colors = require('colors'), spawn = require('child_process').spawn, Q = require('q'), - settings = require('../package.json') + settings = require('../package.json'); colors.setTheme({ - silly: 'rainbow', - input: 'grey', - small: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'white', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red' + silly: 'rainbow', + input: 'grey', + small: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'white', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' }); -var fs = require('fs'), +var fs = require('fs'), argv = require('optimist').argv; var TASKS = [ @@ -64,7 +64,7 @@ var TASKS = [ name: 'start', usage: 'appname', task: IonicStartTask - }, + }, { title: 'emulate', name: 'emulate', @@ -102,7 +102,6 @@ var TASKS = [ usage: '', task: IonicUploadTask }, - /* { title: 'package', name: 'package', @@ -110,16 +109,15 @@ var TASKS = [ usage: 'mode platform', task: IonicPackageTask } - */ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com/', - //IONIC_DASH: 'http://localhost:8000/', - IONIC_COOKIES: 'ionic.cookies', - IONIC_API: 'api/v1/', + IONIC_DASH: 'http://apps.ionicframework.com', + //IONIC_DASH: 'http://localhost:8000', + IONIC_API: '/api/v1/', + PRIVATE_PATH: '.ionic', _tryBuildingTask: function() { - if(argv._.length == 0) { + if(argv._.length === 0) { return false; } var taskName = argv._[0]; @@ -138,7 +136,7 @@ Ionic = { var alt = t.alt[j]; if(alt === name) { return t; - } + } } } } @@ -186,23 +184,24 @@ Ionic = { return this._printGenericUsage(); } - console.log('Running', task.title.info.bold, 'task...') + console.log('\nRunning', task.title.info.bold, 'task...'); var taskObj = new task.task(); taskObj.run(this); }, fail: function(msg) { - process.stderr.write('ERROR: '); - process.stderr.write(msg.error.bold + '\nExiting.\n'); + process.stderr.write(msg.error.bold); + process.stderr.write('\n\n'); process.exit(1); }, spawnPromise: function(cmd, args, onStdOut, onStdErr) { var q = Q.defer(); + var child; console.log('\nRUNNING:'.info.bold, cmd, args.join(' ')); try { - var child = spawn(cmd, args); + child = spawn(cmd, args); } catch(e) { } child.stdout.setEncoding('utf8'); @@ -241,7 +240,7 @@ Ionic = { var tmpFolder = os.tmpdir(); var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); - var tempZipFileStream = fs.createWriteStream(tempZipFilePath) + var tempZipFileStream = fs.createWriteStream(tempZipFilePath); var unzipRepo = function(fileName) { var readStream = fs.createReadStream(fileName); @@ -269,11 +268,11 @@ Ionic = { getLocalIps: function() { var interfaces = os.networkInterfaces(); var addresses = []; - for (k in interfaces) { - for (k2 in interfaces[k]) { + for (var k in interfaces) { + for (var k2 in interfaces[k]) { var address = interfaces[k][k2]; if (address.family == 'IPv4' && !address.internal) { - addresses.push(address.address) + addresses.push(address.address); } } } diff --git a/lib/ionic/config.js b/lib/ionic/config.js index 14ede659a1..f2474fba5f 100644 --- a/lib/ionic/config.js +++ b/lib/ionic/config.js @@ -8,7 +8,7 @@ module.exports = { CONFIG_FILE: '.ionic/ionic.config', load: function() { this.file = this.CONFIG_FILE; - if(fs.existsSync(path.join(home,this.file))) { + if(fs.existsSync(path.join(home,this.file))) { this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); } else { this.data = {}; @@ -16,7 +16,7 @@ module.exports = { return this; }, save: function() { - if(!this.data) { + if(!this.data) { return; } try { @@ -28,7 +28,7 @@ module.exports = { } fs.writeFileSync(p, JSON.stringify(this.data, null, 2)); } catch(e) { - console.error('Unable to save settings file:', e); + console.error( ('Unable to save settings file: ' + e).red ); } }, get: function(k) { @@ -39,7 +39,7 @@ module.exports = { this.data = {}; } this.data[k] = v; - + this.save(); - } + } }; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 69faedac1d..0c2290789b 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -3,10 +3,10 @@ var fs = require('fs'), argv = require('optimist').argv, prompt = require('prompt'), IonicProject = require('./project'), + IonicStore = require('./store').IonicStore, IonicTask = require('./task').IonicTask; -var IonicLoginTask = function() { -} +var IonicLoginTask = function() {}; IonicLoginTask.HELP_LINE = 'Login to the Ionic Platform'; @@ -14,9 +14,10 @@ IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.run = function(ionic, callback) { var self = this; + var schema = [{ name: 'email', - pattern: /^[A-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[A-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/, + pattern: /^[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+(?:\.[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+)*@(?:[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?$/, message: 'Email for your Ionic Platform login', required: true }, { @@ -31,20 +32,15 @@ IonicLoginTask.prototype.run = function(ionic, callback) { if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { this.email = argv._[1].toLowerCase(); schema.shift(); - } - // Assume project email is login email if it exists - else if(project.get('email')) { - this.email = project.get('email'); - schema.shift(); } - console.log('To continue, please login to your Ionic account.\nDon\'t have one? Create a one here: ' + (ionic.IONIC_DASH + 'signup').info.bold + '\n'); + console.log('\nTo continue, please login to your Ionic account.'.bold.green); + console.log('Don\'t have one? Create a one at: '.grey + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); prompt.override = argv; prompt.start(); - prompt.get(schema, function (err, result) { if(err) { ionic.fail('Error logging in: ' + err); @@ -55,48 +51,44 @@ IonicLoginTask.prototype.run = function(ionic, callback) { } self.password = result.password; - if(!project.get('email')) { - project.set('email'); - } - var jar = request.jar(); request({ - url: ionic.IONIC_DASH + 'login', + url: ionic.IONIC_DASH + '/login', jar: jar - }, + }, function(err, response, body) { - if(err || jar.cookies.length == 0) { + if(err || jar.cookies.length === 0) { ionic.fail('Error logging in: ' + err); } request({ method: 'POST', - url: ionic.IONIC_DASH + 'login', - jar: jar, + url: ionic.IONIC_DASH + '/login', + jar: jar, form: { username: self.email, password: self.password, csrfmiddlewaretoken: jar.cookies[0].value } }, - function (err, response, body) { + function (err, response, body) { if(err) { ionic.fail('Error logging in: ' + err); } // Should be a 304 redirect status code if correct if(response.statusCode == 200) { - ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.') + ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); } - - var err = fs.writeFileSync(ionic.IONIC_COOKIES, JSON.stringify(jar, null, 2)); - if(err) { - ionic.fail('Error writing ' + ionic.IONIC_COOKIES + ': ' + err); - } - - console.log('Logged in! :)'); + + self.cookieData.set(ionic.IONIC_DASH, jar); + self.cookieData.save(); + + console.log('Logged in! :)'.green); if(callback) { callback(jar); + project.set('email', self.email); + project.save(); } }); }); @@ -104,22 +96,20 @@ IonicLoginTask.prototype.run = function(ionic, callback) { }; IonicLoginTask.prototype.get = function(ionic, callback) { - var self = this; - - if(fs.existsSync(ionic.IONIC_COOKIES)) { - var jar = JSON.parse(fs.readFileSync(ionic.IONIC_COOKIES)); - if(jar.cookies && jar.cookies.length > 0) { - for(i in jar.cookies) { - var cookie = jar.cookies[i]; - if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { - callback(jar); - return; - } + this.cookieData = new IonicStore('cookies'); + var jar = this.cookieData.get(ionic.IONIC_DASH); + + if(jar && jar.cookies && jar.cookies.length) { + for(var i in jar.cookies) { + var cookie = jar.cookies[i]; + if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { + callback(jar); + return; } } } this.run(ionic, callback); -} +}; exports.IonicLoginTask = IonicLoginTask; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 68f9629cb9..9ec8f31a94 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -1,246 +1,530 @@ var fs = require('fs'), + http = require('http'), path = require('path'), parseUrl = require('url').parse, + spawn = require("child_process").spawn, argv = require('optimist').argv, prompt = require('prompt'), shelljs = require('shelljs/global'), - FormData = require('form-data'), + FormData = require('form-data'), IonicProject = require('./project'), - IonicProjectPrivate = require('./private'), + IonicStore = require('./store').IonicStore, IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, IonicLoginTask = require('./login').IonicLoginTask; -var IonicPackageTask = function() { -} +var IonicPackageTask = function() {}; -IonicPackageTask.HELP_LINE = 'Package an Ionic project using the Ionic Platform Build service (requires login)'; +IonicPackageTask.HELP_LINE = 'Package an app using the Ionic Platform Build service (requires login)'; IonicPackageTask.prototype = new IonicTask(); + IonicPackageTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic package mode(debug|release) platform [more platforms,...]\n'); -} + process.stderr.write('\nUsage:\nionic package mode[debug|release] platform[ios,android]\n'); +}; + IonicPackageTask.prototype.run = function(ionic) { + var self = this; + self.ionic = ionic; + + self.project = IonicProject.load(); + + if(argv['clear-signing'] || argv.c) { + self.clearSigning(); + return; + } + + self.loadProject(); + + var login = new IonicLoginTask(); + login.get(self.ionic, function(jar) { + self.jar = jar; + + self.loadAppSigning(function(){ + self.packagePlatforms(self.platforms); + }); + }); + +}; + + +IonicPackageTask.prototype.clearSigning = function() { + var self = this; + console.log('Clearing app signing and credential information...'.yellow); + + var appId = self.project.get('app_id'); + + if(!appId) { + self.ionic.fail('App Id is not known'); + } + + var login = new IonicLoginTask(); + login.get(self.ionic, function(jar) { + var options = { + url: self.ionic.IONIC_DASH + self.ionic.IONIC_API + 'app/' + appId + '/signing/clear', + headers: { + cookie: jar.cookies.map(function (c) { + return c.name + "=" + encodeURIComponent(c.value); + }).join("; ") + } + }; + + request(options, function(err, response, body) { + if(err) { + self.ionic.fail("Error clearing app signing: " + err); + } + console.log( ('App (' + appId + ') signing and credential information cleared\n').green ); + }); + }); +}; + + +IonicPackageTask.prototype.loadProject = function() { + console.log( ("Loading " + this.project.get('name')).bold.yellow ); + if(argv._.length < 3) { IonicPackageTask.prototype._printUsage(); - ionic.fail('No platforms or build mode specified, exiting.'); + this.ionic.fail('No platforms or build mode specified.'); } - var mode = argv._[1].toLowerCase(); - if(mode != 'debug' && mode != 'release') { + this.mode = argv._[1].toLowerCase(); + if(this.mode != 'debug' && this.mode != 'release') { IonicPackageTask.prototype._printUsage(); - ionic.fail('Package build mode must be debug or release, exiting.'); + this.ionic.fail('Package build mode must be "debug" or "release".'); } - var platforms = argv._.slice(2); + this.platforms = argv._.slice(2); - if(platforms.length < 1) { - ionic.fail('No platforms specified, exiting.'); + if(this.platforms.length < 1) { + this.ionic.fail('No platforms specified.'); } +}; - var upload = new IonicUploadTask(); - upload.run(ionic, function() { - var login = new IonicLoginTask(); - login.get(ionic, function(jar) { +IonicPackageTask.prototype.loadPlugins = function() { + var self = this; + var parseString = require('xml2js').parseString; + var cp = spawn("cordova", ['plugins']); - var project = IonicProject.load(); - var projectPrivate = IonicProjectPrivate.load(project.get('app_id')); + cp.stdout.on("data", function (c) { + self.plugins = []; - console.log('Grabbing plugins...'); - var plugins = []; - var pluginExec = exec('cordova plugins'); - if(pluginExec.code != 0 ) { - process.stderr.write('Unable to read cordova plugin list. Please see console for more info.\n'); - } else { - pluginExec.output = pluginExec.output.replace(/'/g, '"'); - plugins = JSON.parse(pluginExec.output); - } + var pluginNames = JSON.parse(c.toString().replace(/'/g, '"')); + + for(var x=0; x= 0 && d.status < 3) { + // still queued/building + attempt++; + + if(attempt > 60) { + ionic.fail("\nUnable to receive build status"); + } + + setTimeout(function(){ + pingBuildStatus(ionic, requestOptions, platform, attempt); + }, 5000); + + } else if(d.status == 4) { + console.log("Use 'ionic package --clear-signing' to clear app signing and credential data if needed.".bold.red); + ionic.fail("Build failed"); + } else if(d.status == 3) { + downloadBuildPackage(platform, d); + } else { + ionic.fail("\nError receiving build status"); + } + + } catch(e) { + ionic.fail("\nError pinging build status: " + e); + } + + }); +} + + +function downloadBuildPackage(platform, data) { + console.log( ('\n\n' + platform + ' build complete, downloading package...').bold.grey ); + + var dirPath = path.resolve('./packages'); + var filePath = path.resolve(dirPath + '/' + data.package_filename); + + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + + var params = parseUrl(data.package_url); + + var file = fs.createWriteStream(filePath); + var request = http.get({hostname: params.hostname, path: params.path, port: params.port, protocol: 'http:'}, function(response) { + response.pipe(file); + file.on('finish', function() { + file.close(function(){ + console.log( ('Saved ' + platform + ' package: ' + filePath + '\n').bold.green ); + }); + }); + }).on('response', function(res){ + + var ProgressBar = require('progress'); + var bar = new ProgressBar('[:bar] :percent :etas', { + complete: '=', + incomplete: ' ', + width: 30, + total: parseInt(res.headers['content-length'], 10) + }); + + res.on('data', function (chunk) { + bar.tick(chunk.length); + }); + + res.on('end', function () { + console.log('\n'); + }); + + }).on('error', function(err) { + fs.unlink(filePath); + console.error( (err).red ); + }); +} + + +function fileExists(filePath) { + // check if a file exists with a relative path or absolute path + filePath = filePath.replace(/\\ /g, ' ').trim(); + return fs.existsSync(path.resolve(filePath)); +} + exports.IonicPackageTask = IonicPackageTask; diff --git a/lib/ionic/private.js b/lib/ionic/private.js deleted file mode 100644 index 68a83c7952..0000000000 --- a/lib/ionic/private.js +++ /dev/null @@ -1,67 +0,0 @@ -var fs = require('fs'), - path = require('path'), - ionic = require('../ionic'); - -var home = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH; - -module.exports = { - PRIVATE_PATH: '.ionic/', - PRIVATE_EXT: '.project', - PRIVATE_DEFAULT: { - ios_certificate: '', - ios_certificate_password: '', - ios_profile: '', - android_keystore: '', - android_keystore_alias: '', - android_keystore_password: '', - android_key_password: '' - }, - load: function(app_id) { - if(app_id) { - this.file = this.PRIVATE_PATH+app_id+this.PRIVATE_EXT; - if(fs.existsSync(path.join(home,this.file))) { - this.data = JSON.parse(fs.readFileSync(path.join(home, this.file))); - } else { - this.data = this.PRIVATE_DEFAULT; - } - } - return this; - }, - create: function() { - this.data = this.PRIVATE_DEFAULT; - return this; - }, - save: function(app_id) { - if(!this.data) { - console.trace(); - console.error('This should never happen!'); - } - if(app_id) { - this.file = this.PRIVATE_PATH+app_id+this.PRIVATE_EXT; - try { - fs.writeFileSync(path.join(home,this.file), JSON.stringify(this.data, null, 2)); - } catch(e) { - console.error('Unable to save private settings file:', e); - } - } - }, - get: function(k) { - if(k) { - return this.data[k]; - } else { - return this.data; - } - }, - set: function(k, v) { - if(!this.data) { - this.data = PRIVATE_DEFAULT; - } - this.data[k] = v; - }, - remove: function(k) { - if(!this.data) { - this.data = PRIVATE_DEFAULT; - } - this.data[k] = ''; - } -}; diff --git a/lib/ionic/project.js b/lib/ionic/project.js index ebf6130b4d..5b58da3c72 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -8,24 +8,20 @@ module.exports = { name: '', email: '', app_id: '', - package_name: '', }, load: function() { - this.file = this.PROJECT_FILE; + this.file = this.PROJECT_FILE; + if(fs.existsSync(this.file)) { - this.data = JSON.parse(fs.readFileSync(this.file)) + this.data = JSON.parse(fs.readFileSync(this.file)); + } else { if(fs.existsSync('www')) { var parts = path.resolve('./').split(path.sep); var dirname = parts[parts.length-1]; - console.log('We have a www folder in the', dirname, 'project'); this.create(dirname); this.save('./'); } - /* - Ionic.fail('Could not find your ' + this.file + ' file!'+ - ' Please run this command in the root of your ionic project.'); - */ } return this; }, @@ -38,9 +34,9 @@ module.exports = { return this; }, save: function(targetPath) { - if(!this.data) { + if(!this.data) { console.trace(); - console.error('This should never happen!'); + console.error('This should never happen!'); } try { fs.writeFileSync((targetPath?targetPath + '/':'') + this.PROJECT_FILE, JSON.stringify(this.data, null, 2)); @@ -60,13 +56,13 @@ module.exports = { }, set: function(k, v) { if(!this.data) { - this.data = PROJECT_DEFAULT; + this.data = this.PROJECT_DEFAULT; } this.data[k] = v; }, remove: function(k) { if(!this.data) { - this.data = PROJECT_DEFAULT; + this.data = this.PROJECT_DEFAULT; } this.data[k] = ''; } diff --git a/lib/ionic/store.js b/lib/ionic/store.js new file mode 100644 index 0000000000..752864fe90 --- /dev/null +++ b/lib/ionic/store.js @@ -0,0 +1,55 @@ +var fs = require('fs'), + path = require('path'); + + +var IonicStore = function(fileName) { + this.data = {}; + + if(!fileName) return this; + + this.fileName = fileName; + if(fileName.indexOf('.') < 0) { + this.fileName += '.data' + } + + this.homeDir = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH; + + this.privateDir = path.join(this.homeDir, '.ionic'); + + if(!fs.existsSync(this.privateDir)) { + fs.mkdirSync(this.privateDir); + } + + this.filePath = path.join(this.privateDir, this.fileName); + + try { + this.data = JSON.parse(fs.readFileSync(this.filePath)); + } catch(e) {} + + return this; +}; + +IonicStore.prototype.get = function(k) { + if(k) { + return this.data[k]; + } + return this.data; +}; + +IonicStore.prototype.set = function(k, v) { + this.data[k] = v; +}; + +IonicStore.prototype.remove = function(k) { + delete this.data[k]; +}; + +IonicStore.prototype.save = function() { + try { + fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2)); + } catch(e) { + console.error('Unable to save ionic data:', this.filePath, e); + } +}; + +exports.IonicStore = IonicStore; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 9af0f1a85e..32bb5ead03 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -10,8 +10,7 @@ var fs = require('fs'), IonicLoginTask = require('./login').IonicLoginTask, Q = require('q'); -var IonicUploadTask = function() { -} +var IonicUploadTask = function() {}; IonicUploadTask.HELP_LINE = 'Upload an Ionic project to the Ionic Platform (requires login)'; @@ -23,12 +22,11 @@ IonicUploadTask.prototype.run = function(ionic, callback) { var login = new IonicLoginTask(); login.get(ionic, function(jar) { - - console.log('Zipping...'); + var TEMP_FILENAME = 'www.zip'; IonicStats.t('upload', {}); - var zip = fs.createWriteStream('www.zip'); + var zip = fs.createWriteStream(TEMP_FILENAME); var archive = archiver('zip'); archive.pipe(zip); @@ -44,64 +42,72 @@ IonicUploadTask.prototype.run = function(ionic, callback) { }); zip.on('close', function() { - console.log('Done'); if(project.get('app_id')) { - console.log('Uploading app (id: ' + project.get('app_id') + ')'); + console.log( ('\nUploading app (' + project.get('app_id') + ')...').bold.grey ); } else { - console.log('Uploading app.'); + console.log('\nUploading new app...'.bold.grey); } var form = new FormData(); form.append('name', project.get('name')); form.append('csrfmiddlewaretoken', jar.cookies[0].value); - form.append('app_file', fs.createReadStream(path.resolve('www.zip')), {filename: 'www.zip', contentType: 'application/zip'}); - // form.append('app_file', zip.toBuffer(), {filename: 'www.zip', contentType: 'application/zip'}); + form.append('app_file', fs.createReadStream(path.resolve(TEMP_FILENAME)), {filename: TEMP_FILENAME, contentType: 'application/zip'}); - var url = ionic.IONIC_DASH + 'projects/' + project.get('app_id'); + var url = ionic.IONIC_DASH + ionic.IONIC_API + 'app/upload/' + project.get('app_id'); var params = parseUrl(url); form.submit({ + protocol: params.protocol, hostname: params.hostname, port: params.port, path: params.path, headers: form.getHeaders({ cookie: jar.cookies.map(function (c) { - return c.name + "=" + encodeURIComponent(c.value) + return c.name + "=" + encodeURIComponent(c.value); }).join("; ") }) }, function(err, response) { - rm('-f', 'www.zip'); + + rm('-f', TEMP_FILENAME); if(err) { ionic.fail("Error uploading: " + err); } - if(response.statusCode == 302) { - if(response.headers.location.indexOf('login?next=') >= 0) { - console.error('Session expired. Please log in again and run this command again.'); - q.reject('not_logged_in'); - return; - } - console.log('Done!'.info.bold); - - var redirectPath = parseUrl(response.headers.location); - project.set('app_id', redirectPath.pathname.match(/^\/projects\/(\w+)\/?$/)[1]); - project.save(); - - if(callback) { - callback(); - }; - } else if(response.statusCode === 200) { - console.log('Got response', response.statusCode); - callback && callback(); - } else { - if(response.headers['content-type'] == 'application/json') { - response.on('data', function(chunk) { - console.log(String(chunk)); - }); + response.setEncoding('utf8'); + response.on("data", function(data) { + try { + var d = JSON.parse(data); + if(d.errors && d.errors.length) { + for (var j = 0; j < d.errors.length; j++) { + console.log( (d.errors[j]).bold.error ); + } + q.reject('upload_error'); + ionic.fail('Unable to upload app'); + } + + if(response.statusCode == 200) { + // Success + project.set('app_id', d.app_id); + project.save(); + console.log( ('Successfully uploaded (' + project.get('app_id') + ')\n').bold.grey ); + + if(callback) { + callback(); + } + + } else if(response.statusCode == 401) { + console.error( ('Session expired. Please log in again and run this command again.').red ); + q.reject('not_logged_in'); + + } else { + q.reject('upload_error'); + } + + } catch(parseEx) { + q.reject('upload_error'); + ionic.fail('Error upload response: ' + parseEx); } - console.error('Unable to upload. HTTP response:', response.statusCode); - q.reject(response); - } + }); q.resolve(callback); }); diff --git a/package.json b/package.json index c02d9aaa19..6c196a4b7f 100644 --- a/package.json +++ b/package.json @@ -19,25 +19,42 @@ "type": "git", "url": "https://github.com/driftyco/ionic-cli.git" }, - "author": "Max Lynch and Peter Collins ", + "contributors": [ + { + "name": "Max Lynch", + "email": "max@drifty.com", + "web": "https://twitter.com/maxlynch" + }, + { + "name": "Peter Collins", + "email": "peter@drifty.com", + "web": "https://twitter.com/SomethingNew2_0" + }, + { + "name": "Adam Bradley", + "web": "https://twitter.com/adamdbradley" + } + ], "license": "MIT", "dependencies": { "archiver": "0.5.1", + "colors": "^0.6.2", + "connect": "^2.14.5", + "connect-livereload": "^0.4.0", "event-stream": "3.0.x", "form-data": "~0.1.0", "ncp": "0.4.2", + "npm": "^1.4.6", + "open": "0.0.5", "optimist": "0.6.0", "prompt": "0.2.12", + "progress": "1.1.7", + "q": "^1.0.1", "request": "2.27.0", "shelljs": "0.2.6", - "unzip": "0.1.9", - "colors": "^0.6.2", - "q": "^1.0.1", - "npm": "^1.4.6", - "connect": "^2.14.5", - "open": "0.0.5", "tiny-lr-fork": "0.0.5", - "connect-livereload": "^0.4.0", - "vinyl-fs": "^0.1.4" + "vinyl-fs": "^0.1.4", + "unzip": "0.1.9", + "xml2js": "^0.4.4" } } From 2ec45308e648ceb879c7b7d27925d98c2d03714b Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Thu, 10 Jul 2014 09:45:15 -0500 Subject: [PATCH 122/850] Master --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c196a4b7f..bbd034e4ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.14", + "version": "1.0.15", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From f11a774a65b5d7728dc12a302cf1ed1f3e005491 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 11 Jul 2014 09:21:00 -0500 Subject: [PATCH 123/850] packaging an app --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 20031cea44..5b2be158dc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ There are three choices of templates. * Side-Menu (sidemenu) * Tabs (tabs) * Blank (blank) - + ## Testing in a Browser ```bash @@ -49,8 +49,22 @@ $ ionic emulate ios ```bash $ ionic run ios + + +## Packaging an app (beta) + +Using Ionic's service, you can compile and package your project into an app-store ready app without +requiring native SDKs on your machine. + +```bash +$ ionic package debug android ``` +The third argument can be either `debug` or `release`, and the last argument can be either `android` or `ios`. + + +## Cordova Commands + Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better. From 7d227350897d4fd49d06d92d79237baa05bcaa80 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 11 Jul 2014 09:26:41 -0500 Subject: [PATCH 124/850] fix broken md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5b2be158dc..158d3afd24 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ $ ionic emulate ios ```bash $ ionic run ios +``` ## Packaging an app (beta) From b58092fe6551e427cbfa6d0b73b4cf2668c5fd89 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 11 Jul 2014 13:15:09 -0500 Subject: [PATCH 125/850] load plugins through package.json files --- lib/ionic/package.js | 54 +++++++++++++++----------------------------- lib/ionic/upload.js | 7 +++++- package.json | 5 ++-- 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 9ec8f31a94..17321fed5a 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -104,44 +104,20 @@ IonicPackageTask.prototype.loadProject = function() { IonicPackageTask.prototype.loadPlugins = function() { - var self = this; - var parseString = require('xml2js').parseString; - var cp = spawn("cordova", ['plugins']); - - cp.stdout.on("data", function (c) { - self.plugins = []; - - var pluginNames = JSON.parse(c.toString().replace(/'/g, '"')); + this.plugins = []; - for(var x=0; x Date: Sat, 12 Jul 2014 11:54:12 -0500 Subject: [PATCH 126/850] update config.xml from cmd args --- lib/ionic/package.js | 7 ++- lib/ionic/start.js | 127 ++++++++++++++++++++++++++++--------------- package.json | 5 +- 3 files changed, 91 insertions(+), 48 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 17321fed5a..745f2be9c0 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -82,7 +82,8 @@ IonicPackageTask.prototype.clearSigning = function() { IonicPackageTask.prototype.loadProject = function() { - console.log( ("Loading " + this.project.get('name')).bold.yellow ); + var appName = this.project.get('name') || "app"; + console.log( ("Loading " + appName).bold.yellow ); if(argv._.length < 3) { IonicPackageTask.prototype._printUsage(); @@ -353,8 +354,10 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { if(d.errors && d.errors.length) { for (var j = 0; j < d.errors.length; j++) { - process.stderr.write(d.errors[j] + '\n'); + console.log( d.errors[j].bold.error ); } + console.log(''); + } else if(d.build_status_url) { process.stderr.write('.'); setTimeout(function(){ diff --git a/lib/ionic/start.js b/lib/ionic/start.js index e21c5fb5b7..2f10ba1771 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -9,6 +9,7 @@ var fs = require('fs'), colors = require('colors'), spawn = require('child_process').spawn, Q = require('q'), + xml2js = require('xml2js'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -28,8 +29,7 @@ fs.mkdirParent = function(dirPath, mode, callback) { }); }; -var IonicStartTask = function() { -} +var IonicStartTask = function() {}; // The URL for the cordova wrapper project IonicStartTask.WRAPPER_REPO_NAME = 'ionic-app-base'; @@ -39,23 +39,30 @@ IonicStartTask.HELP_LINE = 'Start a new Ionic project with the given name.'; IonicStartTask.prototype = new IonicTask(); IonicStartTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic start appName [starterProject(blank,tabs,sidemenu)]\n'); + process.stderr.write('\nUsage: ionic start myapp\n'); + process.stderr.write('\nCommand-line Flags/Options:\n\n') + process.stderr.write(' -t, --template ...... starter template to use (tabs, sidemenu, blank)\n'); + process.stderr.write(' -a, --app ................... your app\'s name (Use quotes around the name)\n'); + process.stderr.write(' -p, --package ........... package name, such as "com.mycompany.myapp"\n'); }; IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No app name specified, exiting.'); + this._printUsage(); + ionic.fail('\nInvalid command'); } - // Grab the name of the app - this.appName = argv._[1]; + // Grab the app's relative directory name + this.appDirectory = argv._[1]; - // Grab the target path from the command line, or use this as the app name - var targetPathName = this.appName; + // Grab the name of the app from -a or --app. Defaults to appDirectory if none provided + this.appName = argv.a || argv.app || this.appDirectory; + this.packageName = argv.p || argv.package; - var starterProject = argv._[2] || 'tabs'; + // start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs + var starterProject = argv.t || argv.template || argv._[2] || 'tabs'; - this.targetPath = path.resolve(this.appName); + this.targetPath = path.resolve(this.appDirectory); // Make sure to create this, or ask them if they want to override it if(this._checkTargetPath() === false) { @@ -68,7 +75,7 @@ IonicStartTask.prototype.run = function(ionic) { fs.mkdirSync(this.targetPath); this._fetchAndWriteSeed(starterProject.toLowerCase()); - this._writeConfig(ionic); + this._writeProjectFile(ionic); }; @@ -102,18 +109,55 @@ IonicStartTask.prototype._installCordovaPlugins = function() { console.log('Initializing cordova project.'.info.bold); exec('cordova plugin add org.apache.cordova.device && ' + 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard' - , function(err, stdout, stderr) { - if(err) { - q.reject(stderr); - } else { - q.resolve(stdout); - } + 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard', + function(err, stdout, stderr) { + if(err) { + q.reject(stderr); + } else { + q.resolve(stdout); + } }); return q.promise; }; +IonicStartTask.prototype._updateConfigXml = function() { + var self = this; + console.log('Update config.xml'.info.bold); + + try { + var configXmlPath = self.targetPath + '/config.xml'; + var configString = fs.readFileSync(configXmlPath, { encoding: 'utf8' }); + + var parseString = xml2js.parseString; + parseString(configString, function (err, jsonConfig) { + if(err) { + Ionic.fail('Error parsing config.xml: ' + err); + } + + if(!self.packageName) { + var packageName = self.appDirectory + Math.round((Math.random() * 899999) + 100000); + self.packageName = 'com.ionicframework.' + packageName.replace(/\./g, ''); + } + + jsonConfig.widget.$.id = self.packageName.replace(/ /g, '').replace(/-/g, '').replace(/_/g, '').toLowerCase().trim(); + jsonConfig.widget.name = [ self.appName ]; + + var xmlBuilder = new xml2js.Builder(); + configString = xmlBuilder.buildObject(jsonConfig); + + fs.writeFile(configXmlPath, configString, function(err) { + if(err) { + Ionic.fail('Error saving config.xml file: ' + err); + } + }); + }); + + } catch(e) { + Ionic.fail('Error updating config.xml file: ' + e); + } +}; + IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var self = this; @@ -137,34 +181,29 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var pluginQ = Q.defer(); // Install dependencies for the starter project - //Ionic.spawnPromise('npm', ['install', '--quiet']).then(function() { - // Move the content of this repo into the www folder - cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); + // Move the content of this repo into the www folder + cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); - // Copy the root config file to the www folder - // cp(self.targetPath + '/config.xml', 'www'); + // Clean up start template folder + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); - // Clean up start template folder - rm('-rf', self.targetPath + '/' + repoFolderName + '/'); + // update the config.xml file from cmd line args + self._updateConfigXml(); - self._installCordovaPlugins().then(function(output) { - pluginQ.resolve(stdout); - }, function(err) { - pluginQ.reject(err); - }); - - pluginQ.promise.then(function() { - self._printQuickHelp(self.appName); - }, function(err) { - Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); - }); + self._installCordovaPlugins().then(function(output) { + pluginQ.resolve(stdout); + }, function(err) { + pluginQ.reject(err); + }); - IonicStats.t('start', {}); - /* - }).fail(function(err, stderr) {; - Ionic.fail('Unable to install Ionic dependencies. Please make sure you\'ve installed cordova, and gulp globally by running:\nsudo npm install -g cordova gulp. Error:\n'.error.bold + err + '\n' + stderr); + pluginQ.promise.then(function() { + self._printQuickHelp(self.appDirectory); + }, function(err) { + Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); }); - */ + + IonicStats.t('start', {}); + }).catch(function(err) { console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode, err); console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'.error.bold); @@ -191,13 +230,13 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\n\nFor more help, visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold); }; -IonicStartTask.prototype._writeConfig = function(ionic) { - var project = IonicProject.create(); +IonicStartTask.prototype._writeProjectFile = function(ionic) { + var project = IonicProject.create(); project.set('name', this.appName); project.save(this.targetPath); }; -IonicStartTask.prototype._checkTargetPath = function() { +IonicStartTask.prototype._checkTargetPath = function() { if(fs.existsSync(this.targetPath)) { process.stderr.write('The directory '.error.bold + this.targetPath + ' already exists, please remove it if you would like to create a new ionic project there.\n'.error.bold); return false; diff --git a/package.json b/package.json index 9845a893ef..e70bf44935 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.16", + "version": "1.0.17", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -53,7 +53,8 @@ "request": "2.27.0", "shelljs": "0.2.6", "tiny-lr-fork": "0.0.5", + "unzip": "0.1.9", "vinyl-fs": "^0.1.4", - "unzip": "0.1.9" + "xml2js": "^0.4.4" } } From 53a866ba01855d085210f34720a3581003f1318f Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 12 Jul 2014 18:33:31 -0500 Subject: [PATCH 127/850] start cmd line options --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 158d3afd24..d18c0c0637 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,18 @@ $ sudo npm install -g ionic ```bash $ ionic start myApp [template] ``` -There are three choices of templates. + +There are three choices of templates: * Side-Menu (sidemenu) * Tabs (tabs) * Blank (blank) + +Command-line flags/options: + + -a, --app ................... your app's name (Use quotes around the name) + -p, --package ........... package name, such as "com.mycompany.myapp" + ## Testing in a Browser From 6fad60218f1f433953024e83d7d4bfcd693d19dd Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 11:39:02 -0500 Subject: [PATCH 128/850] package improvements, added cmd line opts --- README.md | 2 +- lib/ionic.js | 215 +++++++++++++++++++++++++++----- lib/ionic/build.js | 14 +-- lib/ionic/emulate.js | 14 +-- lib/ionic/login.js | 183 +++++++++++++++------------ lib/ionic/package.js | 281 +++++++++++++++++++++++++----------------- lib/ionic/platform.js | 45 ++++--- lib/ionic/project.js | 3 +- lib/ionic/run.js | 14 +-- lib/ionic/serve.js | 46 ++++--- lib/ionic/start.js | 25 ++-- lib/ionic/store.js | 2 +- lib/ionic/upload.js | 8 +- package.json | 2 +- 14 files changed, 538 insertions(+), 316 deletions(-) diff --git a/README.md b/README.md index d18c0c0637..09bcb96306 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Ionic-Cli ========= -The Ionic Framework command line utility makes it easy to start, build, run, and emulate [Ionic](http://ionicframework.com/) apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. +The Ionic Framework command line utility makes it easy to start, build, run, and emulate [Ionic](http://ionicframework.com/) apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. Use `ionic --help` for detailed task information. ## Installing diff --git a/lib/ionic.js b/lib/ionic.js index 6604d4a192..96d419a3fd 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -53,61 +53,109 @@ var fs = require('fs'), argv = require('optimist').argv; var TASKS = [ + { + title: 'start', + name: 'start', + summary: 'Starts a new Ionic project in the specified PATH', + args: { + '': 'directory for the new project', + '[TEMPLATE]': 'Starter template to use (tabs, sidemenu, blank)' + }, + options: { + '--app-name|-a': 'Human readable app\'s name (Use quotes around the name)', + '--id|-i': 'Package name set as config' + }, + task: IonicStartTask + }, { title: 'serve', name: 'serve', - usage: '', + summary: 'Start a local development server for app dev and testing', + args: { + '[http-port]': '', + '[livereload-port]': '' + }, + options: { + '--nobrowser|-b': 'Disable auto browser launch', + '--nolivereload|-r': 'Do not start live reload' + }, task: IonicServeTask }, { - title: 'start', - name: 'start', - usage: 'appname', - task: IonicStartTask + title: 'platform', + name: 'platform', + summary: 'Add platform target for building an Ionic app', + args: { + '': '' + }, + task: IonicPlatformTask }, { title: 'emulate', name: 'emulate', - usage: 'emulate', + summary: 'Emulate an Ionic project on a simulator or emulator', + args: { + '': '' + }, task: IonicEmulateTask }, { title: 'run', name: 'run', - usage: 'run', + summary: 'Run an ionic project on a connected device', + args: { + '': '' + }, task: IonicRunTask }, { title: 'build', name: 'build', - usage: 'build', + summary: 'Locally build an ionic project for a given platform', + args: { + '': '' + }, task: IonicBuildTask }, { - title: 'platform', - name: 'platform', - usage: 'platform', - task: IonicPlatformTask - }, - { - title: 'login', - name: 'login', - usage: '[email]', - task: IonicLoginTask + title: 'package', + name: 'package', + alt: ['pack'], + summary: 'Package an app using the Ionic Build service', + args: { + '': '"ios" or "android"', + '': '"debug" or "release"' + }, + options: { + '--android-keystore-file|-k': 'Android keystore file', + '--android-keystore-alias|-a': 'Android keystore alias', + '--android-keystore-password|-w': 'Android keystore password', + '--android-key-password|-r': 'Android key password', + '--ios-certificate-file|-c': 'iOS certificate file', + '--ios-certificate-password|-d': 'iOS certificate password', + '--ios-profile-file|-f': 'iOS profile file', + '--output|-o': 'Path to save the packaged app', + '--clear-signing|-l': 'Clear out all signing data from Ionic server', + '--email|-e': 'Ionic account email', + '--password|-p': 'Ionic account password' + }, + task: IonicPackageTask }, { title: 'upload', name: 'upload', + summary: 'Upload an app to your Ionic account', + options: { + '--email|-e': 'Ionic account email', + '--password|-p': 'Ionic account password' + }, alt: ['up'], - usage: '', task: IonicUploadTask }, { - title: 'package', - name: 'package', - alt: ['pack'], - usage: 'mode platform', - task: IonicPackageTask + title: 'login', + name: 'login', + task: IonicLoginTask } ]; @@ -142,13 +190,101 @@ Ionic = { } }, - _printGenericUsage: function() { + printUsage: function(d) { + var w = function(s) { + process.stdout.write(s); + }; + + w('\n'); + + var rightColumn = 45; + var dots = ''; + var indent = ''; + var x, arg; + + var taskArgs = d.name; + + for(arg in d.args) { + taskArgs += ' ' + arg; + } + + w(taskArgs.green); + + while( (taskArgs + dots).length < rightColumn + 1) { + dots += '.'; + } + + w(' ' + dots.grey + ' '); + + w(d.summary); + + for(arg in d.args) { + if( !d.args[arg] ) continue; + var argLine = arg; + + indent = ''; + w('\n'); + while(indent.length < rightColumn) { + indent += ' '; + } + w( (indent + ' ' + argLine + ' = ' + d.args[arg]).grey ); + } + + indent = ''; + while(indent.length < d.name.length + 1) { + indent += ' '; + } + + for(var opt in d.options) { + w('\n'); + dots = ''; + + var optLine = indent + '[' + opt + '] '; + + w(optLine.yellow); + + while( (dots.length + optLine.length - 2) < rightColumn) { + dots += '.'; + } + w(dots.grey + ' '); + + w(d.options[opt].grey); + } + + w('\n'); + }, + + _printAvailableTasks: function() { + this._printIonic(); + process.stderr.write('\nUsage: ionic task args\n\n===============\n\n'); + process.stderr.write('Available tasks: '.bold); + process.stderr.write('(use --help or -h for more info)\n\n'); + + for(var i = 0; i < TASKS.length; i++) { + var task = TASKS[i]; + if(task.summary) { + var name = ' ' + task.name + ' '; + var dots = ''; + while((name + dots).length < 20) { + dots += '.'; + } + process.stderr.write(name.green + dots.grey + ' ' + task.summary + '\n'); + } + } + + process.stderr.write('\n'); + process.exit(1); + }, + + _printHelpLines: function() { this._printIonic(); - process.stderr.write('Usage: ionic task args\n\n===============\n\nAvailable tasks:\n\n'); + process.stderr.write('\n===================\n'); for(var i = 0; i < TASKS.length; i++) { var task = TASKS[i]; - process.stderr.write(' ' + task.name + ' - ' + task.task.HELP_LINE + '\n'); + if(task.summary) { + this.printUsage(task); + } } process.stderr.write('\n'); @@ -174,25 +310,38 @@ Ionic = { }, run: function() { - if(argv.version) { + if(argv.version || argv.v) { console.log('Ionic CLI version ' + settings.version); process.exit(0); } + if(argv.help || argv.h) { + return this._printHelpLines(); + } + var task = this._tryBuildingTask(); if(!task) { - return this._printGenericUsage(); + return this._printAvailableTasks(); } - console.log('\nRunning', task.title.info.bold, 'task...'); - var taskObj = new task.task(); taskObj.run(this); }, - fail: function(msg) { + fail: function(msg, taskHelp) { process.stderr.write(msg.error.bold); - process.stderr.write('\n\n'); + process.stderr.write('\n'); + if(taskHelp) { + for(var i = 0; i < TASKS.length; i++) { + var task = TASKS[i]; + if(task.name == taskHelp) { + this.printUsage(task); + process.stderr.write('\n'); + break; + } + } + } + process.stderr.write('\n'); process.exit(1); }, diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 04e871ed02..60a91c6d8c 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -9,27 +9,19 @@ var fs = require('fs'), IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats; -var IonicBuildTask = function() { -} - -IonicBuildTask.HELP_LINE = 'Locally build an ionic project for a given platform'; +var IonicBuildTask = function() {}; IonicBuildTask.prototype = new IonicTask(); -IonicBuildTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic build platform [more platforms,...]\n'); -} - IonicBuildTask.prototype.run = function(ionic) { if(argv._.length < 2) { - IonicBuildTask.prototype._printUsage(); - ionic.fail('No platforms specified, exiting.'); + ionic.fail('No platforms specified.', 'build'); } var platforms = argv._.slice(1); if(platforms.length < 1) { - ionic.fail('No platforms specified, exiting.'); + ionic.fail('No platforms specified.', 'build'); } IonicStats.t('build', { 'platform': platforms.join(',') }); diff --git a/lib/ionic/emulate.js b/lib/ionic/emulate.js index 0c1934b12e..ca30dffb5c 100644 --- a/lib/ionic/emulate.js +++ b/lib/ionic/emulate.js @@ -10,29 +10,21 @@ var fs = require('fs'), var argv = require('optimist').argv; -var IonicEmulateTask = function() { -} - -IonicEmulateTask.HELP_LINE = 'Emulate an ionic project on a simulator or emulator.'; +var IonicEmulateTask = function() {}; IonicEmulateTask.prototype = new IonicTask(); -IonicEmulateTask.prototype._printUsage = function() { - process.stderr.write('\nUsage: ionic emulate [platform]\n'); -} - IonicEmulateTask.prototype.run = function(ionic) { var patform; if(argv._.length < 2) { - IonicEmulateTask.prototype._printUsage(); - ionic.fail('No platforms specified, exiting.'); + ionic.fail('No platforms specified.', 'emulate'); } var platforms = argv._.slice(1); if(platforms.length < 1) { - ionic.fail('No platforms specified, exiting.'); + ionic.fail('No platforms specified.', 'emulate'); } IonicStats.t('emulate', { 'platform': platforms.join(',') }); diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 0c2290789b..7504c07ff7 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -8,108 +8,139 @@ var fs = require('fs'), var IonicLoginTask = function() {}; -IonicLoginTask.HELP_LINE = 'Login to the Ionic Platform'; - IonicLoginTask.prototype = new IonicTask(); -IonicLoginTask.prototype.run = function(ionic, callback) { - var self = this; +IonicLoginTask.prototype.get = function(ionic, callback) { - var schema = [{ - name: 'email', - pattern: /^[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+(?:\.[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+)*@(?:[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?$/, - message: 'Email for your Ionic Platform login', - required: true - }, { - name: 'password', - hidden: true, - required: true - }]; - - var project = IonicProject.load(); - - // Grab the email for login - if(argv._.length >= 2 && schema[0].pattern.test(argv._[1])) { - this.email = argv._[1].toLowerCase(); - schema.shift(); + if(ionic.jar) { + // already in memory + callback(ionic.jar); + return; } - console.log('\nTo continue, please login to your Ionic account.'.bold.green); - console.log('Don\'t have one? Create a one at: '.grey + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); + this.email = argv.email || argv.e || process.env.IONIC_EMAIL; + this.password = argv.password || argv.p || process.env.IONIC_PASSWORD; - prompt.override = argv; + if(!this.email && this.password) { + ionic.fail('--email or -e command line flag, or IONIC_EMAIL environment variable required'); + } + if(this.email && !this.password) { + ionic.fail('--password or -p command line flag, or IONIC_PASSWORD environment variable required'); + } - prompt.start(); + if(!this.email && !this.password) { + // did not include cmd line flags, check for existing cookies + this.cookieData = new IonicStore('cookies'); + var jar = this.cookieData.get(ionic.IONIC_DASH); - prompt.get(schema, function (err, result) { - if(err) { - ionic.fail('Error logging in: ' + err); + if(jar && jar.cookies && jar.cookies.length) { + for(var i in jar.cookies) { + var cookie = jar.cookies[i]; + if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { + ionic.jar = jar; + callback(jar); + return; + } + } } + } + + this.run(ionic, callback); +}; + +IonicLoginTask.prototype.run = function(ionic, callback) { + var self = this; + + if(!this.email && !this.password) { + + var schema = [{ + name: 'email', + pattern: /^[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+(?:\.[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+)*@(?:[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?$/, + description: 'Email:', + required: true + }, { + name: 'password', + description: 'Password:', + hidden: true, + required: true + }]; + + // prompt for log + console.log('\nTo continue, please login to your Ionic account.'.bold.green); + console.log('Don\'t have one? Create a one at: '.grey + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); + + prompt.override = argv; + prompt.message = ''; + prompt.delimiter = ''; + prompt.start(); + + prompt.get(schema, function (err, result) { + if(err) { + ionic.fail('Error logging in: ' + err); + } + + self.email = result.email; + self.password = result.password; + + self.requestLogIn(ionic, callback, true); + }); + + } else { + // cmd line flag were added, use those instead of a prompt + self.requestLogIn(ionic, callback, false); + } - if(!self.email) { - self.email = result.email.toLowerCase(); +}; + +IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { + var self = this; + + var jar = request.jar(); + request({ + url: ionic.IONIC_DASH + '/login', + jar: jar + }, + function(err, response, body) { + if(err || jar.cookies.length === 0) { + ionic.fail('Error logging in: ' + err); } - self.password = result.password; - var jar = request.jar(); request({ + method: 'POST', url: ionic.IONIC_DASH + '/login', - jar: jar + jar: jar, + form: { + username: self.email.toString().toLowerCase(), + password: self.password, + csrfmiddlewaretoken: jar.cookies[0].value + } }, - function(err, response, body) { - if(err || jar.cookies.length === 0) { + function (err, response, body) { + if(err) { ionic.fail('Error logging in: ' + err); } - request({ - method: 'POST', - url: ionic.IONIC_DASH + '/login', - jar: jar, - form: { - username: self.email, - password: self.password, - csrfmiddlewaretoken: jar.cookies[0].value - } - }, - function (err, response, body) { - if(err) { - ionic.fail('Error logging in: ' + err); - } - // Should be a 304 redirect status code if correct - if(response.statusCode == 200) { - ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); - } + // Should be a 302 redirect status code if correct + if(response.statusCode != 302) { + ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); + } + if(saveCookies) { + // save cookies self.cookieData.set(ionic.IONIC_DASH, jar); self.cookieData.save(); + } - console.log('Logged in! :)'.green); - - if(callback) { - callback(jar); - project.set('email', self.email); - project.save(); - } - }); - }); - }); -}; + // save in memory + ionic.jar = jar; -IonicLoginTask.prototype.get = function(ionic, callback) { - this.cookieData = new IonicStore('cookies'); - var jar = this.cookieData.get(ionic.IONIC_DASH); + console.log('Logged in! :)'.green); - if(jar && jar.cookies && jar.cookies.length) { - for(var i in jar.cookies) { - var cookie = jar.cookies[i]; - if(cookie.name == "sessionid" && new Date(cookie.expires) > new Date()) { + if(callback) { callback(jar); - return; } - } - } - - this.run(ionic, callback); + }); + }); }; exports.IonicLoginTask = IonicLoginTask; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 745f2be9c0..a94e065aa7 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -15,92 +15,58 @@ var fs = require('fs'), var IonicPackageTask = function() {}; -IonicPackageTask.HELP_LINE = 'Package an app using the Ionic Platform Build service (requires login)'; - IonicPackageTask.prototype = new IonicTask(); - -IonicPackageTask.prototype._printUsage = function() { - process.stderr.write('\nUsage:\nionic package mode[debug|release] platform[ios,android]\n'); -}; - - IonicPackageTask.prototype.run = function(ionic) { var self = this; self.ionic = ionic; self.project = IonicProject.load(); + self.inputFiles = {}; + self.inputValues = {}; + self.useCmdArgs = false; - if(argv['clear-signing'] || argv.c) { + if(argv['clear-signing'] || argv.l) { self.clearSigning(); return; } self.loadProject(); + this.getCmdLineOptions(); + var login = new IonicLoginTask(); login.get(self.ionic, function(jar) { self.jar = jar; self.loadAppSigning(function(){ - self.packagePlatforms(self.platforms); + self.initPlatforms(); }); }); }; -IonicPackageTask.prototype.clearSigning = function() { - var self = this; - console.log('Clearing app signing and credential information...'.yellow); - - var appId = self.project.get('app_id'); - - if(!appId) { - self.ionic.fail('App Id is not known'); - } - - var login = new IonicLoginTask(); - login.get(self.ionic, function(jar) { - var options = { - url: self.ionic.IONIC_DASH + self.ionic.IONIC_API + 'app/' + appId + '/signing/clear', - headers: { - cookie: jar.cookies.map(function (c) { - return c.name + "=" + encodeURIComponent(c.value); - }).join("; ") - } - }; - - request(options, function(err, response, body) { - if(err) { - self.ionic.fail("Error clearing app signing: " + err); - } - console.log( ('App (' + appId + ') signing and credential information cleared\n').green ); - }); - }); -}; - - IonicPackageTask.prototype.loadProject = function() { var appName = this.project.get('name') || "app"; - console.log( ("Loading " + appName).bold.yellow ); + console.log( ('Loading ' + appName + '...').bold.yellow ); if(argv._.length < 3) { - IonicPackageTask.prototype._printUsage(); - this.ionic.fail('No platforms or build mode specified.'); + this.ionic.fail('No platforms or build mode specified.', 'package'); } this.mode = argv._[1].toLowerCase(); if(this.mode != 'debug' && this.mode != 'release') { - IonicPackageTask.prototype._printUsage(); - this.ionic.fail('Package build mode must be "debug" or "release".'); + this.ionic.fail('Package build mode must be "debug" or "release".', 'package'); } this.platforms = argv._.slice(2); if(this.platforms.length < 1) { - this.ionic.fail('No platforms specified.'); + this.ionic.fail('No platforms specified.', 'package'); } + + this.loadPlugins(); }; @@ -122,9 +88,48 @@ IonicPackageTask.prototype.loadPlugins = function() { }; +IonicPackageTask.prototype.getCmdLineOptions = function() { + var self = this; + + function getCmdArgValue(propertyName, shortName) { + var value = argv[propertyName] || argv[shortName]; + if(value) { + self.inputValues[propertyName] = value; + self.useCmdArgs = true; + } + } + + function getCmdArgFile(propertyName, shortName) { + var value = argv[propertyName] || argv[shortName]; + if(value) { + if(!fileExists(value)) { + self.ionic.fail("Unable to find file: " + argv[propertyName]); + } + self.inputFiles[propertyName] = value; + self.useCmdArgs = true; + } + } + + getCmdArgValue('android-keystore-alias', 'a'); + getCmdArgValue('android-keystore-password', 'w'); + getCmdArgValue('android-key-password', 'r'); + getCmdArgValue('ios-certificate-password', 'd'); + + getCmdArgFile('android-keystore-file', 'k'); + getCmdArgFile('ios-certificate-file', 'c'); + getCmdArgFile('ios-profile-file', 'f'); +}; + + IonicPackageTask.prototype.loadAppSigning = function(callback) { var self = this; + if(self.useCmdArgs) { + // if they used cmd line args, don't bother checking + callback(); + return; + } + if(!self.project.get('app_id')) { // if its the first load we won't have an appId yet callback(); @@ -134,6 +139,7 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { var privateData = new IonicStore(self.project.get('app_id')); var cck = privateData.get('cck'); if(!cck) { + // if there's no client key don't bother callback(); return; } @@ -149,8 +155,11 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { }; request(options, function(err, response, body) { - if(!err && response.statusCode == 200) { + if(err) { + self.ionic.fail("Error loading app signing info: " + err); + } + if(response.statusCode == 200) { try { self.signing = JSON.parse(body); @@ -161,7 +170,6 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { } catch(e) { self.ionic.fail("Error parsing app signing: " + e); } - } callback(); @@ -169,92 +177,107 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { }; -IonicPackageTask.prototype.packagePlatforms = function(platforms) { +IonicPackageTask.prototype.initPlatforms = function() { var self = this; - prompt.override = argv; - prompt.start(); + if(self.useCmdArgs) { + self.packagePlatforms(); - var promptProperties = self.buildPromptProperties(platforms); + } else { + prompt.override = argv; + prompt.message = ''; + prompt.delimiter = ''; + prompt.start(); - prompt.get({properties: promptProperties}, function (err, promptResult) { - if(err) { - self.ionic.fail('Error packaging: ' + err); - } + var promptProperties = self.buildPromptProperties(); + + prompt.get({properties: promptProperties}, function (err, promptResult) { + if(err) { + self.ionic.fail('Error packaging: ' + err); + } - self.loadPlugins(); + for(var propertyName in promptResult) { + var promptValue = promptResult[propertyName]; + if( !promptValue ) continue; - var upload = new IonicUploadTask(); - upload.run(self.ionic, function() { - for(var x=0; x ...... starter template to use (tabs, sidemenu, blank)\n'); - process.stderr.write(' -a, --app ................... your app\'s name (Use quotes around the name)\n'); - process.stderr.write(' -p, --package ........... package name, such as "com.mycompany.myapp"\n'); -}; - IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { - this._printUsage(); - ionic.fail('\nInvalid command'); + ionic.fail('Invalid command', 'start'); } // Grab the app's relative directory name this.appDirectory = argv._[1]; // Grab the name of the app from -a or --app. Defaults to appDirectory if none provided - this.appName = argv.a || argv.app || this.appDirectory; - this.packageName = argv.p || argv.package; + this.appName = argv['app-name'] || argv.a; + if(!this.appName) { + var appNameSplit = this.appDirectory.split('/'); + appNameSplit = appNameSplit[ appNameSplit.length -1 ].split('\\'); + this.appName = appNameSplit[ appNameSplit.length -1 ]; + } + + this.packageName = argv.id || argv.i; // start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs - var starterProject = argv.t || argv.template || argv._[2] || 'tabs'; + var starterProject = argv.template || argv.t || argv._[2] || 'tabs'; this.targetPath = path.resolve(this.appDirectory); diff --git a/lib/ionic/store.js b/lib/ionic/store.js index 752864fe90..0743efc0c8 100644 --- a/lib/ionic/store.js +++ b/lib/ionic/store.js @@ -9,7 +9,7 @@ var IonicStore = function(fileName) { this.fileName = fileName; if(fileName.indexOf('.') < 0) { - this.fileName += '.data' + this.fileName += '.data'; } this.homeDir = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 4a262354e7..08ac6ee9e3 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -12,8 +12,6 @@ var fs = require('fs'), var IonicUploadTask = function() {}; -IonicUploadTask.HELP_LINE = 'Upload an Ionic project to the Ionic Platform (requires login)'; - IonicUploadTask.prototype = new IonicTask(); IonicUploadTask.prototype.run = function(ionic, callback) { @@ -42,11 +40,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { }); zip.on('close', function() { - if(project.get('app_id')) { - console.log( ('\nUploading app (' + project.get('app_id') + ')...').bold.grey ); - } else { - console.log('\nUploading new app...'.bold.grey); - } + console.log('\nUploading app...'.bold.grey); var form = new FormData(); form.append('name', project.get('name')); diff --git a/package.json b/package.json index e70bf44935..b403524295 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.0.17", + "version": "1.1.0", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From ac98c44f816d20cb64d6513cb53160ed64eb4a7b Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 11:46:44 -0500 Subject: [PATCH 129/850] version # in printout --- lib/ionic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic.js b/lib/ionic.js index 96d419a3fd..0911f82f18 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -301,7 +301,7 @@ Ionic = { w(' _ ___ _ __ _ ___ \n'); w(' | |/ _ \\| \'_ \\| |/ __|\n'); w(' | | (_) | | | | | (__ \n'); - w(' |_|\\___/|_| |_|_|\\___|\n'); + w(' |_|\\___/|_| |_|_|\\___| v'+ settings.version + '\n'); }, From 3e0e96da3453b9bad846ebd62fd8c5090aa89917 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 11:50:50 -0500 Subject: [PATCH 130/850] 1.1.0-beta1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b403524295..95065829ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0", + "version": "1.1.0-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 8a7b792ed62337efde3c46d78e5fada7bf0f84be Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 12:07:11 -0500 Subject: [PATCH 131/850] fix order of package args --- lib/ionic.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 0911f82f18..6d2cc29d29 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -123,8 +123,8 @@ var TASKS = [ alt: ['pack'], summary: 'Package an app using the Ionic Build service', args: { - '': '"ios" or "android"', - '': '"debug" or "release"' + '': '"debug" or "release"', + '': '"ios" or "android"' }, options: { '--android-keystore-file|-k': 'Android keystore file', diff --git a/package.json b/package.json index 95065829ec..61e7c55546 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0-beta1", + "version": "1.1.0-beta2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 6084491436872d79554ad4c8da3d0d7ff76d61c2 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 12:34:20 -0500 Subject: [PATCH 132/850] fix cookieData --- lib/ionic.js | 2 +- lib/ionic/login.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 6d2cc29d29..5b10a38354 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -62,7 +62,7 @@ var TASKS = [ '[TEMPLATE]': 'Starter template to use (tabs, sidemenu, blank)' }, options: { - '--app-name|-a': 'Human readable app\'s name (Use quotes around the name)', + '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', '--id|-i': 'Package name set as config' }, task: IonicStartTask diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 7504c07ff7..a2d3983eef 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -11,6 +11,7 @@ var IonicLoginTask = function() {}; IonicLoginTask.prototype = new IonicTask(); IonicLoginTask.prototype.get = function(ionic, callback) { + this.cookieData = new IonicStore('cookies'); if(ionic.jar) { // already in memory @@ -30,7 +31,6 @@ IonicLoginTask.prototype.get = function(ionic, callback) { if(!this.email && !this.password) { // did not include cmd line flags, check for existing cookies - this.cookieData = new IonicStore('cookies'); var jar = this.cookieData.get(ionic.IONIC_DASH); if(jar && jar.cookies && jar.cookies.length) { diff --git a/package.json b/package.json index 61e7c55546..bd6dfbe450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0-beta2", + "version": "1.1.0-beta3", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 9b0b5caf0029de865111045ca08e8ed17f897f8a Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 12:42:34 -0500 Subject: [PATCH 133/850] fix cookieData store save --- lib/ionic/login.js | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index a2d3983eef..43deb50b83 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -127,6 +127,9 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { if(saveCookies) { // save cookies + if(!self.cookieData) { + self.cookieData = new IonicStore('cookies'); + } self.cookieData.set(ionic.IONIC_DASH, jar); self.cookieData.save(); } diff --git a/package.json b/package.json index bd6dfbe450..ac6e047701 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0-beta3", + "version": "1.1.0-beta4", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From db4fe047b780147e880f2f10a211199b556c5085 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 13:32:42 -0500 Subject: [PATCH 134/850] make sure there's a www directory --- lib/ionic/serve.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index d7a0e0d08d..6d52b8b08c 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -1,4 +1,5 @@ var fs = require('fs'), + path = require('path'), argv = require('optimist').argv, connect = require('connect'), open = require('open'), @@ -28,18 +29,18 @@ IonicServeTask.prototype.run = function(ionic) { this._start(ionic); }; -IonicServeTask.prototype._changed = function(path) { +IonicServeTask.prototype._changed = function(filePath) { // Cleanup the path a bit var pwd = process.cwd(); - path = path.replace(pwd + '/', ''); + filePath = filePath.replace(pwd + '/', ''); - console.log('Changed', path); + console.log( (' changed: ' + filePath).green ); var req = request.post('http://localhost:' + this.liveReloadPort + '/changed', { path: '/changed', method: 'POST', body: JSON.stringify({ - files: [path] + files: [filePath] }) }, function(err, res, body) { if(err) { @@ -52,6 +53,10 @@ IonicServeTask.prototype._start = function(ionic) { var self = this; var app = connect(); + if (!fs.existsSync( path.resolve('www') )) { + ionic.fail('"www" directory cannot be found. Make sure the working directory is an Ionic project.'); + } + if(this.runLivereload) { vfs.watch('www/**/*', { }, function(f) { From bec0c92b7d59ce14d64dd42a7c8d42eaee52044b Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 13:45:10 -0500 Subject: [PATCH 135/850] do not require email, package arg order doesn't matter --- lib/ionic/package.js | 38 ++++++++++++++++++++++++-------------- package.json | 2 +- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index a94e065aa7..7ff3e2e30e 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -55,12 +55,19 @@ IonicPackageTask.prototype.loadProject = function() { this.ionic.fail('No platforms or build mode specified.', 'package'); } - this.mode = argv._[1].toLowerCase(); + this.mode = argv._[2].toLowerCase(); if(this.mode != 'debug' && this.mode != 'release') { - this.ionic.fail('Package build mode must be "debug" or "release".', 'package'); + // ionic package debug android + this.mode = argv._[1].toLowerCase(); + this.platforms = argv._.slice(2); + } else { + // ionic package android debug + this.platforms = [ argv._[1].toLowerCase() ]; } - this.platforms = argv._.slice(2); + if(this.mode != 'debug' && this.mode != 'release') { + this.ionic.fail('Package build mode must be "debug" or "release".', 'package'); + } if(this.platforms.length < 1) { this.ionic.fail('No platforms specified.', 'package'); @@ -73,17 +80,21 @@ IonicPackageTask.prototype.loadProject = function() { IonicPackageTask.prototype.loadPlugins = function() { this.plugins = []; - var pluginsPath = path.resolve('./plugins/'); - var pluginDirs = fs.readdirSync(pluginsPath); + try { + var pluginsPath = path.resolve('./plugins/'); + var pluginDirs = fs.readdirSync(pluginsPath); - for(var x=0; x Date: Fri, 18 Jul 2014 14:03:40 -0500 Subject: [PATCH 136/850] update keywords --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 29088a502f..b057fac894 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "keywords": [ "ionic", "ionic framework", + "ionicframework", "mobile", - "html5", + "app", + "hybrid", "cordova", "phonegap" ], From cdcdafe28013523d8e39d346e182d88adf436123 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 15:11:04 -0500 Subject: [PATCH 137/850] no-email flag, ~ resolve path --- lib/ionic.js | 3 ++- lib/ionic/package.js | 35 ++++++++++++++++++++++++++--------- package.json | 2 +- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 5b10a38354..3200524889 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -63,7 +63,7 @@ var TASKS = [ }, options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', - '--id|-i': 'Package name set as config' + '--id|-i': 'Package name set in the config, ie: com.mycompany.myapp' }, task: IonicStartTask }, @@ -135,6 +135,7 @@ var TASKS = [ '--ios-certificate-password|-d': 'iOS certificate password', '--ios-profile-file|-f': 'iOS profile file', '--output|-o': 'Path to save the packaged app', + '--no-email|-n': 'Do not send a build package email', '--clear-signing|-l': 'Clear out all signing data from Ionic server', '--email|-e': 'Ionic account email', '--password|-p': 'Ionic account password' diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 7ff3e2e30e..089b0d38ff 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -73,6 +73,8 @@ IonicPackageTask.prototype.loadProject = function() { this.ionic.fail('No platforms specified.', 'package'); } + this.buildStatusEmail = (!argv['no-email'] && !argv.n); + this.loadPlugins(); }; @@ -81,12 +83,12 @@ IonicPackageTask.prototype.loadPlugins = function() { this.plugins = []; try { - var pluginsPath = path.resolve('./plugins/'); + var pluginsPath = resolvePath('./plugins/'); var pluginDirs = fs.readdirSync(pluginsPath); for(var x=0; x Date: Fri, 18 Jul 2014 15:18:20 -0500 Subject: [PATCH 138/850] v1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c89e605b6..3f6115f7d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0-beta6", + "version": "1.1.0", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 19e3ad1753506d0d1e0a0d23bbf49e59bef3ec88 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 18 Jul 2014 15:22:10 -0500 Subject: [PATCH 139/850] fix start cmd options --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 09bcb96306..9c2fa70028 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ There are three choices of templates: * Side-Menu (sidemenu) * Tabs (tabs) * Blank (blank) - + Command-line flags/options: - -a, --app ................... your app's name (Use quotes around the name) - -p, --package ........... package name, such as "com.mycompany.myapp" + --app-name, -a ........................ Human readable name for the app (Use quotes around the name) + --id, -i .............................. Package name set in the config, ie: com.mycompany.myapp ## Testing in a Browser From d7c0b9a55d04501080a0de9f12ddd360769d5878 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 13:32:30 -0500 Subject: [PATCH 140/850] Update serve.js --- lib/ionic/serve.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 6d52b8b08c..90a4a71243 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -19,7 +19,6 @@ IonicServeTask.prototype = new IonicTask(); IonicServeTask.prototype.run = function(ionic) { var project = IonicProject.load(); - // Grab the name of the app this.port = argv._[1] || 8100; this.liveReloadPort = argv._[2] || 35729; From a10db157a41384f05cfd73837dbc0c3f0f0abc1d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 13:32:48 -0500 Subject: [PATCH 141/850] Update platform.js --- lib/ionic/platform.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js index fd91a80780..c7cd0476a9 100644 --- a/lib/ionic/platform.js +++ b/lib/ionic/platform.js @@ -18,7 +18,6 @@ IonicPlatformTask.prototype.run = function(ionic) { ionic.fail('No platforms specified.', 'platform'); } - // Grab the name of the app var argPlatforms = argv._.slice(1); var cordovaArgs = ['add', 'remove', 'rm', 'list', 'ls', 'update', 'up']; From a118acd7f6293d6a5a07a31a0972735e420240e1 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 21:34:56 -0500 Subject: [PATCH 142/850] fix promise resolve --- lib/ionic.js | 2 +- lib/ionic/start.js | 20 +++++++++++++------- package.json | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 3200524889..6867733e13 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -63,7 +63,7 @@ var TASKS = [ }, options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', - '--id|-i': 'Package name set in the config, ie: com.mycompany.myapp' + '--id|-i': 'Package name for config, ie: com.mycompany.myapp' }, task: IonicStartTask }, diff --git a/lib/ionic/start.js b/lib/ionic/start.js index fcfc675460..23c5c5e054 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -186,7 +186,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { self._updateConfigXml(); self._installCordovaPlugins().then(function(output) { - pluginQ.resolve(stdout); + pluginQ.resolve(); }, function(err) { pluginQ.reject(err); }); @@ -206,7 +206,11 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { }); }, function(err) { - Ionic.fail('Unable to grab wrapper project:'.error.bold, err); + Ionic.fail( ('Unable to grab wrapper project: ' + err).error.bold ); + + }).catch(function(err) { + console.error('Error: Unable to fetch wrapper: HTTP:'.error.bold, err.statusCode, err); + Ionic.fail(''); }); }; @@ -217,12 +221,14 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\n * cd into your project:', ('$ cd ' + projectDirectory).info.bold); console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); - console.log(' See the Android Platform Guid for full Android installation instructions: https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); - console.log('\n * Build your app:', 'ionic build [platform]'.info.bold); - console.log('\n * Simulate your app:', 'ionic emulate [platform]'.info.bold); - console.log('\n * Run your app on a device:', 'ionic run [platform]'.info.bold); + console.log(' See the Android Platform Guid for full Android installation instructions:'.small); + console.log(' https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); + console.log('\n * Build your app:', 'ionic build '.info.bold); + console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); + console.log('\n * Run your app on a device:', 'ionic run '.info.bold); console.log('\n * Develop in the browser with live reload:', 'ionic serve'.info.bold); - console.log('\n\nFor more help, visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold); + console.log('\n * Package an app using Ionic package service:', 'ionic package '.info.bold); + console.log('\n\nFor more help use', 'ionic --help'.info.bold, 'or visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold, '\n'); }; IonicStartTask.prototype._writeProjectFile = function(ionic) { diff --git a/package.json b/package.json index 3f6115f7d3..3c6ab7c240 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.0", + "version": "1.1.1-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From a38b6b6d99f4946a59918c0c15a955d6e935fd8f Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 22:19:11 -0500 Subject: [PATCH 143/850] check latest npm version --- lib/ionic.js | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 6867733e13..071d9aa1ce 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -312,8 +312,7 @@ Ionic = { run: function() { if(argv.version || argv.v) { - console.log('Ionic CLI version ' + settings.version); - process.exit(0); + return this.version(); } if(argv.help || argv.h) { @@ -346,6 +345,36 @@ Ionic = { process.exit(1); }, + version: function() { + process.stderr.write('Installed Ionic CLI version: ' + settings.version + '\n'); + process.stderr.write('Latest npm version: '); + + try { + var child = spawn('npm', ['show', 'ionic', 'version']); + child.stdout.setEncoding('utf8'); + child.stdout.on('data', function(npmVersion) { + process.stderr.write(npmVersion.trim() + '\n'); + + if(npmVersion.trim() != settings.version.trim()) { + process.stderr.write('Use ' + 'npm update -g ionic'.bold + ' to update to the latest version\n\n'); + } + + }); + child.stderr.on('data', function(data) { + process.stderr.clearLine(); + process.stderr.cursorTo(0); + process.stderr.write('Error loading current npm version: ' + data); + }); + child.on('error', function(err) { + process.stderr.clearLine(); + process.stderr.cursorTo(0); + process.stderr.write('Error loading current npm version: ' + err); + }); + } catch(e) { + console.log(e) + } + }, + spawnPromise: function(cmd, args, onStdOut, onStdErr) { var q = Q.defer(); var child; @@ -355,7 +384,6 @@ Ionic = { } catch(e) { } child.stdout.setEncoding('utf8'); - child.stderr.setEncoding('utf8'); child.stdout.on('data', function(data) { process.stdout.write(data); onStdOut && onStdOut(data); From e7b95e0b09b612f1bd9bdbc31274a4dae0f6905e Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 22:47:51 -0500 Subject: [PATCH 144/850] more error catching --- lib/ionic.js | 13 ++++++++++--- lib/ionic/start.js | 2 ++ package.json | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 071d9aa1ce..e9160a534f 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -427,6 +427,9 @@ Ionic = { writeStream.on('close', function() { q.resolve(repoFolderName); }); + writeStream.on('error', function(err) { + q.reject(err); + }); readStream.pipe(writeStream); }; @@ -435,9 +438,13 @@ Ionic = { q.reject(res); return; } - tempZipFileStream.write(body); - tempZipFileStream.close(); - unzipRepo(tempZipFilePath); + try { + tempZipFileStream.write(body); + tempZipFileStream.close(); + unzipRepo(tempZipFilePath); + } catch(e) { + q.reject(e); + } }); return q.promise; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 23c5c5e054..38347ee4aa 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -93,6 +93,8 @@ IonicStartTask.prototype._fetchWrapper = function() { q.resolve(self.targetPath); }, function(err) { q.reject(err); + }).catch(function(err) { + Ionic.fail('Error: Unable to fetch wrapper repo: ' + err); }); return q.promise; diff --git a/package.json b/package.json index 3c6ab7c240..2c7376feae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.1-beta1", + "version": "1.1.1-beta2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 3adb15900ebc504ced2b8746f4e2f2b598deeafe Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 19 Jul 2014 23:37:39 -0500 Subject: [PATCH 145/850] --no-cordova option --- lib/ionic.js | 7 ++++--- lib/ionic/start.js | 44 ++++++++++++++++++++++++++++++-------------- package.json | 2 +- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index e9160a534f..407d98b85e 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -63,7 +63,8 @@ var TASKS = [ }, options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', - '--id|-i': 'Package name for config, ie: com.mycompany.myapp' + '--id|-i': 'Package name for config, ie: com.mycompany.myapp', + '--no-cordova|-n': 'Do not create an app targeted for Cordova' }, task: IonicStartTask }, @@ -353,10 +354,10 @@ Ionic = { var child = spawn('npm', ['show', 'ionic', 'version']); child.stdout.setEncoding('utf8'); child.stdout.on('data', function(npmVersion) { - process.stderr.write(npmVersion.trim() + '\n'); + process.stderr.write(npmVersion.trim() + '\n\n'); if(npmVersion.trim() != settings.version.trim()) { - process.stderr.write('Use ' + 'npm update -g ionic'.bold + ' to update to the latest version\n\n'); + process.stderr.write(' * Use ' + 'npm update -g ionic'.info.bold + ' to update to the latest version\n\n'); } }); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 38347ee4aa..0956a07249 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -53,6 +53,7 @@ IonicStartTask.prototype.run = function(ionic) { } this.packageName = argv.id || argv.i; + this.isCordovaProject = (argv.cordova !== false && !argv.n); // start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs var starterProject = argv.template || argv.t || argv._[2] || 'tabs'; @@ -90,6 +91,14 @@ IonicStartTask.prototype._fetchWrapper = function() { rm('-rf', self.targetPath + '/' + repoFolderName + '/'); cd(self.targetPath); + if(!self.isCordovaProject) { + // remove any cordova files/directories if they only want the www + var cordovaFiles = ['hooks/', 'platforms/', 'plugins/', 'config.xml']; + for(var x=0; x'.info.bold); - console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); - console.log('\n * Run your app on a device:', 'ionic run '.info.bold); console.log('\n * Develop in the browser with live reload:', 'ionic serve'.info.bold); - console.log('\n * Package an app using Ionic package service:', 'ionic package '.info.bold); + + if(this.isCordovaProject) { + console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.info.bold); + console.log(' Note: iOS development requires OS X currently'.small); + console.log(' See the Android Platform Guid for full Android installation instructions:'.small); + console.log(' https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); + console.log('\n * Build your app:', 'ionic build '.info.bold); + console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); + console.log('\n * Run your app on a device:', 'ionic run '.info.bold); + console.log('\n * Package an app using Ionic package service:', 'ionic package '.info.bold); + } console.log('\n\nFor more help use', 'ionic --help'.info.bold, 'or visit the Ionic docs:', 'http://ionicframework.com/docs'.info.bold, '\n'); }; diff --git a/package.json b/package.json index 2c7376feae..85cdfed33d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.1-beta2", + "version": "1.1.1-beta3", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From fba948f4d505126185b30c06dbb1df533c01587d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 21 Jul 2014 10:45:56 -0500 Subject: [PATCH 146/850] fix latest version print out --- lib/ionic.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 407d98b85e..98ade02569 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -348,32 +348,18 @@ Ionic = { version: function() { process.stderr.write('Installed Ionic CLI version: ' + settings.version + '\n'); - process.stderr.write('Latest npm version: '); try { var child = spawn('npm', ['show', 'ionic', 'version']); child.stdout.setEncoding('utf8'); child.stdout.on('data', function(npmVersion) { - process.stderr.write(npmVersion.trim() + '\n\n'); - + process.stderr.write('Latest npm version: ' + npmVersion.trim() + '\n\n'); if(npmVersion.trim() != settings.version.trim()) { process.stderr.write(' * Use ' + 'npm update -g ionic'.info.bold + ' to update to the latest version\n\n'); } }); - child.stderr.on('data', function(data) { - process.stderr.clearLine(); - process.stderr.cursorTo(0); - process.stderr.write('Error loading current npm version: ' + data); - }); - child.on('error', function(err) { - process.stderr.clearLine(); - process.stderr.cursorTo(0); - process.stderr.write('Error loading current npm version: ' + err); - }); - } catch(e) { - console.log(e) - } + } catch(e) {} }, spawnPromise: function(cmd, args, onStdOut, onStdErr) { From 7aa51514aa601d63ea144f8f06773808269f7221 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 21 Jul 2014 14:24:11 -0500 Subject: [PATCH 147/850] print latest version on all tasks --- lib/ionic.js | 53 +++++++++++++++++++++++++++++++++++-------- lib/ionic/build.js | 6 ++--- lib/ionic/emulate.js | 6 ++--- lib/ionic/login.js | 12 +++++----- lib/ionic/package.js | 38 +++++++++++++++---------------- lib/ionic/platform.js | 4 ++-- lib/ionic/run.js | 6 ++--- lib/ionic/serve.js | 8 +++++-- lib/ionic/start.js | 18 +++++++-------- lib/ionic/upload.js | 10 ++++---- package.json | 2 +- 11 files changed, 100 insertions(+), 63 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 98ade02569..2410678240 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -275,7 +275,7 @@ Ionic = { } process.stderr.write('\n'); - process.exit(1); + this.processExit(1); }, _printHelpLines: function() { @@ -290,7 +290,7 @@ Ionic = { } process.stderr.write('\n'); - process.exit(1); + this.processExit(1); }, _printIonic: function() { @@ -312,6 +312,14 @@ Ionic = { }, run: function() { + var self = this; + + self.checkLatestVersion(); + + process.on('exit', function(){ + self.printVersionWarning(); + }); + if(argv.version || argv.v) { return this.version(); } @@ -343,23 +351,48 @@ Ionic = { } } process.stderr.write('\n'); - process.exit(1); + this.processExit(1); }, version: function() { process.stderr.write('Installed Ionic CLI version: ' + settings.version + '\n'); + }, - try { + checkLatestVersion: function() { + this.latestVersion = Q.defer(); + var self = this; + + if(settings.version.indexOf('beta') > -1) { + // don't bother if its a beta version + this.latestVersion.resolve(); + } else { + // check the latest version in npm var child = spawn('npm', ['show', 'ionic', 'version']); child.stdout.setEncoding('utf8'); child.stdout.on('data', function(npmVersion) { - process.stderr.write('Latest npm version: ' + npmVersion.trim() + '\n\n'); - if(npmVersion.trim() != settings.version.trim()) { - process.stderr.write(' * Use ' + 'npm update -g ionic'.info.bold + ' to update to the latest version\n\n'); - } - + self.npmVersion = npmVersion.trim(); + self.latestVersion.resolve(); }); - } catch(e) {} + child.stdout.on('error', function() { + self.latestVersion.resolve(); + }); + } + }, + + printVersionWarning: function() { + if(this.npmVersion && this.npmVersion != settings.version.trim()) { + process.stdout.write('Ionic CLI is out of date:\n'.bold.yellow); + process.stdout.write( (' * Locally installed version: ' + settings.version + '\n').yellow ); + process.stdout.write( (' * Latest version: ' + this.npmVersion + '\n').yellow ); + process.stdout.write( ' * Use '.yellow + 'npm update -g ionic'.info.bold + ' to update to the latest version\n\n'.yellow ); + this.npmVersion = null; + } + }, + + processExit: function(code) { + this.latestVersion.promise.then(function(){ + process.exit(code); + }); }, spawnPromise: function(cmd, args, onStdOut, onStdErr) { diff --git a/lib/ionic/build.js b/lib/ionic/build.js index 60a91c6d8c..ca2396bfec 100644 --- a/lib/ionic/build.js +++ b/lib/ionic/build.js @@ -15,13 +15,13 @@ IonicBuildTask.prototype = new IonicTask(); IonicBuildTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No platforms specified.', 'build'); + return ionic.fail('No platforms specified.', 'build'); } var platforms = argv._.slice(1); if(platforms.length < 1) { - ionic.fail('No platforms specified.', 'build'); + return ionic.fail('No platforms specified.', 'build'); } IonicStats.t('build', { 'platform': platforms.join(',') }); @@ -30,7 +30,7 @@ IonicBuildTask.prototype.run = function(ionic) { var platform = platforms[i]; console.log('Building platform', platform); if(exec("cordova build " + platform).code !== 0) { - ionic.fail('Unable to build app on platform ' + platform + '. Please see console for more info.'); + return ionic.fail('Unable to build app on platform ' + platform + '. Please see console for more info.'); } } }; diff --git a/lib/ionic/emulate.js b/lib/ionic/emulate.js index ca30dffb5c..1798615f93 100644 --- a/lib/ionic/emulate.js +++ b/lib/ionic/emulate.js @@ -18,13 +18,13 @@ IonicEmulateTask.prototype.run = function(ionic) { var patform; if(argv._.length < 2) { - ionic.fail('No platforms specified.', 'emulate'); + return ionic.fail('No platforms specified.', 'emulate'); } var platforms = argv._.slice(1); if(platforms.length < 1) { - ionic.fail('No platforms specified.', 'emulate'); + return ionic.fail('No platforms specified.', 'emulate'); } IonicStats.t('emulate', { 'platform': platforms.join(',') }); @@ -33,7 +33,7 @@ IonicEmulateTask.prototype.run = function(ionic) { platform = platforms[i]; console.log('Emulating app on platform', platform); if(exec("cordova emulate " + platform).code !== 0) { - ionic.fail('Unable to emulate app on platform ' + platform + '. Please see console for more info.'); + return ionic.fail('Unable to emulate app on platform ' + platform + '. Please see console for more info.'); } } }; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 43deb50b83..1b918a411a 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -23,10 +23,10 @@ IonicLoginTask.prototype.get = function(ionic, callback) { this.password = argv.password || argv.p || process.env.IONIC_PASSWORD; if(!this.email && this.password) { - ionic.fail('--email or -e command line flag, or IONIC_EMAIL environment variable required'); + return ionic.fail('--email or -e command line flag, or IONIC_EMAIL environment variable required'); } if(this.email && !this.password) { - ionic.fail('--password or -p command line flag, or IONIC_PASSWORD environment variable required'); + return ionic.fail('--password or -p command line flag, or IONIC_PASSWORD environment variable required'); } if(!this.email && !this.password) { @@ -76,7 +76,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { prompt.get(schema, function (err, result) { if(err) { - ionic.fail('Error logging in: ' + err); + return ionic.fail('Error logging in: ' + err); } self.email = result.email; @@ -102,7 +102,7 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { }, function(err, response, body) { if(err || jar.cookies.length === 0) { - ionic.fail('Error logging in: ' + err); + return ionic.fail('Error logging in: ' + err); } request({ @@ -117,12 +117,12 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { }, function (err, response, body) { if(err) { - ionic.fail('Error logging in: ' + err); + return ionic.fail('Error logging in: ' + err); } // Should be a 302 redirect status code if correct if(response.statusCode != 302) { - ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); + return ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); } if(saveCookies) { diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 089b0d38ff..3f57ac1fb1 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -52,7 +52,7 @@ IonicPackageTask.prototype.loadProject = function() { console.log( ('Loading ' + appName + '...').bold.yellow ); if(argv._.length < 3) { - this.ionic.fail('No platforms or build mode specified.', 'package'); + return this.ionic.fail('No platforms or build mode specified.', 'package'); } this.mode = argv._[2].toLowerCase(); @@ -66,11 +66,11 @@ IonicPackageTask.prototype.loadProject = function() { } if(this.mode != 'debug' && this.mode != 'release') { - this.ionic.fail('Package build mode must be "debug" or "release".', 'package'); + return this.ionic.fail('Package build mode must be "debug" or "release".', 'package'); } if(this.platforms.length < 1) { - this.ionic.fail('No platforms specified.', 'package'); + return this.ionic.fail('No platforms specified.', 'package'); } this.buildStatusEmail = (!argv['no-email'] && !argv.n); @@ -96,7 +96,7 @@ IonicPackageTask.prototype.loadPlugins = function() { } catch(e) {} } } catch(pluginError) { - this.ionic.fail('Unable to find plugin directory. Make sure the working directory is an Ionic project.'); + return this.ionic.fail('Unable to find plugin directory. Make sure the working directory is an Ionic project.'); } }; @@ -116,7 +116,7 @@ IonicPackageTask.prototype.getCmdLineOptions = function() { var value = argv[propertyName] || argv[shortName]; if(value) { if(!fileExists(value)) { - self.ionic.fail("Unable to find file: " + argv[propertyName]); + return self.ionic.fail("Unable to find file: " + argv[propertyName]); } self.inputFiles[propertyName] = value; self.useCmdArgs = true; @@ -169,7 +169,7 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { request(options, function(err, response, body) { if(err) { - self.ionic.fail("Error loading app signing info: " + err); + return self.ionic.fail("Error loading app signing info: " + err); } if(response.statusCode == 200) { @@ -177,11 +177,11 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { self.signing = JSON.parse(body); if(!self.signing) { - self.ionic.fail("Invalid app signing information"); + return self.ionic.fail("Invalid app signing information"); } } catch(e) { - self.ionic.fail("Error parsing app signing: " + e); + return self.ionic.fail("Error parsing app signing: " + e); } } @@ -206,7 +206,7 @@ IonicPackageTask.prototype.initPlatforms = function() { prompt.get({properties: promptProperties}, function (err, promptResult) { if(err) { - self.ionic.fail('Error packaging: ' + err); + return self.ionic.fail('Error packaging: ' + err); } for(var propertyName in promptResult) { @@ -351,7 +351,7 @@ IonicPackageTask.prototype.buildPostRequest = function(platform) { inputFile = inputFile.replace(/\\ /g, ' ').trim(); form.append(propertyName.replace(/-/g, '_'), fs.createReadStream( resolvePath(inputFile) ) ); } catch(e) { - this.ionic.fail("Error loading " + resolvePath(inputFile)); + return this.ionic.fail("Error loading " + resolvePath(inputFile)); } } @@ -387,7 +387,7 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { }, function(err, response) { if(err) { - self.ionic.fail("Error packaging " + platform + ": " + err); + return self.ionic.fail("Error packaging " + platform + ": " + err); } response.setEncoding('utf8'); @@ -431,7 +431,7 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { self.project.save(); } catch(e) { - self.ionic.fail('Error submitPostRequest: ' + e); + return self.ionic.fail('Error submitPostRequest: ' + e); } }); @@ -446,7 +446,7 @@ IonicPackageTask.prototype.clearSigning = function() { var appId = self.project.get('app_id'); if(!appId) { - self.ionic.fail('App Id is not known'); + return self.ionic.fail('App Id is not known'); } var login = new IonicLoginTask(); @@ -462,7 +462,7 @@ IonicPackageTask.prototype.clearSigning = function() { request(options, function(err, response, body) { if(err) { - self.ionic.fail("Error clearing app signing: " + err); + return self.ionic.fail("Error clearing app signing: " + err); } console.log( ('App (' + appId + ') signing and credential information cleared\n').green ); }); @@ -480,7 +480,7 @@ function pingBuildStatus(ionic, requestOptions, platform, attempt) { request(requestOptions, function(err, response, body) { if(err) { - ionic.fail("\nError pinging build status: " + err); + return ionic.fail("\nError pinging build status: " + err); } try { @@ -508,7 +508,7 @@ function pingBuildStatus(ionic, requestOptions, platform, attempt) { attempt++; if(attempt > 60) { - ionic.fail("\nUnable to receive build status"); + return ionic.fail("\nUnable to receive build status"); } setTimeout(function(){ @@ -517,15 +517,15 @@ function pingBuildStatus(ionic, requestOptions, platform, attempt) { } else if(d.status == 4) { console.log("Use 'ionic package --clear-signing' to clear app signing and credential data if needed.".bold.red); - ionic.fail("Build failed"); + return ionic.fail("Build failed"); } else if(d.status == 3) { downloadBuildPackage(platform, d); } else { - ionic.fail("\nError receiving build status"); + return ionic.fail("\nError receiving build status"); } } catch(e) { - ionic.fail("\nError pinging build status: " + e); + return ionic.fail("\nError pinging build status: " + e); } }); diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js index c7cd0476a9..b5b326ed5e 100644 --- a/lib/ionic/platform.js +++ b/lib/ionic/platform.js @@ -15,7 +15,7 @@ IonicPlatformTask.prototype = new IonicTask(); IonicPlatformTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No platforms specified.', 'platform'); + return ionic.fail('No platforms specified.', 'platform'); } var argPlatforms = argv._.slice(1); @@ -38,7 +38,7 @@ IonicPlatformTask.prototype.run = function(ionic) { } if(platforms.length < 1) { - ionic.fail('No platforms specified.', 'platform'); + return ionic.fail('No platforms specified.', 'platform'); } if(cordovaArg == 'add') { diff --git a/lib/ionic/run.js b/lib/ionic/run.js index 51ccd6130f..76c4752e32 100644 --- a/lib/ionic/run.js +++ b/lib/ionic/run.js @@ -15,13 +15,13 @@ IonicRunTask.prototype = new IonicTask(); IonicRunTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('No platforms specified.', 'run'); + return ionic.fail('No platforms specified.', 'run'); } var platforms = argv._.slice(1); if(platforms.length < 1) { - ionic.fail('No platforms specified.', 'run'); + return ionic.fail('No platforms specified.', 'run'); } IonicStats.t('run', { 'platform': platforms.join(',') }); @@ -30,7 +30,7 @@ IonicRunTask.prototype.run = function(ionic) { var platform = platforms[i]; console.log('Running app on platform', platform); if(exec("cordova run " + platform).code !== 0) { - ionic.fail('Unable to run app on platform ' + platform + '. Please see console for more info.'); + return ionic.fail('Unable to run app on platform ' + platform + '. Please see console for more info.'); } } }; diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 2d17238155..448c63e3b8 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -26,6 +26,10 @@ IonicServeTask.prototype.run = function(ionic) { this.runLivereload = !argv.nolivereload && !argv.r; this._start(ionic); + + ionic.latestVersion.promise.then(function(){ + ionic.printVersionWarning(); + }); }; IonicServeTask.prototype._changed = function(filePath) { @@ -53,7 +57,7 @@ IonicServeTask.prototype._start = function(ionic) { var app = connect(); if (!fs.existsSync( path.resolve('www') )) { - ionic.fail('"www" directory cannot be found. Make sure the working directory is an Ionic project.'); + return ionic.fail('"www" directory cannot be found. Make sure the working directory is an Ionic project.'); } if(this.runLivereload) { @@ -65,7 +69,7 @@ IonicServeTask.prototype._start = function(ionic) { server = tinylr(); server.listen(this.liveReloadPort, function(err) { if(err) { - ionic.fail('Unable to start live reload server:', err); + return ionic.fail('Unable to start live reload server:', err); } else { console.log('Running live reload server at', (self.host(self.liveReloadPort).info.bold) ); if(self.launchBrowser) { diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 0956a07249..f618ec0a25 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -38,7 +38,7 @@ IonicStartTask.prototype = new IonicTask(); IonicStartTask.prototype.run = function(ionic) { if(argv._.length < 2) { - ionic.fail('Invalid command', 'start'); + return ionic.fail('Invalid command', 'start'); } // Grab the app's relative directory name @@ -103,7 +103,7 @@ IonicStartTask.prototype._fetchWrapper = function() { }, function(err) { q.reject(err); }).catch(function(err) { - Ionic.fail('Error: Unable to fetch wrapper repo: ' + err); + return Ionic.fail('Error: Unable to fetch wrapper repo: ' + err); }); return q.promise; @@ -138,7 +138,7 @@ IonicStartTask.prototype._updateConfigXml = function() { var parseString = xml2js.parseString; parseString(configString, function (err, jsonConfig) { if(err) { - Ionic.fail('Error parsing config.xml: ' + err); + return Ionic.fail('Error parsing config.xml: ' + err); } if(!self.packageName) { @@ -154,13 +154,13 @@ IonicStartTask.prototype._updateConfigXml = function() { fs.writeFile(configXmlPath, configString, function(err) { if(err) { - Ionic.fail('Error saving config.xml file: ' + err); + return Ionic.fail('Error saving config.xml file: ' + err); } }); }); } catch(e) { - Ionic.fail('Error updating config.xml file: ' + e); + return Ionic.fail('Error updating config.xml file: ' + e); } }; @@ -209,7 +209,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { pluginQ.promise.then(function() { self._printQuickHelp(self.appDirectory); }, function(err) { - Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); + return Ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); }); IonicStats.t('start', {}); @@ -217,15 +217,15 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { }).catch(function(err) { console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode, err); console.error('Valid project types are blank, tabs, or sidemenu (or see more on our starter page: http://ionicframework.com/getting-started/)'.error.bold); - Ionic.fail(''); + return Ionic.fail(''); }); }, function(err) { - Ionic.fail( ('Unable to grab wrapper project: ' + err).error.bold ); + return Ionic.fail( ('Unable to grab wrapper project: ' + err).error.bold ); }).catch(function(err) { console.error('Error: Unable to fetch wrapper: HTTP:'.error.bold, err.statusCode, err); - Ionic.fail(''); + return Ionic.fail(''); }); }; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 08ac6ee9e3..05a14d5eee 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -35,7 +35,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { archive.finalize(function(err, bytes) { if(err) { - ionic.fail("Error uploading: " + err); + return ionic.fail("Error uploading: " + err); } }); @@ -64,7 +64,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { rm('-f', TEMP_FILENAME); if(err) { - ionic.fail("Error uploading: " + err); + return ionic.fail("Error uploading: " + err); } response.setEncoding('utf8'); @@ -76,7 +76,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { console.log( (d.errors[j]).bold.error ); } q.reject('upload_error'); - ionic.fail('Unable to upload app'); + return ionic.fail('Unable to upload app'); } if(response.statusCode == 200) { @@ -90,7 +90,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { callback(); } catch(callbackEx) { q.reject('upload_error'); - ionic.fail('Error upload callback: ' + callbackEx); + return ionic.fail('Error upload callback: ' + callbackEx); } } @@ -104,7 +104,7 @@ IonicUploadTask.prototype.run = function(ionic, callback) { } catch(parseEx) { q.reject('upload_error'); - ionic.fail('Error upload response: ' + parseEx); + return ionic.fail('Error upload response: ' + parseEx); } }); diff --git a/package.json b/package.json index 85cdfed33d..9fbb4efe91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.1-beta3", + "version": "1.1.1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 254f955ac2648deaf335ae2aa35e74800c1f5263 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 21 Jul 2014 14:27:11 -0500 Subject: [PATCH 148/850] --no-cordova option --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9c2fa70028..e3bc7ffe56 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Command-line flags/options: --app-name, -a ........................ Human readable name for the app (Use quotes around the name) --id, -i .............................. Package name set in the config, ie: com.mycompany.myapp + --no-cordova, -n ...................... Do not create an app targeted for Cordova ## Testing in a Browser From 9c69de3e98511de810307b37577bd58b56918750 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 22 Jul 2014 17:06:25 -0500 Subject: [PATCH 149/850] Removed version check for now --- lib/ionic.js | 10 ++++++---- package.json | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2410678240..158b1c032f 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -314,11 +314,11 @@ Ionic = { run: function() { var self = this; - self.checkLatestVersion(); + //self.checkLatestVersion(); - process.on('exit', function(){ - self.printVersionWarning(); - }); + //process.on('exit', function(){ + //self.printVersionWarning(); + //}); if(argv.version || argv.v) { return this.version(); @@ -390,9 +390,11 @@ Ionic = { }, processExit: function(code) { + /* this.latestVersion.promise.then(function(){ process.exit(code); }); + */ }, spawnPromise: function(cmd, args, onStdOut, onStdErr) { diff --git a/package.json b/package.json index 9fbb4efe91..8a9275b057 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.1", + "version": "1.1.2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 330fc4c442d0325ca0097c86dfbefe0412742a47 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 22 Jul 2014 17:13:24 -0500 Subject: [PATCH 150/850] V bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a9275b057..f57f2280b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.2", + "version": "1.1.3", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From ff3a59c1f22543a6316e5899b78bc6247bd04a9e Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 22 Jul 2014 17:35:00 -0500 Subject: [PATCH 151/850] Bold formatting --- lib/ionic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic.js b/lib/ionic.js index 158b1c032f..7092421cf5 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -270,7 +270,7 @@ Ionic = { while((name + dots).length < 20) { dots += '.'; } - process.stderr.write(name.green + dots.grey + ' ' + task.summary + '\n'); + process.stderr.write(name.green.bold + dots.grey + ' ' + task.summary + '\n'); } } From 3ce81471efcd9dbb79b872cfc3605557ea54dd79 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 22 Jul 2014 22:34:09 -0500 Subject: [PATCH 152/850] use http api to check for latest ionic version Prefer the http api over spawning `npm show ionic version` due to possible npm version issues and the command line hassles. --- lib/ionic.js | 41 ++++++++++++++++++++++++----------------- package.json | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 7092421cf5..2d243e6ed3 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -24,6 +24,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, IonicServeTask = require('./ionic/serve'), IonicProject = require('./ionic/project'), + IonicStore = require('./ionic/store').IonicStore, path = require('path'), request = require('request'), os = require('os'), @@ -314,11 +315,11 @@ Ionic = { run: function() { var self = this; - //self.checkLatestVersion(); + self.checkLatestVersion(); - //process.on('exit', function(){ - //self.printVersionWarning(); - //}); + process.on('exit', function(){ + self.printVersionWarning(); + }); if(argv.version || argv.v) { return this.version(); @@ -362,21 +363,29 @@ Ionic = { this.latestVersion = Q.defer(); var self = this; - if(settings.version.indexOf('beta') > -1) { - // don't bother if its a beta version - this.latestVersion.resolve(); - } else { - // check the latest version in npm - var child = spawn('npm', ['show', 'ionic', 'version']); - child.stdout.setEncoding('utf8'); - child.stdout.on('data', function(npmVersion) { - self.npmVersion = npmVersion.trim(); + try { + // stay silent if it errors + var ionicConfig = new IonicStore('ionic.config'); + var versionCheck = ionicConfig.get('versionCheck'); + if(versionCheck && ((versionCheck + 86400000) > Date.now() )) { + // we've recently checked for the latest version, so don't bother again self.latestVersion.resolve(); - }); - child.stdout.on('error', function() { + return; + } + + var proxy = process.env.PROXY || null; + request({ url: 'http://registry.npmjs.org/ionic/latest', proxy: proxy }, function(err, res, body) { + try { + self.npmVersion = JSON.parse(body).version; + ionicConfig.set('versionCheck', Date.now()); + ionicConfig.save(); + } catch(e) {} self.latestVersion.resolve(); }); + } catch(e) { + self.latestVersion.resolve(); } + }, printVersionWarning: function() { @@ -390,11 +399,9 @@ Ionic = { }, processExit: function(code) { - /* this.latestVersion.promise.then(function(){ process.exit(code); }); - */ }, spawnPromise: function(cmd, args, onStdOut, onStdErr) { diff --git a/package.json b/package.json index f57f2280b1..d17e1a1114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.3", + "version": "1.1.4", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 12c45c77358ab083d6fc4ca141f30d1553c1506c Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 24 Jul 2014 22:08:17 -0500 Subject: [PATCH 153/850] v1.1.5 --- README.md | 14 ++- lib/ionic.js | 122 +++++++++++++------- lib/ionic/build.js | 38 ------ lib/ionic/cordova.js | 21 ++++ lib/ionic/emulate.js | 41 ------- lib/ionic/lib.js | 260 ++++++++++++++++++++++++++++++++++++++++++ lib/ionic/login.js | 9 +- lib/ionic/package.js | 56 +++++---- lib/ionic/platform.js | 57 --------- lib/ionic/run.js | 38 ------ lib/ionic/serve.js | 2 + lib/ionic/start.js | 33 +++--- lib/ionic/stats.js | 83 +++++++++++++- lib/ionic/upload.js | 8 +- package.json | 2 +- 15 files changed, 520 insertions(+), 264 deletions(-) delete mode 100644 lib/ionic/build.js create mode 100644 lib/ionic/cordova.js delete mode 100644 lib/ionic/emulate.js create mode 100644 lib/ionic/lib.js delete mode 100644 lib/ionic/platform.js delete mode 100644 lib/ionic/run.js diff --git a/README.md b/README.md index e3bc7ffe56..2e6ed11ac3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ Ionic-Cli ========= -The Ionic Framework command line utility makes it easy to start, build, run, and emulate [Ionic](http://ionicframework.com/) apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. Use `ionic --help` for detailed task information. +The Ionic Framework command line utility makes it easy to start, build, run, and emulate [Ionic](http://ionicframework.com/) apps. In the future, it will also have support for our mobile development services and tools that make Ionic even more powerful. + +Use the `ionic --help` command for more detailed task information. ## Installing @@ -25,7 +27,7 @@ Command-line flags/options: --app-name, -a ........................ Human readable name for the app (Use quotes around the name) --id, -i .............................. Package name set in the config, ie: com.mycompany.myapp - --no-cordova, -n ...................... Do not create an app targeted for Cordova + --no-cordova, -w ...................... Do not create an app targeted for Cordova ## Testing in a Browser @@ -59,6 +61,14 @@ $ ionic emulate ios $ ionic run ios ``` +## Update Ionic lib + +Update Ionic library files, which are found in the `www/lib/ionic` directory. + +```bash +$ ionic lib update +``` + ## Packaging an app (beta) diff --git a/lib/ionic.js b/lib/ionic.js index 2d243e6ed3..57df79da29 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -15,13 +15,11 @@ Copyright 2014 Drifty (http://drifty.com/) */ var IonicStartTask = require('./ionic/start').IonicStartTask, - IonicPlatformTask = require('./ionic/platform').IonicPlatformTask, - IonicRunTask = require('./ionic/run').IonicRunTask, - IonicEmulateTask = require('./ionic/emulate').IonicEmulateTask; - IonicBuildTask = require('./ionic/build').IonicBuildTask, + IonicCordovaTask = require('./ionic/cordova').IonicCordovaTask, IonicLoginTask = require('./ionic/login').IonicLoginTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, + IonicLibTask = require('./ionic/lib').IonicLibTask, IonicServeTask = require('./ionic/serve'), IonicProject = require('./ionic/project'), IonicStore = require('./ionic/store').IonicStore, @@ -65,7 +63,7 @@ var TASKS = [ options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', '--id|-i': 'Package name for config, ie: com.mycompany.myapp', - '--no-cordova|-n': 'Do not create an app targeted for Cordova' + '--no-cordova|-w': 'Create a basic structure without Cordova requirements' }, task: IonicStartTask }, @@ -90,7 +88,7 @@ var TASKS = [ args: { '': '' }, - task: IonicPlatformTask + task: IonicCordovaTask }, { title: 'emulate', @@ -99,7 +97,7 @@ var TASKS = [ args: { '': '' }, - task: IonicEmulateTask + task: IonicCordovaTask }, { title: 'run', @@ -108,7 +106,11 @@ var TASKS = [ args: { '': '' }, - task: IonicRunTask + options: { + '--debug|--release': '', + '--device|--emulator|--target=FOO': '' + }, + task: IonicCordovaTask }, { title: 'build', @@ -117,7 +119,30 @@ var TASKS = [ args: { '': '' }, - task: IonicBuildTask + task: IonicCordovaTask + }, + { + title: 'plugin add', + name: 'plugin', + summary: 'Add a Cordova plugin', + args: { + '': 'Can be a plugin ID, a local path, or a git URL.' + }, + options: { + '--searchpath ': 'When looking up plugins by ID, look in this directory and\n\ + each of its subdirectories for the plugin before hitting the registry.' + }, + task: IonicCordovaTask + }, + { + title: 'prepare', + name: 'prepare', + task: IonicCordovaTask + }, + { + title: 'compile', + name: 'compile', + task: IonicCordovaTask }, { title: 'package', @@ -155,6 +180,18 @@ var TASKS = [ alt: ['up'], task: IonicUploadTask }, + { + title: 'lib', + name: 'lib', + summary: 'Gets Ionic library version info or updates the Ionic library', + args: { + '[update]': 'Updates the Ionic Framework version in www/lib/ionic' + }, + options: { + '--version|-v': 'Exact Ionic version, otherwise it will default to the latest' + }, + task: IonicLibTask + }, { title: 'login', name: 'login', @@ -205,13 +242,13 @@ Ionic = { var indent = ''; var x, arg; - var taskArgs = d.name; + var taskArgs = d.title; for(arg in d.args) { taskArgs += ' ' + arg; } - w(taskArgs.green); + w(taskArgs.green.bold); while( (taskArgs + dots).length < rightColumn + 1) { dots += '.'; @@ -219,7 +256,7 @@ Ionic = { w(' ' + dots.grey + ' '); - w(d.summary); + w(d.summary.bold); for(arg in d.args) { if( !d.args[arg] ) continue; @@ -230,7 +267,7 @@ Ionic = { while(indent.length < rightColumn) { indent += ' '; } - w( (indent + ' ' + argLine + ' = ' + d.args[arg]).grey ); + w( (indent + ' ' + argLine + ' ' + d.args[arg]).bold ); } indent = ''; @@ -244,14 +281,16 @@ Ionic = { var optLine = indent + '[' + opt + '] '; - w(optLine.yellow); + w(optLine.yellow.bold); - while( (dots.length + optLine.length - 2) < rightColumn) { - dots += '.'; - } - w(dots.grey + ' '); + if(d.options[opt]) { + while( (dots.length + optLine.length - 2) < rightColumn) { + dots += '.'; + } + w(dots.grey + ' '); - w(d.options[opt].grey); + w(d.options[opt].bold); + } } w('\n'); @@ -260,6 +299,11 @@ Ionic = { _printAvailableTasks: function() { this._printIonic(); process.stderr.write('\nUsage: ionic task args\n\n===============\n\n'); + + if(process.argv.length > 2) { + process.stderr.write( (process.argv[2] + ' is not a valid task\n\n').bold.red ); + } + process.stderr.write('Available tasks: '.bold); process.stderr.write('(use --help or -h for more info)\n\n'); @@ -271,7 +315,7 @@ Ionic = { while((name + dots).length < 20) { dots += '.'; } - process.stderr.write(name.green.bold + dots.grey + ' ' + task.summary + '\n'); + process.stderr.write(name.green.bold + dots.grey + ' ' + task.summary.bold + '\n'); } } @@ -321,7 +365,7 @@ Ionic = { self.printVersionWarning(); }); - if(argv.version || argv.v) { + if( (argv.version || argv.v) && !argv._.length) { return this.version(); } @@ -339,6 +383,7 @@ Ionic = { }, fail: function(msg, taskHelp) { + this.hasFailed = true; process.stderr.write(msg.error.bold); process.stderr.write('\n'); if(taskHelp) { @@ -356,7 +401,7 @@ Ionic = { }, version: function() { - process.stderr.write('Installed Ionic CLI version: ' + settings.version + '\n'); + process.stderr.write('v' + settings.version + '\n'); }, checkLatestVersion: function() { @@ -439,11 +484,9 @@ Ionic = { fetchRepo: function(targetPath, repoName, repoUrl) { var q = Q.defer(); - var proxy = process.env.PROXY || null; - // The folder name the project will be downloaded and extracted to var repoFolderName = repoName + '-master'; - console.log('\nDOWNLOADING:'.info.bold, repoUrl); + console.log('\nDownloading:'.info.bold, repoUrl); var tmpFolder = os.tmpdir(); var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); @@ -462,6 +505,7 @@ Ionic = { readStream.pipe(writeStream); }; + var proxy = process.env.PROXY || null; request({ url: repoUrl, encoding: null, proxy: proxy }, function(err, res, body) { if(res.statusCode !== 200) { q.reject(res); @@ -474,25 +518,23 @@ Ionic = { } catch(e) { q.reject(e); } + }).on('response', function(res){ + var ProgressBar = require('progress'); + var bar = new ProgressBar('[:bar] :percent :etas', { + complete: '=', + incomplete: ' ', + width: 30, + total: parseInt(res.headers['content-length'], 10) + }); + + res.on('data', function (chunk) { + bar.tick(chunk.length); + }); }); return q.promise; - }, - - getLocalIps: function() { - var interfaces = os.networkInterfaces(); - var addresses = []; - for (var k in interfaces) { - for (var k2 in interfaces[k]) { - var address = interfaces[k][k2]; - if (address.family == 'IPv4' && !address.internal) { - addresses.push(address.address); - } - } - } - - return addresses; } + }; exports.Ionic = Ionic; diff --git a/lib/ionic/build.js b/lib/ionic/build.js deleted file mode 100644 index ca2396bfec..0000000000 --- a/lib/ionic/build.js +++ /dev/null @@ -1,38 +0,0 @@ -var fs = require('fs'), - os = require('os'), - argv = require('optimist').argv, - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), - IonicTask = require('./task').IonicTask, - IonicStats = require('./stats').IonicStats; - -var IonicBuildTask = function() {}; - -IonicBuildTask.prototype = new IonicTask(); - -IonicBuildTask.prototype.run = function(ionic) { - if(argv._.length < 2) { - return ionic.fail('No platforms specified.', 'build'); - } - - var platforms = argv._.slice(1); - - if(platforms.length < 1) { - return ionic.fail('No platforms specified.', 'build'); - } - - IonicStats.t('build', { 'platform': platforms.join(',') }); - - for(var i = 0; i < platforms.length; i++) { - var platform = platforms[i]; - console.log('Building platform', platform); - if(exec("cordova build " + platform).code !== 0) { - return ionic.fail('Unable to build app on platform ' + platform + '. Please see console for more info.'); - } - } -}; - -exports.IonicBuildTask = IonicBuildTask; diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js new file mode 100644 index 0000000000..c9044a27c3 --- /dev/null +++ b/lib/ionic/cordova.js @@ -0,0 +1,21 @@ +var IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats; + +var IonicCordovaTask = function() {}; + +IonicCordovaTask.prototype = new IonicTask(); + +IonicCordovaTask.prototype.run = function(ionic) { + var cmdName = process.argv[2].toLowerCase(); + var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); + + var command = 'cordova ' + cmdName + ' ' + cmdArgs.join(' '); + + if(exec(command).code !== 0) { + return ionic.fail('Error from ' + cmdName + ' command.', cmdName); + } + + IonicStats.t(); +}; + +exports.IonicCordovaTask = IonicCordovaTask; diff --git a/lib/ionic/emulate.js b/lib/ionic/emulate.js deleted file mode 100644 index 1798615f93..0000000000 --- a/lib/ionic/emulate.js +++ /dev/null @@ -1,41 +0,0 @@ -var fs = require('fs'), - os = require('os'), - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), - IonicTask = require('./task').IonicTask, - IonicStats = require('./stats').IonicStats; - -var argv = require('optimist').argv; - -var IonicEmulateTask = function() {}; - -IonicEmulateTask.prototype = new IonicTask(); - -IonicEmulateTask.prototype.run = function(ionic) { - var patform; - - if(argv._.length < 2) { - return ionic.fail('No platforms specified.', 'emulate'); - } - - var platforms = argv._.slice(1); - - if(platforms.length < 1) { - return ionic.fail('No platforms specified.', 'emulate'); - } - - IonicStats.t('emulate', { 'platform': platforms.join(',') }); - - for(var i = 0; i < platforms.length; i++) { - platform = platforms[i]; - console.log('Emulating app on platform', platform); - if(exec("cordova emulate " + platform).code !== 0) { - return ionic.fail('Unable to emulate app on platform ' + platform + '. Please see console for more info.'); - } - } -}; - -exports.IonicEmulateTask = IonicEmulateTask; diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js new file mode 100644 index 0000000000..07aaedce43 --- /dev/null +++ b/lib/ionic/lib.js @@ -0,0 +1,260 @@ +var fs = require('fs'), + os = require('os'), + request = require('request'), + path = require('path'), + unzip = require('unzip'), + argv = require('optimist').argv, + prompt = require('prompt'), + colors = require('colors'), + Q = require('q'), + IonicTask = require('./task').IonicTask; + IonicStats = require('./stats').IonicStats; + +var IonicLibTask = function() {}; + +IonicLibTask.prototype = new IonicTask(); + +IonicLibTask.prototype.run = function(ionic) { + var self = this; + self.codeHost = 'http://code.ionicframework.com'; + self.local = {}; + self.latest = {}; + + if (!fs.existsSync( path.resolve('www') )) { + return ionic.fail('"www" directory cannot be found. Make sure the working directory is at the top level of an Ionic project.', 'lib'); + } + + if(argv._.length > 1 && (argv._[1].toLowerCase() == 'update' || argv._[1].toLowerCase() == 'up')) { + this.updatePrompt(); + } else { + // just version info + this.printLibVersions(); + } + +}; + + +IonicLibTask.prototype.printLibVersions = function() { + var self = this; + + var p = path.resolve('www/lib/ionic/version.json'); + try { + self.local = require(p); + console.log('Local Ionic version: '.bold.green + self.local.version + ' (' + path.resolve('www/lib/ionic/') + ')'); + } catch(e) { + console.log('Unable to load ionic lib version information'.bold.error); + console.log('Error loading: '.bold.error + p ); + } + + this.getLatestVersions().then(function(){ + console.log('Latest Ionic version: '.bold.green + self.latest.version_number + ' (released ' + self.latest.release_date + ')'); + + if(self.local.version != self.latest.version_number) { + console.log(' * Local version is out of date'.yellow ); + } else { + console.log(' * Local version up to date'.green ); + } + }); +}; + + +IonicLibTask.prototype.getLatestVersions = function() { + var q = Q.defer(); + var self = this; + + var proxy = process.env.PROXY || null; + request({ url: self.codeHost + '/latest.json', proxy: proxy }, function(err, res, body) { + try { + self.latest = JSON.parse(body); + q.resolve(); + } catch(e) { + console.log(e); + q.reject(e); + } + }); + + return q.promise; +}; + + +IonicLibTask.prototype.updatePrompt = function() { + var self = this; + prompt.message = ''; + prompt.delimiter = ''; + prompt.start(); + + var libPath = path.resolve('www/lib/ionic/'); + + console.log('Are you sure you want replace '.green + libPath.info + ' with an updated version of Ionc?'.green); + + var promptProperties = { + areYouSure: { + name: 'areYouSure', + description: '(yes/no):'.yellow.bold, + required: true + } + }; + + prompt.get({properties: promptProperties}, function (err, promptResult) { + if(err) { + return console.log('Error: ' + err); + } + + var areYouSure = promptResult.areYouSure.toLowerCase().trim(); + if(areYouSure == 'yes' || areYouSure == 'y') { + self.getLatest(); + } + }); +}; + + +IonicLibTask.prototype.getLatest = function() { + var self = this; + + var dirPath = path.resolve('www/lib/'); + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + + dirPath = path.resolve('www/lib/ionic/'); + deleteFolderRecursive(dirPath); + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + + var version = argv.version || argv.v; + if(version && version !== true && version !== false) { + // get specific version + var archivePath = '/' + version + '/ionic-v' + version + '.zip'; + self.downloadZip(archivePath, version); + + } else { + // get the latest version + this.getLatestVersions().then(function(){ + console.log('Latest version: '.bold.green + self.latest.version_number + ' (released ' + self.latest.release_date + ')'); + + self.downloadZip(self.latest.archive, self.latest.version_number); + + }).catch(function(err) { + console.log('Error: ' + err); + }); + } + +}; + + +IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { + var self = this; + + var versionZip = self.codeHost + archivePath; + self.tmpZipPath = path.resolve('www/lib/ionic/ionic.zip'); + + console.log('Downloading: '.green.bold + versionZip); + + var file = fs.createWriteStream(self.tmpZipPath); + var proxy = process.env.PROXY || null; + request({ url: versionZip, encoding: null, proxy: proxy }, function(err, res, body) { + if(err) { + console.log(err) + return; + } + if(res.statusCode == 404) { + console.log( ('Invalid version: ' + versionNumber).bold.red ); + try { + file.close(); + fs.unlink(self.tmpZipPath); + } catch(e) { + console.error( (e).red ); + } + return; + } + if(res.statusCode >= 400) { + console.log('Unable to download zip (' + res.statusCode + ')'); + return; + } + try { + file.write(body); + file.close(function(){ + self.updateFiles(); + }) + } catch(e) { + console.error( (e).red ); + } + }).on('response', function(res){ + + var ProgressBar = require('progress'); + var bar = new ProgressBar('[:bar] :percent :etas', { + complete: '=', + incomplete: ' ', + width: 30, + total: parseInt(res.headers['content-length'], 10) + }); + + res.on('data', function (chunk) { + bar.tick(chunk.length); + }); + + }).on('error', function(err) { + try { + fs.unlink(self.tmpZipPath); + } catch(e) { + console.error( (e).red ); + } + console.error( (err).red ); + }); + +}; + + +IonicLibTask.prototype.updateFiles = function() { + var self = this; + var ionicLibDir = path.resolve('www/lib/ionic/'); + var readStream = fs.createReadStream(self.tmpZipPath); + + try { + var writeStream = unzip.Extract({ path: ionicLibDir }); + writeStream.on('close', function() { + try{ + var newVersion = require(path.resolve('www/lib/ionic/version.json')).version; + + console.log('Ionic version updated to: '.bold.green + newVersion.bold ); + IonicStats.t(); + + } catch(e) { + console.log('Error loading version info'.bold); + } + try { + fs.unlink(self.tmpZipPath); + } catch(e) {} + }); + writeStream.on('error', function(err) { + console.log('Error: ' + err); + }); + readStream.pipe(writeStream); + + readStream.on('error', function(err){ + console.log('Error: ' + err); + }); + + } catch(err) { + console.log('Error: ' + err); + } +}; + + +function deleteFolderRecursive(path) { + if( fs.existsSync(path) ) { + fs.readdirSync(path).forEach(function(file,index){ + var curPath = path + "/" + file; + if(fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(path); + } +} + + +exports.IonicLibTask = IonicLibTask; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 1b918a411a..c61adaa799 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -56,18 +56,18 @@ IonicLoginTask.prototype.run = function(ionic, callback) { var schema = [{ name: 'email', pattern: /^[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+(?:\.[A-z0-9!#$%&'*+\/=?\^_{|}~\-]+)*@(?:[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9\-]*[A-z0-9])?$/, - description: 'Email:', + description: 'Email:'.yellow.bold, required: true }, { name: 'password', - description: 'Password:', + description: 'Password:'.yellow.bold, hidden: true, required: true }]; // prompt for log console.log('\nTo continue, please login to your Ionic account.'.bold.green); - console.log('Don\'t have one? Create a one at: '.grey + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); + console.log('Don\'t have one? Create a one at: '.bold + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); prompt.override = argv; prompt.message = ''; @@ -113,7 +113,8 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { username: self.email.toString().toLowerCase(), password: self.password, csrfmiddlewaretoken: jar.cookies[0].value - } + }, + proxy: process.env.PROXY || null }, function (err, response, body) { if(err) { diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 3f57ac1fb1..5de1e6da39 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -1,8 +1,7 @@ var fs = require('fs'), - http = require('http'), + request = require('request'), path = require('path'), parseUrl = require('url').parse, - spawn = require("child_process").spawn, argv = require('optimist').argv, prompt = require('prompt'), shelljs = require('shelljs/global'), @@ -11,6 +10,7 @@ var fs = require('fs'), IonicStore = require('./store').IonicStore, IonicTask = require('./task').IonicTask, IonicUploadTask = require('./upload').IonicUploadTask, + IonicStats = require('./stats').IonicStats, IonicLoginTask = require('./login').IonicLoginTask; var IonicPackageTask = function() {}; @@ -26,6 +26,8 @@ IonicPackageTask.prototype.run = function(ionic) { self.inputValues = {}; self.useCmdArgs = false; + IonicStats.t(); + if(argv['clear-signing'] || argv.l) { self.clearSigning(); return; @@ -35,6 +37,8 @@ IonicPackageTask.prototype.run = function(ionic) { this.getCmdLineOptions(); + if(self.ionic.hasFailed) return; + var login = new IonicLoginTask(); login.get(self.ionic, function(jar) { self.jar = jar; @@ -49,7 +53,7 @@ IonicPackageTask.prototype.run = function(ionic) { IonicPackageTask.prototype.loadProject = function() { var appName = this.project.get('name') || "app"; - console.log( ('Loading ' + appName + '...').bold.yellow ); + console.log( ('Loading ' + appName + '...').bold.green ); if(argv._.length < 3) { return this.ionic.fail('No platforms or build mode specified.', 'package'); @@ -164,7 +168,8 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { return c.name + "=" + encodeURIComponent(c.value); }).join("; "), cck: cck - } + }, + proxy: process.env.PROXY || null }; request(options, function(err, response, body) { @@ -252,7 +257,7 @@ IonicPackageTask.prototype.buildPromptProperties = function() { promptProperties['android-keystore-file']= { name: 'android-keystore-file', - description: 'Android Keystore File (.keystore):', + description: 'Android Keystore File (.keystore):'.yellow.bold, required: true, conform: fileExists, isFile: true @@ -260,20 +265,20 @@ IonicPackageTask.prototype.buildPromptProperties = function() { promptProperties['android-keystore-alias'] = { name: 'android-keystore-alias', - description: 'Keystore Alias:', + description: 'Keystore Alias:'.yellow.bold.yellow.bold, required: true }; promptProperties['android-keystore-password'] = { name: 'android-keystore-password', - description: 'Keystore Password:', + description: 'Keystore Password:'.yellow.bold, hidden: true, required: true }; promptProperties['android-key-password'] = { name: 'android-key-password', - description: 'Key Password (optional):', + description: 'Key Password (optional):'.yellow.bold, hidden: true }; } @@ -282,7 +287,7 @@ IonicPackageTask.prototype.buildPromptProperties = function() { // iOS promptProperties['ios-certificate-file'] = { name: 'ios-certificate-file', - description: 'iOS Certificate File (.p12):', + description: 'iOS Certificate File (.p12):'.yellow.bold, required: true, conform: fileExists, isFile: true @@ -290,14 +295,14 @@ IonicPackageTask.prototype.buildPromptProperties = function() { promptProperties['ios-certificate-password'] = { name: 'ios-certificate-password', - description: 'Certificate Password:', + description: 'Certificate Password:'.yellow.bold, hidden: true, required: true }; promptProperties['ios-profile-file'] = { name: 'ios-profile-file', - description: 'iOS Mobile Provisioning Profile (.mobileprovision):', + description: 'iOS Mobile Provisioning Profile (.mobileprovision):'.yellow.bold, required: true, conform: fileExists, isFile: true @@ -371,7 +376,7 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { var privateData = new IonicStore(this.project.get('app_id')); - console.log( (platform + ' ' + self.mode + ' package building...').bold.grey ); + console.log( (platform + ' ' + self.mode + ' building...').bold ); form.submit({ protocol: params.protocol, @@ -441,7 +446,7 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { IonicPackageTask.prototype.clearSigning = function() { var self = this; - console.log('Clearing app signing and credential information...'.yellow); + console.log('Clearing app signing and credential information...'.yellow.bold); var appId = self.project.get('app_id'); @@ -457,14 +462,15 @@ IonicPackageTask.prototype.clearSigning = function() { cookie: jar.cookies.map(function (c) { return c.name + "=" + encodeURIComponent(c.value); }).join("; ") - } + }, + proxy: process.env.PROXY || null }; request(options, function(err, response, body) { if(err) { return self.ionic.fail("Error clearing app signing: " + err); } - console.log( ('App (' + appId + ') signing and credential information cleared\n').green ); + console.log( ('App (' + appId + ') signing and credential information cleared\n').green.bold ); }); }); }; @@ -533,7 +539,7 @@ function pingBuildStatus(ionic, requestOptions, platform, attempt) { function downloadBuildPackage(platform, data) { - console.log( ('\n\n' + platform + ' build complete, downloading package...').bold.grey ); + console.log( ('\n\n' + platform + ' build complete, downloading package...').bold ); var filePath = argv.output; @@ -546,16 +552,22 @@ function downloadBuildPackage(platform, data) { } } - var params = parseUrl(data.package_url); - var file = fs.createWriteStream(filePath); - var request = http.get({hostname: params.hostname, path: params.path, port: params.port, protocol: 'http:'}, function(response) { - response.pipe(file); - file.on('finish', function() { + + var proxy = process.env.PROXY || null; + request({ url: data.package_url, proxy: proxy }, function(err, res, body) { + if(res.statusCode !== 200) { + console.error( (err).red ); + return; + } + try { + file.write(body); file.close(function(){ console.log( ('Saved ' + platform + ' package: ' + filePath + '\n').bold.green ); }); - }); + } catch(e) { + q.reject(e); + } }).on('response', function(res){ var ProgressBar = require('progress'); diff --git a/lib/ionic/platform.js b/lib/ionic/platform.js deleted file mode 100644 index b5b326ed5e..0000000000 --- a/lib/ionic/platform.js +++ /dev/null @@ -1,57 +0,0 @@ -var fs = require('fs'), - os = require('os'), - argv = require('optimist').argv, - request = require('request'), - ncp = require('ncp').ncp, - path = require('path'), - shelljs = require('shelljs/global'), - unzip = require('unzip'), - IonicTask = require('./task').IonicTask, - IonicStats = require('./stats').IonicStats; - -var IonicPlatformTask = function() {}; - -IonicPlatformTask.prototype = new IonicTask(); - -IonicPlatformTask.prototype.run = function(ionic) { - if(argv._.length < 2) { - return ionic.fail('No platforms specified.', 'platform'); - } - - var argPlatforms = argv._.slice(1); - - var cordovaArgs = ['add', 'remove', 'rm', 'list', 'ls', 'update', 'up']; - var cordovaArg = 'add'; - var platforms = []; - - for(var y=0; y 3 ? process.argv.slice(3) : []); // skip the cmdName + + var statsData = additionalData || {}; + var platforms = []; + var x, y, cmd; + + // update any aliases with the full cmd so there's a common property + var aliasMap = { + 'rm': 'remove', + 'ls': 'list', + 'up': 'update', + '-w': '--no-cordova', + '-b': '--nobrowser', + '-r': '--nolivereload', + '-l': '--clear-signing', + '-n': '--no-email' + }; + for(x=0; x Date: Sat, 26 Jul 2014 00:16:20 +0800 Subject: [PATCH 154/850] Fix typo in `ionic start` quick tips --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index d4b64f47e3..f3e7ad2d4d 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -244,7 +244,7 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { if(this.isCordovaProject) { console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); - console.log(' See the Android Platform Guid for full Android installation instructions:'.small); + console.log(' See the Android Platform Guide for full Android installation instructions:'.small); console.log(' https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); console.log('\n * Build your app:', 'ionic build '.info.bold); console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); From 2a9796a7a6e82d3cc790d76c9d259074f45462dc Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 25 Jul 2014 11:55:46 -0500 Subject: [PATCH 155/850] typo fix --- lib/ionic/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 07aaedce43..7322243c55 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -85,7 +85,7 @@ IonicLibTask.prototype.updatePrompt = function() { var libPath = path.resolve('www/lib/ionic/'); - console.log('Are you sure you want replace '.green + libPath.info + ' with an updated version of Ionc?'.green); + console.log('Are you sure you want to replace '.green.bold + libPath.info.bold + ' with an updated version of Ionc?'.green.bold); var promptProperties = { areYouSure: { @@ -97,7 +97,7 @@ IonicLibTask.prototype.updatePrompt = function() { prompt.get({properties: promptProperties}, function (err, promptResult) { if(err) { - return console.log('Error: ' + err); + return console.log(err); } var areYouSure = promptResult.areYouSure.toLowerCase().trim(); From 46e5f2ca3e3c7f97e908fdb1eac333d0a9a4e62e Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 25 Jul 2014 13:18:41 -0500 Subject: [PATCH 156/850] no version checking for betas --- lib/ionic.js | 6 ++++++ lib/ionic/stats.js | 1 + 2 files changed, 7 insertions(+) diff --git a/lib/ionic.js b/lib/ionic.js index 57df79da29..ff2ffb4355 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -409,6 +409,12 @@ Ionic = { var self = this; try { + if(settings.version.indexOf('beta') > -1) { + // don't bother checking if its a beta + self.latestVersion.resolve(); + return; + } + // stay silent if it errors var ionicConfig = new IonicStore('ionic.config'); var versionCheck = ionicConfig.get('versionCheck'); diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index b6a808a549..d5869665bf 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -586,6 +586,7 @@ exports.IonicStats = { // add which cli version is being used try { statsData.cli_version = require('../../package.json').version; + if(statsData.cli_version.indexOf('beta') > -1) return; } catch(e2) {} IonicStats.mp(cmdName, statsData); From c2e4a1dbc7846e8258872ad4c183c73e2da48c0f Mon Sep 17 00:00:00 2001 From: Alexis THOMAS Date: Sun, 27 Jul 2014 18:30:51 +0200 Subject: [PATCH 157/850] Replace link to specific version of Cordova docs Cordova docs link set to "edge" instead of 3.4.0 or 3.5.0 or newer to come --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index f3e7ad2d4d..2d213c4c7d 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -245,7 +245,7 @@ IonicStartTask.prototype._printQuickHelp = function(projectDirectory) { console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.info.bold); console.log(' Note: iOS development requires OS X currently'.small); console.log(' See the Android Platform Guide for full Android installation instructions:'.small); - console.log(' https://cordova.apache.org/docs/en/3.4.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); + console.log(' https://cordova.apache.org/docs/en/edge/guide_platforms_android_index.md.html#Android%20Platform%20Guide'.small); console.log('\n * Build your app:', 'ionic build '.info.bold); console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); console.log('\n * Run your app on a device:', 'ionic run '.info.bold); From b8bb829556b1697f6b87c42112d9c099abb3e41f Mon Sep 17 00:00:00 2001 From: Alexis THOMAS Date: Sun, 27 Jul 2014 19:09:46 +0200 Subject: [PATCH 158/850] Typo in update prompt --- lib/ionic/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 7322243c55..3b7ef046d3 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -85,7 +85,7 @@ IonicLibTask.prototype.updatePrompt = function() { var libPath = path.resolve('www/lib/ionic/'); - console.log('Are you sure you want to replace '.green.bold + libPath.info.bold + ' with an updated version of Ionc?'.green.bold); + console.log('Are you sure you want to replace '.green.bold + libPath.info.bold + ' with an updated version of Ionic?'.green.bold); var promptProperties = { areYouSure: { From 5524eebe0aeef0ee10fe1d14a7233a63b618d7d9 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sun, 27 Jul 2014 18:40:41 -0500 Subject: [PATCH 159/850] Options --- lib/ionic.js | 11 ++++++++++- package.json | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index ff2ffb4355..2cfc100f7b 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -57,8 +57,9 @@ var TASKS = [ name: 'start', summary: 'Starts a new Ionic project in the specified PATH', args: { + '[options]': 'any flags for the command', '': 'directory for the new project', - '[TEMPLATE]': 'Starter template to use (tabs, sidemenu, blank)' + '[template]': 'Starter template to use (tabs, sidemenu, blank)' }, options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', @@ -72,6 +73,7 @@ var TASKS = [ name: 'serve', summary: 'Start a local development server for app dev and testing', args: { + '[options]': '', '[http-port]': '', '[livereload-port]': '' }, @@ -86,6 +88,7 @@ var TASKS = [ name: 'platform', summary: 'Add platform target for building an Ionic app', args: { + '[options]': '', '': '' }, task: IonicCordovaTask @@ -95,6 +98,7 @@ var TASKS = [ name: 'emulate', summary: 'Emulate an Ionic project on a simulator or emulator', args: { + '[options]': '', '': '' }, task: IonicCordovaTask @@ -104,6 +108,7 @@ var TASKS = [ name: 'run', summary: 'Run an ionic project on a connected device', args: { + '[options]': '', '': '' }, options: { @@ -117,6 +122,7 @@ var TASKS = [ name: 'build', summary: 'Locally build an ionic project for a given platform', args: { + '[options]': '', '': '' }, task: IonicCordovaTask @@ -126,6 +132,7 @@ var TASKS = [ name: 'plugin', summary: 'Add a Cordova plugin', args: { + '[options]': '', '': 'Can be a plugin ID, a local path, or a git URL.' }, options: { @@ -150,6 +157,7 @@ var TASKS = [ alt: ['pack'], summary: 'Package an app using the Ionic Build service', args: { + '[options]': '', '': '"debug" or "release"', '': '"ios" or "android"' }, @@ -185,6 +193,7 @@ var TASKS = [ name: 'lib', summary: 'Gets Ionic library version info or updates the Ionic library', args: { + '[options]': '', '[update]': 'Updates the Ionic Framework version in www/lib/ionic' }, options: { diff --git a/package.json b/package.json index e7b91e07a1..0384d97976 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.5", + "version": "1.1.6", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From aff090b1a6a039418a8cebc6ab672cdeaabb2444 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 29 Jul 2014 14:11:04 -0500 Subject: [PATCH 160/850] network error, error handling for progress bar --- lib/ionic.js | 4 +++- lib/ionic/lib.js | 4 +++- lib/ionic/package.js | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2cfc100f7b..9219ae1ddc 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -543,7 +543,9 @@ Ionic = { }); res.on('data', function (chunk) { - bar.tick(chunk.length); + try { + bar.tick(chunk.length); + } catch(e){} }); }); diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 7322243c55..46770022cd 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -191,7 +191,9 @@ IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { }); res.on('data', function (chunk) { - bar.tick(chunk.length); + try { + bar.tick(chunk.length); + } catch(e){} }); }).on('error', function(err) { diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 5de1e6da39..32a3171f2d 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -579,7 +579,9 @@ function downloadBuildPackage(platform, data) { }); res.on('data', function (chunk) { - bar.tick(chunk.length); + try { + bar.tick(chunk.length); + } catch(e){} }); res.on('end', function () { From a76dce5f1af4300cd42db994cb78ab2c72d7b210 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 2 Aug 2014 23:02:36 -0500 Subject: [PATCH 161/850] prefix CLI to cli version output closes #55 --- lib/ionic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic.js b/lib/ionic.js index 9219ae1ddc..a2c0a64a0c 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -357,7 +357,7 @@ Ionic = { w(' _ ___ _ __ _ ___ \n'); w(' | |/ _ \\| \'_ \\| |/ __|\n'); w(' | | (_) | | | | | (__ \n'); - w(' |_|\\___/|_| |_|_|\\___| v'+ settings.version + '\n'); + w(' |_|\\___/|_| |_|_|\\___| CLI v'+ settings.version + '\n'); }, From be0885fd9f3fcdfad3a36782dff742f9db99f3f8 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 2 Aug 2014 23:18:26 -0500 Subject: [PATCH 162/850] insert `add` cmd when missing from `platform` cmds Closes #54 --- lib/ionic/cordova.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index c9044a27c3..d93ea9cd3c 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -9,6 +9,27 @@ IonicCordovaTask.prototype.run = function(ionic) { var cmdName = process.argv[2].toLowerCase(); var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); + // backwards compatibility prior to fully wrapping cordova cmds + if(cmdName == 'platform') { + // `ionic platform ` used to actually run `ionic platform add ` + // if a cordova platform cmd isn't the cmd then automatically insert `add` + var hasCordovaCmd = false; + var validCommands = 'add remove rm list ls update up check'.split(' '); + var cmdArg, x, y; + for(x=0; x Date: Mon, 4 Aug 2014 11:43:57 -0500 Subject: [PATCH 163/850] set platform body class from cordova hook --- .../after_prepare/010_add_platform_class.js | 92 +++++++++++++++++++ lib/ionic/cordova.js | 72 ++++++++++++++- package.json | 2 +- 3 files changed, 164 insertions(+), 2 deletions(-) create mode 100755 lib/hooks/after_prepare/010_add_platform_class.js diff --git a/lib/hooks/after_prepare/010_add_platform_class.js b/lib/hooks/after_prepare/010_add_platform_class.js new file mode 100755 index 0000000000..fc1f8ef3cf --- /dev/null +++ b/lib/hooks/after_prepare/010_add_platform_class.js @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +// Add Platform Class +// v1.0 +// Automatically adds the platform class to the body tag +// after the `prepare` command. This speeds up device rendering +// the correct layout/style for the specific platform. + +var fs = require('fs'); +var path = require('path'); + +var rootdir = process.argv[2]; + +function addPlatformBodyTag(indexPath, platform) { + // add the platform class to the body tag + try { + var platformClass = 'platform-' + platform; + var cordovaClass = 'platform-cordova platform-webview'; + + var html = fs.readFileSync(indexPath, 'utf8'); + + var bodyTag = findBodyTag(html); + if(!bodyTag) return; // no opening body tag, something's wrong + + if(bodyTag.indexOf(platformClass) > -1) return; // already added + + var newBodyTag = bodyTag; + + var classAttr = findClassAttr(bodyTag); + if(classAttr) { + // body tag has existing class attribute, add the classname + var endingQuote = classAttr.substring(classAttr.length-1); + var newClassAttr = classAttr.substring(0, classAttr.length-1); + newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote; + newBodyTag = bodyTag.replace(classAttr, newClassAttr); + + } else { + // add class attribute tot he body tag + newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">') + } + + html = html.replace(bodyTag, newBodyTag); + + fs.writeFileSync(indexPath, html, 'utf8'); + + process.stdout.write('add to body class: ' + platformClass + '\n'); + } catch(e) { + process.stdout.write(e); + } +} + +function findBodyTag(html) { + // get the body tag + try{ + return html.match(//gi)[0]; + }catch(e){} +} + +function findClassAttr(bodyTag) { + // get the body tag's class attribute + try{ + return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0]; + }catch(e){} +} + +if (rootdir) { + + // go through each of the platform directories that have been prepared + var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); + + for(var x=0; x -1) continue; + addcliHookDirectory( path.join(cliHooksPath, files[x]), files[x] ); + } + }); + + function addcliHookDirectory(cliHookPath, hookDirectoryName) { + fs.readdir(cliHookPath, function(err, files){ + // loop through each of the scripts in the ionic-cli hook directory + if(err) return; + for(var x=0; x Date: Tue, 5 Aug 2014 09:26:25 +0200 Subject: [PATCH 164/850] Update 010_add_platform_class.js --- lib/hooks/after_prepare/010_add_platform_class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hooks/after_prepare/010_add_platform_class.js b/lib/hooks/after_prepare/010_add_platform_class.js index fc1f8ef3cf..cdfb187492 100755 --- a/lib/hooks/after_prepare/010_add_platform_class.js +++ b/lib/hooks/after_prepare/010_add_platform_class.js @@ -35,7 +35,7 @@ function addPlatformBodyTag(indexPath, platform) { newBodyTag = bodyTag.replace(classAttr, newClassAttr); } else { - // add class attribute tot he body tag + // add class attribute to the body tag newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">') } From fb7902a60e24dde30e25fea5d94e0dbe66a5f674 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 5 Aug 2014 14:47:09 -0500 Subject: [PATCH 165/850] spawn cordova commands --- lib/ionic/cordova.js | 20 +++++++++++++++----- package.json | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 6b0d964fa9..dd6732a24b 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -1,7 +1,9 @@ var IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats, fs = require('fs'), - path = require('path'); + path = require('path'), + spawn = require('child_process').spawn, + colors = require('colors'); var IonicCordovaTask = function() {}; @@ -33,11 +35,19 @@ IonicCordovaTask.prototype.run = function(ionic) { } this.addHooks(); - var command = 'cordova ' + cmdName + ' ' + cmdArgs.join(' '); + cmdArgs.unshift(cmdName); - if(exec(command).code !== 0) { - return ionic.fail('Error from ' + cmdName + ' command.', cmdName); - } + var cordovaCmd = spawn('cordova', cmdArgs); + + cordovaCmd.stdout.on('data', function (data) { + process.stdout.write(data); + }); + + cordovaCmd.stderr.on('data', function (data) { + if(data) { + process.stderr.write(data.toString().error.bold); + } + }); IonicStats.t(); }; diff --git a/package.json b/package.json index 4f394bd4bb..ff0a9d20ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.7", + "version": "1.1.8-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 61b09feb40783a32abe8ad925f5f840ed8da93ec Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 5 Aug 2014 15:06:16 -0500 Subject: [PATCH 166/850] use IP when only one IPV4 internal=false address https://github.com/driftyco/ionic/issues/1892 --- lib/ionic/serve.js | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 2faaec0462..a4bc185953 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -93,7 +93,7 @@ IonicServeTask.prototype._start = function(ionic) { IonicServeTask.prototype.host = function(port) { - var address = 'localhost'; + var addresses = []; try { var os = require('os'); @@ -102,13 +102,13 @@ IonicServeTask.prototype.host = function(port) { for (var dev in ifaces) { ifaces[dev].forEach(function(details){ if (details.family == 'IPv4' && !details.internal) { - address = details.address; + addresses.push(details.address); } }); } } catch(e) {} - return 'http://' + address + ':' + port; + return 'http://' + (addresses.length === 1 ? addresses[0] : 'localhost') + ':' + port; }; module.exports = IonicServeTask; diff --git a/package.json b/package.json index ff0a9d20ed..206464bd1c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8-beta1", + "version": "1.1.8-beta2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From fc922932171b699cdc9f9358b801a98ad3c9a593 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 5 Aug 2014 16:01:36 -0500 Subject: [PATCH 167/850] update bower file --- lib/ionic/lib.js | 30 ++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 824930247f..263f50d70c 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -219,6 +219,8 @@ IonicLibTask.prototype.updateFiles = function() { try{ var newVersion = require(path.resolve('www/lib/ionic/version.json')).version; + self.updateBowerFile(newVersion); + console.log('Ionic version updated to: '.bold.green + newVersion.bold ); IonicStats.t(); @@ -244,6 +246,34 @@ IonicLibTask.prototype.updateFiles = function() { }; +IonicLibTask.prototype.updateBowerFile = function(newVersion) { + try { + var bowerFilePath = path.resolve('bower.json'); + var bowerData; + + if( fs.existsSync(bowerFilePath) ) { + bowerData = require(bowerFilePath); + } else { + bowerData = { + "name": "HelloIonic", + "private": "true" + }; + } + + if(!bowerData.devDependencies) bowerData.devDependencies = {}; + + bowerData.devDependencies.ionic = 'driftyco/ionic-bower#' + newVersion; + + var file = fs.createWriteStream(bowerFilePath); + file.write( JSON.stringify(bowerData, null, 2) ); + file.close(); + + } catch(e) { + console.log( ('Bower file error: ' + e).error.bold ); + } +}; + + function deleteFolderRecursive(path) { if( fs.existsSync(path) ) { fs.readdirSync(path).forEach(function(file,index){ diff --git a/package.json b/package.json index 206464bd1c..daf5793d1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8-beta2", + "version": "1.1.8-beta3", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From e4c9a984a01b04e97e21f7bd1b988e95fc9b9dad Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 5 Aug 2014 16:15:10 -0500 Subject: [PATCH 168/850] handle network errors Closes #62 --- lib/ionic.js | 2 +- lib/ionic/lib.js | 6 ++---- package.json | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index a2c0a64a0c..0dcccd39d1 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -522,7 +522,7 @@ Ionic = { var proxy = process.env.PROXY || null; request({ url: repoUrl, encoding: null, proxy: proxy }, function(err, res, body) { - if(res.statusCode !== 200) { + if(!res || res.statusCode !== 200) { q.reject(res); return; } diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 263f50d70c..e4599f56b7 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -68,8 +68,8 @@ IonicLibTask.prototype.getLatestVersions = function() { self.latest = JSON.parse(body); q.resolve(); } catch(e) { - console.log(e); - q.reject(e); + console.log('Error loading latest version information'.bold.error ); + q.reject(); } }); @@ -135,8 +135,6 @@ IonicLibTask.prototype.getLatest = function() { self.downloadZip(self.latest.archive, self.latest.version_number); - }).catch(function(err) { - console.log('Error: ' + err); }); } diff --git a/package.json b/package.json index daf5793d1f..d03dc32df5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8-beta3", + "version": "1.1.8-beta4", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 13502fbd16bfa059cff8f6af20a1ff7c76fa8836 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 09:31:13 -0500 Subject: [PATCH 169/850] set app name in bower.json --- lib/ionic/bower.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ lib/ionic/lib.js | 41 +++++++---------------------------------- lib/ionic/start.js | 3 +++ 3 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 lib/ionic/bower.js diff --git a/lib/ionic/bower.js b/lib/ionic/bower.js new file mode 100644 index 0000000000..0f7ca0b7c4 --- /dev/null +++ b/lib/ionic/bower.js @@ -0,0 +1,45 @@ +var fs = require('fs'), + path = require('path'), + colors = require('colors'); + +exports.IonicBower = { + + setIonicVersion: function(newVersion) { + var bowerData = this.getData(); + if(!bowerData.devDependencies) bowerData.devDependencies = {}; + bowerData.devDependencies.ionic = 'driftyco/ionic-bower#' + newVersion; + this.saveData(bowerData); + }, + + setAppName: function(newAppName) { + var bowerData = this.getData(); + bowerData.name = newAppName; + this.saveData(bowerData); + }, + + getData: function() { + var bowerFilePath = path.resolve('bower.json'); + + if( fs.existsSync(bowerFilePath) ) { + return require(bowerFilePath); + } + + return { + "name": "HelloIonic", + "private": "true" + }; + }, + + saveData: function(bowerData) { + try { + var bowerFilePath = path.resolve('bower.json'); + + var file = fs.createWriteStream(bowerFilePath); + file.write( JSON.stringify(bowerData, null, 2) ); + file.close(); + } catch(e) { + console.log( ('Error saving ' + bowerFilePath + ': ' + e).error.bold ); + } + } + +}; diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index e4599f56b7..bfee7c84b1 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -7,7 +7,7 @@ var fs = require('fs'), prompt = require('prompt'), colors = require('colors'), Q = require('q'), - IonicTask = require('./task').IonicTask; + IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats; var IonicLibTask = function() {}; @@ -153,7 +153,7 @@ IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { var proxy = process.env.PROXY || null; request({ url: versionZip, encoding: null, proxy: proxy }, function(err, res, body) { if(err) { - console.log(err) + console.log(err); return; } if(res.statusCode == 404) { @@ -174,7 +174,7 @@ IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { file.write(body); file.close(function(){ self.updateFiles(); - }) + }); } catch(e) { console.error( (e).red ); } @@ -217,13 +217,14 @@ IonicLibTask.prototype.updateFiles = function() { try{ var newVersion = require(path.resolve('www/lib/ionic/version.json')).version; - self.updateBowerFile(newVersion); - console.log('Ionic version updated to: '.bold.green + newVersion.bold ); IonicStats.t(); + var ionicBower = require('./bower').IonicBower; + ionicBower.setIonicVersion(newVersion); + } catch(e) { - console.log('Error loading version info'.bold); + console.log( ('Error loading version info: ' + e).error.bold ); } try { fs.unlink(self.tmpZipPath); @@ -244,34 +245,6 @@ IonicLibTask.prototype.updateFiles = function() { }; -IonicLibTask.prototype.updateBowerFile = function(newVersion) { - try { - var bowerFilePath = path.resolve('bower.json'); - var bowerData; - - if( fs.existsSync(bowerFilePath) ) { - bowerData = require(bowerFilePath); - } else { - bowerData = { - "name": "HelloIonic", - "private": "true" - }; - } - - if(!bowerData.devDependencies) bowerData.devDependencies = {}; - - bowerData.devDependencies.ionic = 'driftyco/ionic-bower#' + newVersion; - - var file = fs.createWriteStream(bowerFilePath); - file.write( JSON.stringify(bowerData, null, 2) ); - file.close(); - - } catch(e) { - console.log( ('Bower file error: ' + e).error.bold ); - } -}; - - function deleteFolderRecursive(path) { if( fs.existsSync(path) ) { fs.readdirSync(path).forEach(function(file,index){ diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 2d213c4c7d..c8782e7c63 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -212,6 +212,9 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { } pluginQ.promise.then(function() { + var ionicBower = require('./bower').IonicBower; + ionicBower.setAppName(self.appName); + self._printQuickHelp(self.appDirectory); }, function(err) { return self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); From c716a1473d7f68b54c342c6cade0524625f04977 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 10:09:01 -0500 Subject: [PATCH 170/850] update lib w/ bower when using bower --- lib/ionic.js | 4 +++- lib/ionic/lib.js | 51 +++++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 0dcccd39d1..5b341998e7 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -450,10 +450,12 @@ Ionic = { printVersionWarning: function() { if(this.npmVersion && this.npmVersion != settings.version.trim()) { + process.stdout.write('\n-------------------------\n'.red); process.stdout.write('Ionic CLI is out of date:\n'.bold.yellow); process.stdout.write( (' * Locally installed version: ' + settings.version + '\n').yellow ); process.stdout.write( (' * Latest version: ' + this.npmVersion + '\n').yellow ); - process.stdout.write( ' * Use '.yellow + 'npm update -g ionic'.info.bold + ' to update to the latest version\n\n'.yellow ); + process.stdout.write( ' * Run '.yellow + 'npm update -g ionic'.info.bold + ' to update\n'.yellow ); + process.stdout.write('-------------------------\n\n'.red); this.npmVersion = null; } }, diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index bfee7c84b1..9d0ded7b68 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -6,6 +6,7 @@ var fs = require('fs'), argv = require('optimist').argv, prompt = require('prompt'), colors = require('colors'), + spawn = require('child_process').spawn, Q = require('q'), IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats; @@ -19,13 +20,16 @@ IonicLibTask.prototype.run = function(ionic) { self.codeHost = 'http://code.ionicframework.com'; self.local = {}; self.latest = {}; + self.usesBower = false; if (!fs.existsSync( path.resolve('www') )) { return ionic.fail('"www" directory cannot be found. Make sure the working directory is at the top level of an Ionic project.', 'lib'); } + this.loadVersionData(); + if(argv._.length > 1 && (argv._[1].toLowerCase() == 'update' || argv._[1].toLowerCase() == 'up')) { - this.updatePrompt(); + this.updateLibVersion(); } else { // just version info this.printLibVersions(); @@ -34,17 +38,25 @@ IonicLibTask.prototype.run = function(ionic) { }; -IonicLibTask.prototype.printLibVersions = function() { - var self = this; +IonicLibTask.prototype.loadVersionData = function() { + this.versionFilePath = path.resolve('www/lib/ionic/version.json'); + if( !fs.existsSync(this.versionFilePath) ) { + this.versionFilePath = path.resolve('www/lib/ionic/bower.json'); + this.usesBower = fs.existsSync(this.versionFilePath); + } - var p = path.resolve('www/lib/ionic/version.json'); try { - self.local = require(p); - console.log('Local Ionic version: '.bold.green + self.local.version + ' (' + path.resolve('www/lib/ionic/') + ')'); + this.local = require(this.versionFilePath); } catch(e) { console.log('Unable to load ionic lib version information'.bold.error); - console.log('Error loading: '.bold.error + p ); } +}; + + +IonicLibTask.prototype.printLibVersions = function() { + var self = this; + + console.log('Local Ionic version: '.bold.green + this.local.version + ' (' + this.versionFilePath + ')'); this.getLatestVersions().then(function(){ console.log('Latest Ionic version: '.bold.green + self.latest.version_number + ' (released ' + self.latest.release_date + ')'); @@ -77,8 +89,25 @@ IonicLibTask.prototype.getLatestVersions = function() { }; -IonicLibTask.prototype.updatePrompt = function() { +IonicLibTask.prototype.updateLibVersion = function() { var self = this; + + if(self.usesBower) { + var bowerCmd = spawn('bower', ['update', 'ionic']); + + bowerCmd.stdout.on('data', function (data) { + process.stdout.write(data); + }); + + bowerCmd.stderr.on('data', function (data) { + if(data) { + process.stderr.write(data.toString().error.bold); + } + }); + + return; + } + prompt.message = ''; prompt.delimiter = ''; prompt.start(); @@ -215,13 +244,13 @@ IonicLibTask.prototype.updateFiles = function() { var writeStream = unzip.Extract({ path: ionicLibDir }); writeStream.on('close', function() { try{ - var newVersion = require(path.resolve('www/lib/ionic/version.json')).version; + self.loadVersionData(); - console.log('Ionic version updated to: '.bold.green + newVersion.bold ); + console.log('Ionic version updated to: '.bold.green + self.local.version.bold ); IonicStats.t(); var ionicBower = require('./bower').IonicBower; - ionicBower.setIonicVersion(newVersion); + ionicBower.setIonicVersion(self.local.version); } catch(e) { console.log( ('Error loading version info: ' + e).error.bold ); diff --git a/package.json b/package.json index d03dc32df5..51e893fa42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8-beta4", + "version": "1.1.8-beta5", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From c39070209802e5d9e5bd32577e6b337689dbfe86 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 10:13:05 -0500 Subject: [PATCH 171/850] v1.1.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 51e893fa42..c96e0f0d6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8-beta5", + "version": "1.1.8", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 3542e9a490d70d9d2b95b65fb85a188d232b23ef Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 10:20:13 -0500 Subject: [PATCH 172/850] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e6ed11ac3..4618f97515 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,9 @@ $ ionic run ios ## Update Ionic lib -Update Ionic library files, which are found in the `www/lib/ionic` directory. +Update Ionic library files, which are found in the `www/lib/ionic` directory. If bower is being used +by the project, this command will automatically run `bower update`, otherwise this command updates +the local static files from Ionic's CDN. ```bash $ ionic lib update From 0cd183bbbd8a5e516d1a5ddb09041afacfecf150 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 10:20:30 -0500 Subject: [PATCH 173/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4618f97515..0edc636d0c 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ $ ionic run ios ## Update Ionic lib Update Ionic library files, which are found in the `www/lib/ionic` directory. If bower is being used -by the project, this command will automatically run `bower update`, otherwise this command updates +by the project, this command will automatically run `bower update ionic`, otherwise this command updates the local static files from Ionic's CDN. ```bash From ddc60c524cd823e86f83c2ed58c0b8c04d3fb6fc Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 11:01:59 -0500 Subject: [PATCH 174/850] ionic serve description --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0edc636d0c..4c55aacd1d 100644 --- a/README.md +++ b/README.md @@ -25,17 +25,24 @@ There are three choices of templates: Command-line flags/options: - --app-name, -a ........................ Human readable name for the app (Use quotes around the name) - --id, -i .............................. Package name set in the config, ie: com.mycompany.myapp - --no-cordova, -w ...................... Do not create an app targeted for Cordova + --app-name, -a ...... Human readable name for the app (Use quotes around the name) + --id, -i ............ Package name set in the config, ie: com.mycompany.myapp + --no-cordova, -w .... Do not create an app targeted for Cordova ## Testing in a Browser +Start a local development server for app dev and testing. This is also useful to test within a device browser which is connected to the same wireless network. Additionally, LiveReload is installed which is used to monitor changes in the file system. As soon as you save a file, it is preprocessed as needed, and the browser is refreshed automatically. + ```bash -$ ionic serve +$ ionic serve [http-port] [livereload-port] [options] ``` +Command-line flags/options: + + [--nobrowser|-b] ...... Disable launching a browser + [--nolivereload|-r] ... Do not start live reload + ## Adding a platform target From 4e5bb2403f9214d393231ffb0d7d161599bbfb9d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 6 Aug 2014 11:05:17 -0500 Subject: [PATCH 175/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c55aacd1d..11bd1cd8c1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Command-line flags/options: ## Testing in a Browser -Start a local development server for app dev and testing. This is also useful to test within a device browser which is connected to the same wireless network. Additionally, LiveReload is installed which is used to monitor changes in the file system. As soon as you save a file, it is preprocessed as needed, and the browser is refreshed automatically. +Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. ```bash $ ionic serve [http-port] [livereload-port] [options] From f48afd86c5500414c0970cd0fd6affdd2235150f Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 7 Aug 2014 21:39:32 -0500 Subject: [PATCH 176/850] fix windows cordova cmd issues --- lib/ionic/cordova.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index dd6732a24b..2d97530118 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -2,7 +2,7 @@ var IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats, fs = require('fs'), path = require('path'), - spawn = require('child_process').spawn, + exec = require('child_process').exec, colors = require('colors'); var IonicCordovaTask = function() {}; @@ -37,7 +37,7 @@ IonicCordovaTask.prototype.run = function(ionic) { cmdArgs.unshift(cmdName); - var cordovaCmd = spawn('cordova', cmdArgs); + var cordovaCmd = exec('cordova ' + cmdArgs.join(' ')); cordovaCmd.stdout.on('data', function (data) { process.stdout.write(data); diff --git a/package.json b/package.json index c96e0f0d6c..0b4d072aa0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.8", + "version": "1.1.9-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 6b4c3d861c268cf7fc86f71d298008297c76dd02 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 7 Aug 2014 21:40:04 -0500 Subject: [PATCH 177/850] get version data from ionic-bower for scss files --- lib/ionic/bower.js | 8 ++- lib/ionic/lib.js | 169 ++++++++++++++++++++++++++++----------------- 2 files changed, 111 insertions(+), 66 deletions(-) diff --git a/lib/ionic/bower.js b/lib/ionic/bower.js index 0f7ca0b7c4..82e447f6d5 100644 --- a/lib/ionic/bower.js +++ b/lib/ionic/bower.js @@ -20,9 +20,11 @@ exports.IonicBower = { getData: function() { var bowerFilePath = path.resolve('bower.json'); - if( fs.existsSync(bowerFilePath) ) { - return require(bowerFilePath); - } + try { + if( fs.existsSync(bowerFilePath) ) { + return require(bowerFilePath); + } + } catch(e){} return { "name": "HelloIonic", diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 9d0ded7b68..b0656b40d0 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -6,7 +6,7 @@ var fs = require('fs'), argv = require('optimist').argv, prompt = require('prompt'), colors = require('colors'), - spawn = require('child_process').spawn, + exec = require('child_process').exec, Q = require('q'), IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats; @@ -19,7 +19,7 @@ IonicLibTask.prototype.run = function(ionic) { var self = this; self.codeHost = 'http://code.ionicframework.com'; self.local = {}; - self.latest = {}; + self.versionData = {}; self.usesBower = false; if (!fs.existsSync( path.resolve('www') )) { @@ -58,10 +58,10 @@ IonicLibTask.prototype.printLibVersions = function() { console.log('Local Ionic version: '.bold.green + this.local.version + ' (' + this.versionFilePath + ')'); - this.getLatestVersions().then(function(){ - console.log('Latest Ionic version: '.bold.green + self.latest.version_number + ' (released ' + self.latest.release_date + ')'); + this.getVersionData('latest').then(function(){ + console.log('Latest Ionic version: '.bold.green + self.versionData.version_number + ' (released ' + self.versionData.release_date + ')'); - if(self.local.version != self.latest.version_number) { + if(self.local.version != self.versionData.version_number) { console.log(' * Local version is out of date'.yellow ); } else { console.log(' * Local version up to date'.green ); @@ -70,17 +70,39 @@ IonicLibTask.prototype.printLibVersions = function() { }; -IonicLibTask.prototype.getLatestVersions = function() { +IonicLibTask.prototype.getVersionData = function(version) { var q = Q.defer(); var self = this; + var url = self.codeHost; + if(version == 'latest') { + url += '/latest.json'; + } else { + url += '/' + version + '/version.json'; + } + var proxy = process.env.PROXY || null; - request({ url: self.codeHost + '/latest.json', proxy: proxy }, function(err, res, body) { + request({ url: url, proxy: proxy }, function(err, res, body) { try { - self.latest = JSON.parse(body); + if(err || !res || !body) { + console.log('Unable to receive version data'); + q.reject(); + return; + } + if(res.statusCode == 404) { + console.log( ('Invalid version: ' + version).bold.red ); + q.reject(); + return; + } + if(res.statusCode >= 400) { + console.log('Unable to load version data'); + q.reject(); + return; + } + self.versionData = JSON.parse(body); q.resolve(); } catch(e) { - console.log('Error loading latest version information'.bold.error ); + console.log('Error loading '.bold.error + version.bold + ' version information'.bold.error ); q.reject(); } }); @@ -93,7 +115,7 @@ IonicLibTask.prototype.updateLibVersion = function() { var self = this; if(self.usesBower) { - var bowerCmd = spawn('bower', ['update', 'ionic']); + var bowerCmd = exec('bower update ionic'); bowerCmd.stdout.on('data', function (data) { process.stdout.write(data); @@ -146,47 +168,44 @@ IonicLibTask.prototype.getLatest = function() { } dirPath = path.resolve('www/lib/ionic/'); - deleteFolderRecursive(dirPath); if(!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath); } var version = argv.version || argv.v; - if(version && version !== true && version !== false) { - // get specific version - var archivePath = '/' + version + '/ionic-v' + version + '.zip'; - self.downloadZip(archivePath, version); - - } else { - // get the latest version - this.getLatestVersions().then(function(){ - console.log('Latest version: '.bold.green + self.latest.version_number + ' (released ' + self.latest.release_date + ')'); - - self.downloadZip(self.latest.archive, self.latest.version_number); - - }); + if(version === true || !version) { + version = 'latest'; } + this.getVersionData(version).then(function(){ + if(version == 'latest') { + console.log('Latest version: '.bold.green + self.versionData.version_number + ' (released ' + self.versionData.release_date + ')'); + } else { + console.log('Version: '.bold.green + self.versionData.version_number + ' (released ' + self.versionData.release_date + ')'); + } + self.downloadZip(self.versionData.version_number); + }); + }; -IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { +IonicLibTask.prototype.downloadZip = function(version) { var self = this; - var versionZip = self.codeHost + archivePath; + var archivePath = 'https://github.com/driftyco/ionic-bower/archive/v' + version + '.zip'; self.tmpZipPath = path.resolve('www/lib/ionic/ionic.zip'); - console.log('Downloading: '.green.bold + versionZip); + console.log('Downloading: '.green.bold + archivePath); var file = fs.createWriteStream(self.tmpZipPath); var proxy = process.env.PROXY || null; - request({ url: versionZip, encoding: null, proxy: proxy }, function(err, res, body) { + request({ url: archivePath, encoding: null, proxy: proxy }, function(err, res, body) { if(err) { console.log(err); return; } if(res.statusCode == 404) { - console.log( ('Invalid version: ' + versionNumber).bold.red ); + console.log( ('Invalid version: ' + version).bold.red ); try { file.close(); fs.unlink(self.tmpZipPath); @@ -235,58 +254,82 @@ IonicLibTask.prototype.downloadZip = function(archivePath, versionNumber) { }; -IonicLibTask.prototype.updateFiles = function() { +IonicLibTask.prototype.updateFiles = function(version) { var self = this; - var ionicLibDir = path.resolve('www/lib/ionic/'); + var ionicLibDir = path.resolve('www/lib/ionic'); var readStream = fs.createReadStream(self.tmpZipPath); try { - var writeStream = unzip.Extract({ path: ionicLibDir }); - writeStream.on('close', function() { - try{ - self.loadVersionData(); - console.log('Ionic version updated to: '.bold.green + self.local.version.bold ); - IonicStats.t(); + function onEntry(entry) { + var libEntryPath = entry.path.replace('ionic-bower-' + self.versionData.version_number + '/', ionicLibDir + '/'); - var ionicBower = require('./bower').IonicBower; - ionicBower.setIonicVersion(self.local.version); + if( /bower.json|readme/gi.test(entry.path) ) { + entry.autodrain(); + return; + } - } catch(e) { - console.log( ('Error loading version info: ' + e).error.bold ); + if(entry.type == 'Directory') { + if( !fs.existsSync(libEntryPath) ) { + fs.mkdirSync(libEntryPath); + } + } else { + var writeStream = fs.createWriteStream(libEntryPath); + writeStream.on('error', function(err) { + console.log( ('Error writing, ' + libEntryPath + ': ' + err).bold.red ); + }); + entry.pipe(writeStream); } - try { - fs.unlink(self.tmpZipPath); - } catch(e) {} - }); - writeStream.on('error', function(err) { - console.log('Error: ' + err); - }); - readStream.pipe(writeStream); + + entry.autodrain(); + } + + readStream.pipe(unzip.Parse()) + .on('entry', onEntry) + .on('close', function(){ + try{ + console.log('Ionic version updated to: '.bold.green + self.versionData.version_number.bold ); + IonicStats.t(); + + self.writeVersionData(); + + var ionicBower = require('./bower').IonicBower; + ionicBower.setIonicVersion(self.versionData.version_number); + + } catch(e) { + console.log( ('Error loading version info: ' + e).error.bold ); + } + }); readStream.on('error', function(err){ console.log('Error: ' + err); }); + readStream.on('close', function(err){ + try { + fs.unlink(self.tmpZipPath); + } catch(e){} + }); + } catch(err) { console.log('Error: ' + err); } }; - -function deleteFolderRecursive(path) { - if( fs.existsSync(path) ) { - fs.readdirSync(path).forEach(function(file,index){ - var curPath = path + "/" + file; - if(fs.lstatSync(curPath).isDirectory()) { // recurse - deleteFolderRecursive(curPath); - } else { // delete file - fs.unlinkSync(curPath); - } - }); - fs.rmdirSync(path); +IonicLibTask.prototype.writeVersionData = function() { + try { + var versionData = { + "version": this.versionData.version_number || this.versionData.version, + "codename": this.versionData.version_codename || this.versionData.codename, + "date": this.versionData.release_date || this.versionData.date + }; + + var file = fs.createWriteStream( path.resolve('www/lib/ionic/version.json') ); + file.write( JSON.stringify(versionData, null, 2) ); + file.close(); + } catch(e) { + console.log( ('Error writing version data: ' + e).error.bold ); } -} - +}; exports.IonicLibTask = IonicLibTask; From c65760db79bdad46184718551416b2d8d4f8a1eb Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 9 Aug 2014 23:20:51 -0500 Subject: [PATCH 178/850] ionic setup sass --- README.md | 12 +++++ lib/ionic.js | 20 ++++++-- lib/ionic/bower.js | 4 +- lib/ionic/login.js | 2 +- lib/ionic/serve.js | 27 +++++++++- lib/ionic/setup.js | 123 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 lib/ionic/setup.js diff --git a/README.md b/README.md index 2e6ed11ac3..ca06471175 100644 --- a/README.md +++ b/README.md @@ -87,3 +87,15 @@ The third argument can be either `debug` or `release`, and the last argument can Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better. + + +## Using Sass + +By default, starter projects are hooked up to Ionic's precompiled CSS file, which is found in the project's `www/lib/ionic/css` directory, and is linked to the app in the head of the root `index.html` file. However, Ionic projects can also be customized using [Sass](http://sass-lang.com/), which gives developers and designers "superpowers" in terms of creating and maintaining CSS. Please follow these steps if you would like to use Sass for an Ionic project: + +1) Run `npm install` from the working directory of an Ionic project. This will install the [gulp.js](http://gulpjs.com/) build system and a few handy tasks, such as [gulp-sass](https://www.npmjs.org/package/gulp-sass) and [gulp-minify-css](https://www.npmjs.org/package/gulp-minify-css). +2) Remove `` from the `` of the root `index.html` file. +3) Remove `` from the `` of the root `index.html` file. +4) Add `` to the `` of the root `index.html` file. +5) In the `ionic.project` file, add the JavaScript property `sass: true` to the object. + diff --git a/lib/ionic.js b/lib/ionic.js index 5b341998e7..d8f7613f85 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -20,6 +20,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicUploadTask = require('./ionic/upload').IonicUploadTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, IonicLibTask = require('./ionic/lib').IonicLibTask, + IonicSetupTask = require('./ionic/setup').IonicSetupTask, IonicServeTask = require('./ionic/serve'), IonicProject = require('./ionic/project'), IonicStore = require('./ionic/store').IonicStore, @@ -137,7 +138,7 @@ var TASKS = [ }, options: { '--searchpath ': 'When looking up plugins by ID, look in this directory and\n\ - each of its subdirectories for the plugin before hitting the registry.' + each of its subdirectories for the plugin before hitting the registry.' }, task: IonicCordovaTask }, @@ -201,6 +202,15 @@ var TASKS = [ }, task: IonicLibTask }, + { + title: 'setup', + name: 'setup', + summary: 'Configure the project with a build tool ' + '(beta)'.yellow, + args: { + '[sass]': 'Setup the project to use Sass CSS precompiling' + }, + task: IonicSetupTask + }, { title: 'login', name: 'login', @@ -209,7 +219,7 @@ var TASKS = [ ]; Ionic = { - IONIC_DASH: 'http://apps.ionicframework.com', + IONIC_DASH: 'https://ionic.io', //IONIC_DASH: 'http://localhost:8000', IONIC_API: '/api/v1/', PRIVATE_PATH: '.ionic', @@ -246,7 +256,7 @@ Ionic = { w('\n'); - var rightColumn = 45; + var rightColumn = 47; var dots = ''; var indent = ''; var x, arg; @@ -265,7 +275,9 @@ Ionic = { w(' ' + dots.grey + ' '); - w(d.summary.bold); + if(d.summary) { + w(d.summary.bold); + } for(arg in d.args) { if( !d.args[arg] ) continue; diff --git a/lib/ionic/bower.js b/lib/ionic/bower.js index 82e447f6d5..9ceab6e83f 100644 --- a/lib/ionic/bower.js +++ b/lib/ionic/bower.js @@ -1,6 +1,6 @@ var fs = require('fs'), - path = require('path'), - colors = require('colors'); + path = require('path'), + colors = require('colors'); exports.IonicBower = { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index c61adaa799..61f4de86d4 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -123,7 +123,7 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { // Should be a 302 redirect status code if correct if(response.statusCode != 302) { - return ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH +' for help.'); + return ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH.white +' for help.'.red); } if(saveCookies) { diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index a4bc185953..f62c14d40c 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -8,6 +8,7 @@ var fs = require('fs'), vfs = require('vinyl-fs'), request = require('request'), Q = require('q'), + spawn = require('child_process').spawn, IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -24,6 +25,7 @@ IonicServeTask.prototype.run = function(ionic) { this.launchBrowser = !argv.nobrowser && !argv.b; this.runLivereload = !argv.nolivereload && !argv.r; + this.watchSass = project.get('sass') === true && !argv.nosass && !argv.s; this._start(ionic); @@ -62,6 +64,20 @@ IonicServeTask.prototype._start = function(ionic) { return ionic.fail('"www" directory cannot be found. Make sure the working directory is an Ionic project.'); } + if(this.watchSass) { + var childProcess = spawn('gulp', ['watch']); + + childProcess.stdout.on('data', function (data) { + process.stdout.write(data); + }); + + childProcess.stderr.on('data', function (data) { + if(data) { + process.stderr.write(data.toString().yellow); + } + }); + } + if(this.runLivereload) { vfs.watch('www/**/*', { }, function(f) { @@ -73,7 +89,7 @@ IonicServeTask.prototype._start = function(ionic) { if(err) { return ionic.fail('Unable to start live reload server:', err); } else { - console.log('Running live reload server at', (self.host(self.liveReloadPort).info.bold) ); + console.log('Running live reload server:'.green.bold, (self.host(self.liveReloadPort).bold) ); if(self.launchBrowser) { open( self.host(self.port) ); } @@ -88,7 +104,14 @@ IonicServeTask.prototype._start = function(ionic) { app.use(connect.static('www')) .listen(this.port); - console.log('Running dev server at', ( this.host(this.port) ).info.bold); + console.log('Running dev server:'.green.bold, ( this.host(this.port) ).bold); + + process.stdin.on('readable', function() { + var chunk = process.stdin.read(); + if (chunk !== null && /exit|quit|close|stop/gi.test(chunk)) { + process.exit(); + } + }); }; diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js new file mode 100644 index 0000000000..cc835892be --- /dev/null +++ b/lib/ionic/setup.js @@ -0,0 +1,123 @@ +var IonicTask = require('./task').IonicTask, + IonicStats = require('./stats').IonicStats, + fs = require('fs'), + path = require('path'), + argv = require('optimist').argv, + exec = require('child_process').exec, + Q = require('q'), + IonicProject = require('./project'), + colors = require('colors'); + +var IonicSetupTask = function() {}; + +IonicSetupTask.prototype = new IonicTask(); + +IonicSetupTask.prototype.run = function(ionic) { + if( argv._.length < 2 ) { + return ionic.fail('Missing setup task command.', 'setup'); + } + + var tasks = argv._.slice(1); + + for(var x=0; x(.*?)/gi.test(line) ) { + keepLine = false; + activeRemoving = false; + } else if( /lib\/ionic\/css\/ionic.css|css\/style.css/gi.test(line) ) { + keepLine = false; + } + + if(keepLine) { + cleanedLines.push(line); + } + } + + var project = IonicProject.load(); + project.set('sass', true); + project.save(); + + fs.writeFileSync(indexPath, cleanedLines.join('\n'), 'utf8'); + + console.log('Updated '.green.bold + indexPath.bold + ' '.yellow.bold + ' references to sass compiled css'.green.bold); + + console.log('\nIonic project ready to use Sass!'.green.bold); + console.log(' * Customize the app using'.yellow.bold, 'scss/ionic.app.scss'.bold); + console.log(' * Run'.yellow.bold, 'ionic serve'.bold, 'to compile to CSS and start a local dev server'.yellow.bold); + console.log(''); + + } catch(e) { + return ionic.fail('Error parsing ' + indexPath + ': ' + e); + } + + }); +}; + + +IonicSetupTask.prototype.npmInstall = function() { + var q = Q.defer(); + + var childProcess = exec('npm install'); + + childProcess.stdout.on('data', function (data) { + process.stdout.write(data); + }); + + childProcess.stderr.on('data', function (data) { + if(data) { + data = data.toString(); + if( !/no repository field/gi.test(data) ) { + process.stderr.write(data.yellow); + } + } + }); + + childProcess.on('exit', function(code){ + process.stderr.write('\n'); + if(code === 0) { + console.log('Successful '.green.bold + 'npm install'.bold); + q.resolve(); + } else { + console.log( 'Error running '.error.bold + 'npm install'.bold ); + q.reject() + } + }); + + return q.promise; +}; + + +exports.IonicSetupTask = IonicSetupTask; From 71ac69cd5ad81f26fbac6a21299b771cec70d9ec Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 9 Aug 2014 23:22:15 -0500 Subject: [PATCH 179/850] v1.1.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b4d072aa0..f152434f79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.9-beta1", + "version": "1.1.9", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 93d5aae155fd2897a01a393d3719868502772dd8 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 11 Aug 2014 09:22:44 -0500 Subject: [PATCH 180/850] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ae892be806..67329e6840 100644 --- a/README.md +++ b/README.md @@ -102,9 +102,9 @@ Note: we occasionally send anonymous usage statistics to the Ionic team to make By default, starter projects are hooked up to Ionic's precompiled CSS file, which is found in the project's `www/lib/ionic/css` directory, and is linked to the app in the head of the root `index.html` file. However, Ionic projects can also be customized using [Sass](http://sass-lang.com/), which gives developers and designers "superpowers" in terms of creating and maintaining CSS. Please follow these steps if you would like to use Sass for an Ionic project: -1) Run `npm install` from the working directory of an Ionic project. This will install the [gulp.js](http://gulpjs.com/) build system and a few handy tasks, such as [gulp-sass](https://www.npmjs.org/package/gulp-sass) and [gulp-minify-css](https://www.npmjs.org/package/gulp-minify-css). -2) Remove `` from the `` of the root `index.html` file. -3) Remove `` from the `` of the root `index.html` file. -4) Add `` to the `` of the root `index.html` file. -5) In the `ionic.project` file, add the JavaScript property `sass: true` to the object. +1. Run `npm install` from the working directory of an Ionic project. This will install [gulp.js](http://gulpjs.com/) and a few handy tasks, such as [gulp-sass](https://www.npmjs.org/package/gulp-sass) and [gulp-minify-css](https://www.npmjs.org/package/gulp-minify-css). +2. Remove `` from the `` of the root `index.html` file. +3. Remove `` from the `` of the root `index.html` file. +4. Add `` to the `` of the root `index.html` file. +5. In the `ionic.project` file, add the JavaScript property `sass: true` to the object. From 24e88dcbf6151bcdc0b34bbea87e236a99821708 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 11 Aug 2014 09:32:03 -0500 Subject: [PATCH 181/850] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67329e6840..04da02ce8f 100644 --- a/README.md +++ b/README.md @@ -100,11 +100,17 @@ Note: we occasionally send anonymous usage statistics to the Ionic team to make ## Using Sass -By default, starter projects are hooked up to Ionic's precompiled CSS file, which is found in the project's `www/lib/ionic/css` directory, and is linked to the app in the head of the root `index.html` file. However, Ionic projects can also be customized using [Sass](http://sass-lang.com/), which gives developers and designers "superpowers" in terms of creating and maintaining CSS. Please follow these steps if you would like to use Sass for an Ionic project: +By default, starter projects are hooked up to Ionic's precompiled CSS file, which is found in the project's `www/lib/ionic/css` directory, and is linked to the app in the head of the root `index.html` file. However, Ionic projects can also be customized using [Sass](http://sass-lang.com/), which gives developers and designers "superpowers" in terms of creating and maintaining CSS. Below are two ways to setup Sass for your Ionic project (the `ionic setup sass` command simply does the manual steps for you). Once Sass has been setup for your Ionic project, then the `ionic serve` command will also watch for Sass changes. + +#### Setup Sass Automatically + + ionic setup sass + + +#### Setup Sass Manually 1. Run `npm install` from the working directory of an Ionic project. This will install [gulp.js](http://gulpjs.com/) and a few handy tasks, such as [gulp-sass](https://www.npmjs.org/package/gulp-sass) and [gulp-minify-css](https://www.npmjs.org/package/gulp-minify-css). 2. Remove `` from the `` of the root `index.html` file. 3. Remove `` from the `` of the root `index.html` file. 4. Add `` to the `` of the root `index.html` file. 5. In the `ionic.project` file, add the JavaScript property `sass: true` to the object. - From 6c7419cf38e29478d5e84b2cd59e44f781249428 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 11 Aug 2014 09:47:54 -0500 Subject: [PATCH 182/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04da02ce8f..7b755fcea9 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Command-line flags/options: ## Testing in a Browser -Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. +Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. View [Using Sass](https://github.com/driftyco/ionic-cli/edit/master/README.md#using-sass) if you would also like to have `ionic serve` watch the project's Sass files. ```bash $ ionic serve [http-port] [livereload-port] [options] From 338b53dfdbe8831fe37ebb3b7b0967938c0c7a40 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 11 Aug 2014 09:48:22 -0500 Subject: [PATCH 183/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b755fcea9..8d43e2a2d9 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Command-line flags/options: ## Testing in a Browser -Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. View [Using Sass](https://github.com/driftyco/ionic-cli/edit/master/README.md#using-sass) if you would also like to have `ionic serve` watch the project's Sass files. +Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. View [Using Sass](https://github.com/driftyco/ionic-cli/blob/master/README.md#using-sass) if you would also like to have `ionic serve` watch the project's Sass files. ```bash $ ionic serve [http-port] [livereload-port] [options] From 24a00409ea38d73f5c184f0dd4edb0ad5e6343f0 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 11 Aug 2014 11:32:24 -0500 Subject: [PATCH 184/850] setup sass --- lib/ionic.js | 3 ++- lib/ionic/setup.js | 12 +++++++++++- lib/ionic/start.js | 16 ++++++++++++++-- lib/ionic/stats.js | 5 +++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index d8f7613f85..7c56cf9ac4 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -65,7 +65,8 @@ var TASKS = [ options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', '--id|-i': 'Package name for config, ie: com.mycompany.myapp', - '--no-cordova|-w': 'Create a basic structure without Cordova requirements' + '--no-cordova|-w': 'Create a basic structure without Cordova requirements', + '--sass|-s': 'Setup the project to use Sass CSS precompiling' }, task: IonicStartTask }, diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js index cc835892be..4ec4002b85 100644 --- a/lib/ionic/setup.js +++ b/lib/ionic/setup.js @@ -32,6 +32,8 @@ IonicSetupTask.prototype.run = function(ionic) { IonicSetupTask.prototype.sassSetup = function(ionic) { + var q = Q.defer(); + this.npmInstall().then(function(){ var indexPath = path.resolve('www/index.html'); @@ -41,6 +43,7 @@ IonicSetupTask.prototype.sassSetup = function(ionic) { try { lines = fs.readFileSync(indexPath, 'utf8').split('\n'); } catch(e) { + q.reject(e); return ionic.fail('Error loading ' + indexPath); } @@ -76,14 +79,21 @@ IonicSetupTask.prototype.sassSetup = function(ionic) { console.log('\nIonic project ready to use Sass!'.green.bold); console.log(' * Customize the app using'.yellow.bold, 'scss/ionic.app.scss'.bold); - console.log(' * Run'.yellow.bold, 'ionic serve'.bold, 'to compile to CSS and start a local dev server'.yellow.bold); + console.log(' * Run'.yellow.bold, 'ionic serve'.bold, 'to start a local dev server and watch/compile Sass to CSS'.yellow.bold); console.log(''); + q.resolve(); + } catch(e) { + q.reject(e); return ionic.fail('Error parsing ' + indexPath + ': ' + e); } + }, function(e){ + q.reject(e); }); + + return q.promise; }; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index c8782e7c63..e17ae2cd95 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -9,6 +9,7 @@ var fs = require('fs'), spawn = require('child_process').spawn, Q = require('q'), xml2js = require('xml2js'), + setup = require('./setup'), IonicProject = require('./project'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; @@ -63,7 +64,6 @@ IonicStartTask.prototype.run = function(ionic) { // Make sure to create this, or ask them if they want to override it if(this._checkTargetPath() === false) { - process.stderr.write('\nExiting.\n'); process.exit(1); } @@ -188,6 +188,7 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var npmQ = Q.defer(); var gulpQ = Q.defer(); var pluginQ = Q.defer(); + var q = Q.defer(); // Install dependencies for the starter project // Move the content of this repo into the www folder @@ -215,7 +216,18 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var ionicBower = require('./bower').IonicBower; ionicBower.setAppName(self.appName); - self._printQuickHelp(self.appDirectory); + if(argv.sass) { + console.log('setup sass'.green.bold); + var setupTask = new setup.IonicSetupTask(); + q = setupTask.sassSetup(self.ionic) + } else { + q.resolve(); + } + + q.then(function(){ + self._printQuickHelp(self.appDirectory); + }); + }, function(err) { return self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); }); diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index d5869665bf..ffd7ab3041 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -539,7 +539,8 @@ exports.IonicStats = { '-b': '--nobrowser', '-r': '--nolivereload', '-l': '--clear-signing', - '-n': '--no-email' + '-n': '--no-email', + '-s': '--sass' }; for(x=0; x Date: Mon, 11 Aug 2014 11:33:21 -0500 Subject: [PATCH 185/850] api login --- lib/ionic/login.js | 65 +++++++++++++++++++-------------------------- lib/ionic/upload.js | 14 +++++++--- 2 files changed, 37 insertions(+), 42 deletions(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 61f4de86d4..83b8823c25 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -97,53 +97,42 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { var jar = request.jar(); request({ - url: ionic.IONIC_DASH + '/login', - jar: jar + method: 'POST', + url: ionic.IONIC_DASH + ionic.IONIC_API + '/user/login', + jar: jar, + form: { + username: self.email.toString().toLowerCase(), + password: self.password + }, + proxy: process.env.PROXY || null }, - function(err, response, body) { - if(err || jar.cookies.length === 0) { + function (err, response, body) { + if(err) { return ionic.fail('Error logging in: ' + err); } - request({ - method: 'POST', - url: ionic.IONIC_DASH + '/login', - jar: jar, - form: { - username: self.email.toString().toLowerCase(), - password: self.password, - csrfmiddlewaretoken: jar.cookies[0].value - }, - proxy: process.env.PROXY || null - }, - function (err, response, body) { - if(err) { - return ionic.fail('Error logging in: ' + err); - } - - // Should be a 302 redirect status code if correct - if(response.statusCode != 302) { - return ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH.white +' for help.'.red); - } + // Should be a 302 redirect status code if correct + if(response.statusCode != 200) { + return ionic.fail('Email or Password incorrect. Please visit '+ ionic.IONIC_DASH.white +' for help.'.red); + } - if(saveCookies) { - // save cookies - if(!self.cookieData) { - self.cookieData = new IonicStore('cookies'); - } - self.cookieData.set(ionic.IONIC_DASH, jar); - self.cookieData.save(); + if(saveCookies) { + // save cookies + if(!self.cookieData) { + self.cookieData = new IonicStore('cookies'); } + self.cookieData.set(ionic.IONIC_DASH, jar); + self.cookieData.save(); + } - // save in memory - ionic.jar = jar; + // save in memory + ionic.jar = jar; - console.log('Logged in! :)'.green); + console.log('Logged in! :)'.green); - if(callback) { - callback(jar); - } - }); + if(callback) { + callback(jar); + } }); }; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 612e586ae9..e0400a4f6a 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -70,6 +70,16 @@ IonicUploadTask.prototype.run = function(ionic, callback) { response.setEncoding('utf8'); response.on("data", function(data) { try { + + if(response.statusCode == 401) { + q.reject('not_logged_in'); + return ionic.fail('Session expired (401). Please log in and run this command again.'); + + } else if(response.statusCode == 403) { + q.reject('forbidden'); + return ionic.fail('Forbidden upload (403)'); + } + var d = JSON.parse(data); if(d.errors && d.errors.length) { for (var j = 0; j < d.errors.length; j++) { @@ -94,10 +104,6 @@ IonicUploadTask.prototype.run = function(ionic, callback) { } } - } else if(response.statusCode == 401) { - console.error( ('Session expired. Please log in again and run this command again.').red.bold ); - q.reject('not_logged_in'); - } else { q.reject('upload_error'); } From b49d1792dd376a389fa6f6e20f23a85e49c66c48 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 12 Aug 2014 16:19:01 -0500 Subject: [PATCH 186/850] cli version in fail msg --- .gitignore | 1 + lib/ionic.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ccc574f1f2..d0acd17ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.sw* *.cookies node_modules/ +.idea/ diff --git a/lib/ionic.js b/lib/ionic.js index 7c56cf9ac4..b163fb7332 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -407,7 +407,7 @@ Ionic = { fail: function(msg, taskHelp) { this.hasFailed = true; process.stderr.write(msg.error.bold); - process.stderr.write('\n'); + process.stderr.write( (' (CLI v' + settings.version + ')').error.bold + '\n'); if(taskHelp) { for(var i = 0; i < TASKS.length; i++) { var task = TASKS[i]; From 44835e31c8a9a5a6fb903e75eb3f56304068e8b3 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 15 Aug 2014 10:07:32 -0500 Subject: [PATCH 187/850] build sass on setup --- lib/ionic/setup.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js index 4ec4002b85..68263d22ec 100644 --- a/lib/ionic/setup.js +++ b/lib/ionic/setup.js @@ -33,6 +33,7 @@ IonicSetupTask.prototype.run = function(ionic) { IonicSetupTask.prototype.sassSetup = function(ionic) { var q = Q.defer(); + var self = this; this.npmInstall().then(function(){ @@ -82,7 +83,9 @@ IonicSetupTask.prototype.sassSetup = function(ionic) { console.log(' * Run'.yellow.bold, 'ionic serve'.bold, 'to start a local dev server and watch/compile Sass to CSS'.yellow.bold); console.log(''); - q.resolve(); + self.buildSass().then(function(){ + q.resolve(); + }); } catch(e) { q.reject(e); @@ -97,6 +100,36 @@ IonicSetupTask.prototype.sassSetup = function(ionic) { }; +IonicSetupTask.prototype.buildSass = function() { + var q = Q.defer(); + + var childProcess = exec('gulp sass'); + + childProcess.stdout.on('data', function (data) { + process.stdout.write(data); + }); + + childProcess.stderr.on('data', function (data) { + if(data) { + process.stderr.write(data.toString().yellow); + } + }); + + childProcess.on('exit', function(code){ + process.stderr.write('\n'); + if(code === 0) { + console.log('Successful '.green.bold + 'sass build'.bold); + q.resolve(); + } else { + console.log( 'Error running '.error.bold + 'gulp sass'.bold ); + q.reject() + } + }); + + return q.promise; +}; + + IonicSetupTask.prototype.npmInstall = function() { var q = Q.defer(); From a987653e07c3498b7216d896c6015942dd993756 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 15 Aug 2014 22:28:20 -0500 Subject: [PATCH 188/850] lower case start template name --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index e17ae2cd95..0c82cdf427 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -58,7 +58,7 @@ IonicStartTask.prototype.run = function(ionic) { this.isCordovaProject = (argv.cordova !== false && !argv.w); // start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs - var starterProject = argv.template || argv.t || argv._[2] || 'tabs'; + var starterProject = (argv.template || argv.t || argv._[2] || 'tabs').toLowerCase(); this.targetPath = path.resolve(this.appDirectory); From 2805b39b148a05ab24541b7d92cb7f630538d7b1 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 18 Aug 2014 09:41:17 -0500 Subject: [PATCH 189/850] rm /www/Readme.md --- lib/ionic/start.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 0c82cdf427..26f71b674d 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -216,6 +216,10 @@ IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { var ionicBower = require('./bower').IonicBower; ionicBower.setAppName(self.appName); + try { + fs.unlinkSync(self.targetPath + '/www/README.md'); + } catch(e) {} + if(argv.sass) { console.log('setup sass'.green.bold); var setupTask = new setup.IonicSetupTask(); From ba8c9620bb488bc355db80bb0ca43e2755c12a22 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 18 Aug 2014 09:41:33 -0500 Subject: [PATCH 190/850] gulp sass on watch --- lib/ionic/serve.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index f62c14d40c..617fb85a7f 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -65,7 +65,7 @@ IonicServeTask.prototype._start = function(ionic) { } if(this.watchSass) { - var childProcess = spawn('gulp', ['watch']); + var childProcess = spawn('gulp', ['sass','watch']); childProcess.stdout.on('data', function (data) { process.stdout.write(data); From bca11f48276d2619cc1f03a6c9fa6ecdeabd5b1e Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 18 Aug 2014 09:41:48 -0500 Subject: [PATCH 191/850] 1.1.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f152434f79..85b51b8be3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.9", + "version": "1.1.10", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 62eba5e718ee40e90634a626057197e6b1ac0737 Mon Sep 17 00:00:00 2001 From: Steven Pautz Date: Mon, 18 Aug 2014 11:00:16 -0400 Subject: [PATCH 192/850] Update after_prepare hook to match tags which have no attributes. Fixes #74 --- lib/hooks/after_prepare/010_add_platform_class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hooks/after_prepare/010_add_platform_class.js b/lib/hooks/after_prepare/010_add_platform_class.js index cdfb187492..edd86c9065 100755 --- a/lib/hooks/after_prepare/010_add_platform_class.js +++ b/lib/hooks/after_prepare/010_add_platform_class.js @@ -52,7 +52,7 @@ function addPlatformBodyTag(indexPath, platform) { function findBodyTag(html) { // get the body tag try{ - return html.match(//gi)[0]; + return html.match(/])(.*?)>/gi)[0]; }catch(e){} } From 96496ea58f713737aebdd0ef89a5bd025d8ec426 Mon Sep 17 00:00:00 2001 From: Jamieson Warner Date: Tue, 26 Aug 2014 15:41:08 -0500 Subject: [PATCH 193/850] remove double slash from api login calls --- lib/ionic/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 83b8823c25..ce1109faae 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -98,7 +98,7 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { var jar = request.jar(); request({ method: 'POST', - url: ionic.IONIC_DASH + ionic.IONIC_API + '/user/login', + url: ionic.IONIC_DASH + ionic.IONIC_API + 'user/login', jar: jar, form: { username: self.email.toString().toLowerCase(), From 03bdf23418c0457be98e95ac2d9944b59b7bb2b0 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 28 Aug 2014 00:22:39 -0500 Subject: [PATCH 194/850] start ionic apps from codepen url --- lib/ionic.js | 19 +- lib/ionic/start.js | 425 ++++++++++++++++++++++++++++++++------------- package.json | 2 +- 3 files changed, 312 insertions(+), 134 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index b163fb7332..caf294ca6a 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -406,8 +406,10 @@ Ionic = { fail: function(msg, taskHelp) { this.hasFailed = true; - process.stderr.write(msg.error.bold); - process.stderr.write( (' (CLI v' + settings.version + ')').error.bold + '\n'); + if(msg) { + process.stderr.write(msg.error.bold); + process.stderr.write( (' (CLI v' + settings.version + ')').error.bold + '\n'); + } if(taskHelp) { for(var i = 0; i < TASKS.length; i++) { var task = TASKS[i]; @@ -509,17 +511,16 @@ Ionic = { return q.promise; }, /** - * Fetch a repo from GitHub, unzip it to a specific folder. + * Download a zip file, unzip it to a specific folder. */ - fetchRepo: function(targetPath, repoName, repoUrl) { + fetchArchive: function(targetPath, archiveUrl) { var q = Q.defer(); // The folder name the project will be downloaded and extracted to - var repoFolderName = repoName + '-master'; - console.log('\nDownloading:'.info.bold, repoUrl); + console.log('\nDownloading:'.info.bold, archiveUrl); var tmpFolder = os.tmpdir(); - var tempZipFilePath = path.join(tmpFolder, repoName + new Date().getTime() + '.zip'); + var tempZipFilePath = path.join(tmpFolder, 'ionic-starter-' + new Date().getTime() + '.zip'); var tempZipFileStream = fs.createWriteStream(tempZipFilePath); var unzipRepo = function(fileName) { @@ -527,7 +528,7 @@ Ionic = { var writeStream = unzip.Extract({ path: targetPath }); writeStream.on('close', function() { - q.resolve(repoFolderName); + q.resolve(); }); writeStream.on('error', function(err) { q.reject(err); @@ -536,7 +537,7 @@ Ionic = { }; var proxy = process.env.PROXY || null; - request({ url: repoUrl, encoding: null, proxy: proxy }, function(err, res, body) { + request({ url: archiveUrl, encoding: null, proxy: proxy }, function(err, res, body) { if(!res || res.statusCode !== 200) { q.reject(res); return; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 26f71b674d..9c71169b12 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -14,20 +14,6 @@ var fs = require('fs'), IonicTask = require('./task').IonicTask; IonicStats = require('./stats').IonicStats; -fs.mkdirParent = function(dirPath, mode, callback) { - //Call the standard fs.mkdir - fs.mkdir(dirPath, mode, function(error) { - //When it fail in this way, do the custom steps - if (error && error.errno === 34) { - //Create all the parents recursively - fs.mkdirParent(path.dirname(dirPath), mode, callback); - //And then the directory - fs.mkdirParent(dirPath, mode, callback); - } - //Manually run the callback since we used our own callback to do all these - callback && callback(error); - }); -}; var IonicStartTask = function() {}; @@ -54,43 +40,66 @@ IonicStartTask.prototype.run = function(ionic) { this.appName = appNameSplit[ appNameSplit.length -1 ]; } + // get a packge name, like com.ionic.myapp this.packageName = argv.id || argv.i; this.isCordovaProject = (argv.cordova !== false && !argv.w); // start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs - var starterProject = (argv.template || argv.t || argv._[2] || 'tabs').toLowerCase(); + this.template = (argv.template || argv.t || argv._[2] || 'tabs'); + // figure out the full path this.targetPath = path.resolve(this.appDirectory); - // Make sure to create this, or ask them if they want to override it - if(this._checkTargetPath() === false) { - process.exit(1); - } - - console.log('Creating Ionic app in folder', this.targetPath, 'based on', starterProject.info.bold, 'project'); + console.log('Creating Ionic app in folder', this.targetPath, 'based on', this.template.info.bold, 'project'); - fs.mkdirSync(this.targetPath); + // Make sure to create this + if( fs.existsSync(this.targetPath) ) { + // check if its empty first + if( fs.readdirSync(this.targetPath).length ) { + // only freak if target path already has files in it + return this.ionic.fail('The directory '.error.bold + this.targetPath + ' already exists, please remove it if you would like to create a new ionic project there.'.error.bold); + } + } else { + // create the app directory + fs.mkdirSync(this.targetPath); + } - this._fetchAndWriteSeed(starterProject.toLowerCase()); + // kick it all off + this.startApp(); +}; - if(ionic.hasFailed) return; - this._writeProjectFile(ionic); +IonicStartTask.prototype.startApp = function() { + var self = this; + self.fetchWrapper() + .then(function(){ + return self.fetchSeed(); + }) + .then(function(){ + return self.initCordova(); + }) + .then(function(){ + return self.setupSass(); + }) + .then(function(){ + return self.finalize(); + }) + .catch(function(err) { + console.error('Error: Unable to initalize app: '.error.bold, err); + return self.ionic.fail(''); + }); }; -IonicStartTask.prototype._getStarterUrl = function(repo) { - return 'https://github.com/driftyco/' + repo + '/archive/master.zip' ; -}; -IonicStartTask.prototype._fetchWrapper = function() { +IonicStartTask.prototype.fetchWrapper = function() { var q = Q.defer(); var self = this; - var repoName = IonicStartTask.WRAPPER_REPO_NAME; var repoUrl = 'https://github.com/driftyco/' + IonicStartTask.WRAPPER_REPO_NAME + '/archive/master.zip'; - Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { + Ionic.fetchArchive(self.targetPath, repoUrl).then(function() { + var repoFolderName = IonicStartTask.WRAPPER_REPO_NAME + '-master'; cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); rm('-rf', self.targetPath + '/' + repoFolderName + '/'); cd(self.targetPath); @@ -113,25 +122,148 @@ IonicStartTask.prototype._fetchWrapper = function() { return q.promise; }; -IonicStartTask.prototype._installCordovaPlugins = function() { + +IonicStartTask.prototype.fetchSeed = function() { + + if(this.template.toLowerCase().indexOf('codepen') > -1) { + this.seedType = 'codepen'; + return this.fetchCodepen(); + } + + this.seedType = 'ionic-starter'; + return this.fetchIonicStarter(); +}; + + +IonicStartTask.prototype.fetchCodepen = function() { + // Edit Url: http://codepen.io/ionic/pen/gblny + // Download: http://codepen.io/ionic/share/zip/gblny/ + var self = this; + var splt = self.template.split('?')[0].split('#')[0].split('/'); + var wwwPath = path.join(self.targetPath, 'www'); + var codepenId = splt[ splt.length - 1 ]; + if(!codepenId) { + codepenId = splt[ splt.length - 2 ]; + } + + console.log('\nDownloading Codepen:'.info.bold, codepenId); + + var qHTML = Q.defer(); + var qCSS = Q.defer(); + var qJS = Q.defer(); + + var htmlUrl = 'http://codepen.io/ionic/pen/' + codepenId + '.html'; + var cssUrl = 'http://codepen.io/ionic/pen/' + codepenId + '.css'; + var jsUrl = 'http://codepen.io/ionic/pen/' + codepenId + '.js'; + + var proxy = process.env.PROXY || null; + + request({ url: htmlUrl, proxy: proxy }, function(err, res, html) { + if(!err && res && res.statusCode === 200 && html) { + html = '\n' + html; + + var resources = ' \n' + + ' \n\n' + + ' '; + + html = html.replace(/<\/head>/i, '\n' + resources); + + fs.writeFileSync(path.join(wwwPath, 'index.html'), html, 'utf8'); + } + qHTML.resolve(); + }); + + request({ url: cssUrl, proxy: proxy }, function(err, res, css) { + if(!err && res && res.statusCode === 200 && css) { + var cssPath = path.join(wwwPath, 'css'); + if(!fs.existsSync(cssPath)) { + fs.mkdirSync(cssPath); + } + css = css.replace("cursor: url('http://ionicframework.com/img/finger.png'), auto;", ''); + fs.writeFileSync(path.join(cssPath, 'style.css'), css, 'utf8'); + } + qCSS.resolve(); + }); + + request({ url: jsUrl, proxy: proxy }, function(err, res, js) { + if(!err && res && res.statusCode === 200 && js) { + var jsPath = path.join(wwwPath, 'js'); + if(!fs.existsSync(jsPath)) { + fs.mkdirSync(jsPath); + } + fs.writeFileSync(path.join(jsPath, 'app.js'), js, 'utf8'); + } + qJS.resolve(); + }); + + return Q.all([qHTML.promise, qCSS.promise, qJS.promise]); +}; + + +IonicStartTask.prototype.fetchIonicStarter = function() { + var self = this; var q = Q.defer(); - console.log('Initializing cordova project.'.info.bold); - exec('cordova plugin add org.apache.cordova.device && ' + - 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard', - function(err, stdout, stderr) { - if(err) { - q.reject(stderr); - } else { - q.resolve(stdout); - } + // Get the starter project repo name: + var repoName = 'ionic-starter-' + self.template; + + // Get the URL for the starter project repo: + var repoUrl = 'https://github.com/driftyco/' + repoName + '/archive/master.zip'; + + Ionic.fetchArchive(self.targetPath, repoUrl).then(function() { + + var repoFolderName = repoName + '-master'; + + // Move the content of this repo into the www folder + cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); + + // Clean up start template folder + rm('-rf', self.targetPath + '/' + repoFolderName + '/'); + + q.resolve(); + + }).catch(function(err) { + console.error('Error: Unable to fetch project: HTTP:'.error.bold, err.statusCode); + console.error('Valid project types are "blank", "tabs", or "sidemenu"'.error.bold); + console.error('More info available at: http://ionicframework.com/getting-started/'.error.bold); + return self.ionic.fail(''); }); return q.promise; }; -IonicStartTask.prototype._updateConfigXml = function() { + +IonicStartTask.prototype.initCordova = function() { + var q = Q.defer(); + + if(this.isCordovaProject) { + // update the config.xml file from cmd line args + this.updateConfigXml(); + + if(this.ionic.hasFailed) return; + + console.log('Initializing cordova project.'.info.bold); + exec('cordova plugin add org.apache.cordova.device && ' + + 'cordova plugin add org.apache.cordova.console && ' + + 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard', + function(err, stdout, stderr) { + if(err) { + this.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); + q.reject(stderr); + } else { + q.resolve(stdout); + } + }); + + } else { + q.resolve(); + } + + return q.promise; +}; + + +IonicStartTask.prototype.updateConfigXml = function() { var self = this; console.log('\nUpdate config.xml'.info.bold); @@ -168,123 +300,168 @@ IonicStartTask.prototype._updateConfigXml = function() { } }; -IonicStartTask.prototype._fetchAndWriteSeed = function(projectType) { - var self = this; - // First, grab the wrapper project. - var wrapperPromise = this._fetchWrapper(); +IonicStartTask.prototype.setupSass = function() { + if(argv.sass) { + // auto setup sass if they set the option + console.log('setup sass'.green.bold); + var setupTask = new setup.IonicSetupTask(); + return setupTask.sassSetup(this.ionic); + } + + // didn't ask to setup sass, so resolve it + var q = Q.defer(); + q.resolve(); + return q.promise; +}; - wrapperPromise.then(function() { - // Get the starter project repo name: - var repoName = 'ionic-starter-' + projectType; - // The folder name the project will be downloaded and extracted to - var repoFolderName = repoName + '-master'; +IonicStartTask.prototype.updateLibFiles = function() { + var libPath = argv.lib || argv.l || 'lib/ionic'; - // Get the URL for the starter project repo: - var repoUrl = self._getStarterUrl(repoName); + if(libPath == 'lib' && this.seedType == 'ionic-starter') { + // don't bother if it still will be the default + return; + } - Ionic.fetchRepo(self.targetPath, repoName, repoUrl).then(function(repoFolderName) { - var npmQ = Q.defer(); - var gulpQ = Q.defer(); - var pluginQ = Q.defer(); - var q = Q.defer(); - // Install dependencies for the starter project + var libFiles = 'ionic.css ionic.min.css ionic.js ionic.min.js ionic.bundle.js ionic.bundle.min.js ionic-angular.js ionic-angular.min.js'.split(' '); - // Move the content of this repo into the www folder - cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www'); + function changeLibPath(originalUrl) { + var splt = originalUrl.split('/'); + var newUrl = [ libPath ]; + var filename = splt[ splt.length - 1 ]; - // Clean up start template folder - rm('-rf', self.targetPath + '/' + repoFolderName + '/'); + if(filename.indexOf('.css') > -1) { + newUrl.push('css'); + } else if(filename.indexOf('.js') > -1) { + newUrl.push('js'); + } - if(self.isCordovaProject) { - // update the config.xml file from cmd line args - self._updateConfigXml(); + newUrl.push(filename); - if(self.ionic.hasFailed) return; + return newUrl.join('/'); + } - self._installCordovaPlugins().then(function(output) { - pluginQ.resolve(); - }, function(err) { - pluginQ.reject(err); - }); + function replaceResource(html, originalTag) { + originalTag = originalTag.replace(/'/g, '"'); + var splt = originalTag.split('"'); + var newTagArray = []; + + for(var x=0; x -1 ) { + return true; + } + } + } - q.then(function(){ - self._printQuickHelp(self.appDirectory); - }); + function getLibTags(html) { + var resourceTags = []; + var libTags = []; - }, function(err) { - return self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); - }); + try{ + resourceTags = resourceTags.concat( html.match(/\n\n' + + ' \n' + ' '; html = html.replace(/<\/head>/i, '\n' + resources); + html = self.convertTemplates(html); + fs.writeFileSync(path.join(wwwPath, 'index.html'), html, 'utf8'); } qHTML.resolve(); }); - request({ url: cssUrl, proxy: proxy }, function(err, res, css) { + request({ url: codepenUrl + '.css', proxy: proxy }, function(err, res, css) { if(!err && res && res.statusCode === 200 && css) { var cssPath = path.join(wwwPath, 'css'); if(!fs.existsSync(cssPath)) { @@ -185,7 +180,7 @@ IonicStartTask.prototype.fetchCodepen = function() { qCSS.resolve(); }); - request({ url: jsUrl, proxy: proxy }, function(err, res, js) { + request({ url: codepenUrl + '.js', proxy: proxy }, function(err, res, js) { if(!err && res && res.statusCode === 200 && js) { var jsPath = path.join(wwwPath, 'js'); if(!fs.existsSync(jsPath)) { @@ -200,6 +195,64 @@ IonicStartTask.prototype.fetchCodepen = function() { }; +IonicStartTask.prototype.convertTemplates = function(html) { + var templates = []; + var self = this; + + try { + var scripts = html.match(/\n' + - ' '; + ' \n'; + + if(self.isCordovaProject) { + resources += ' \n'; + } + + resources += ' '; html = html.replace(/<\/head>/i, '\n' + resources); From a4f1e251b8e7338015c25940d817d8240d9f580b Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 29 Aug 2014 12:17:31 -0500 Subject: [PATCH 198/850] update help printout --- lib/ionic.js | 56 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index caf294ca6a..2a6013b341 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -60,11 +60,13 @@ var TASKS = [ args: { '[options]': 'any flags for the command', '': 'directory for the new project', - '[template]': 'Starter template to use (tabs, sidemenu, blank)' + '[template]': 'Template name, ex: tabs, sidemenu, blank\n' + + 'Codepen url, ex: http://codepen.io/ionic/pen/odqCz\n' + + 'Defaults to Ionic "tabs" starter template' }, options: { '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', - '--id|-i': 'Package name for config, ie: com.mycompany.myapp', + '--id|-i': 'Package name for config, ex: com.mycompany.myapp', '--no-cordova|-w': 'Create a basic structure without Cordova requirements', '--sass|-s': 'Setup the project to use Sass CSS precompiling' }, @@ -76,7 +78,7 @@ var TASKS = [ summary: 'Start a local development server for app dev and testing', args: { '[options]': '', - '[http-port]': '', + '[port]': '', '[livereload-port]': '' }, options: { @@ -138,8 +140,8 @@ var TASKS = [ '': 'Can be a plugin ID, a local path, or a git URL.' }, options: { - '--searchpath ': 'When looking up plugins by ID, look in this directory and\n\ - each of its subdirectories for the plugin before hitting the registry.' + '--searchpath ': 'When looking up plugins by ID, look in this directory and\n' + + 'subdirectories for the plugin before using the registry.' }, task: IonicCordovaTask }, @@ -157,7 +159,7 @@ var TASKS = [ title: 'package', name: 'package', alt: ['pack'], - summary: 'Package an app using the Ionic Build service', + summary: 'Package an app using the Ionic Build service' + ' (beta)'.yellow, args: { '[options]': '', '': '"debug" or "release"', @@ -193,13 +195,13 @@ var TASKS = [ { title: 'lib', name: 'lib', - summary: 'Gets Ionic library version info or updates the Ionic library', + summary: 'Ionic library version info or updates the Ionic library', args: { '[options]': '', - '[update]': 'Updates the Ionic Framework version in www/lib/ionic' + '[update]': 'Updates the Ionic Framework in www/lib/ionic' }, options: { - '--version|-v': 'Exact Ionic version, otherwise it will default to the latest' + '--version|-v': 'Ionic version, otherwise it will default to the latest' }, task: IonicLibTask }, @@ -257,7 +259,7 @@ Ionic = { w('\n'); - var rightColumn = 47; + var rightColumn = 41; var dots = ''; var indent = ''; var x, arg; @@ -282,14 +284,28 @@ Ionic = { for(arg in d.args) { if( !d.args[arg] ) continue; - var argLine = arg; indent = ''; w('\n'); while(indent.length < rightColumn) { indent += ' '; } - w( (indent + ' ' + argLine + ' ' + d.args[arg]).bold ); + w( (indent + ' ' + arg + ' ').bold ); + + var argDescs = d.args[arg].split('\n'); + var argIndent = indent + ' '; + + for(x=0; x Date: Fri, 29 Aug 2014 12:18:00 -0500 Subject: [PATCH 199/850] fix obj reference --- lib/ionic/start.js | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 9f06ea1ace..0e7083060f 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -317,6 +317,7 @@ IonicStartTask.prototype.fetchIonicStarter = function() { IonicStartTask.prototype.initCordova = function() { + var self = this; var q = Q.defer(); if(this.isCordovaProject) { @@ -331,7 +332,8 @@ IonicStartTask.prototype.initCordova = function() { 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard', function(err, stdout, stderr) { if(err) { - this.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. Try updating (npm install -g cordova), removing this project folder, and trying again.'); + self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. ' + + 'Try updating (npm install -g cordova), removing this project folder, and trying again.'); q.reject(stderr); } else { q.resolve(stdout); diff --git a/package.json b/package.json index 65ed3ac00e..5f3e09afe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.11", + "version": "1.1.12-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From bd8f695b60527188abba2e38d3ea0d4a2dd60779 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 29 Aug 2014 13:48:36 -0500 Subject: [PATCH 200/850] use cordova plugin add com.ionic.keyboard --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 0e7083060f..c7338606aa 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -329,7 +329,7 @@ IonicStartTask.prototype.initCordova = function() { console.log('Initializing cordova project.'.info.bold); exec('cordova plugin add org.apache.cordova.device && ' + 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add https://github.com/driftyco/ionic-plugins-keyboard', + 'cordova plugin add com.ionic.keyboard', function(err, stdout, stderr) { if(err) { self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. ' + From a5a386380ce28334841bca5812dbaa3fa00dba93 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 29 Aug 2014 13:48:48 -0500 Subject: [PATCH 201/850] 1.1.12 --- README.md | 25 +++++++++++++++++-------- package.json | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8d43e2a2d9..445e299d73 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,28 @@ $ sudo npm install -g ionic ## Starting an Ionic App ```bash -$ ionic start myApp [template] +$ ionic start myapp [template] ``` -There are three choices of templates: +Starter templates can either come from a named template, or from any Codepen URL. -* Side-Menu (sidemenu) -* Tabs (tabs) -* Blank (blank) +Named template starters: + +* [tabs](https://github.com/driftyco/ionic-starter-tabs) (Default) +* [sidemenu](https://github.com/driftyco/ionic-starter-sidemenu) +* [blank](https://github.com/driftyco/ionic-starter-blank) + +Codepen URL starters: + +* Any Codepen url, ex: [http://codepen.io/ionic/pen/odqCz](http://codepen.io/ionic/pen/odqCz) +* [Ionic Codepen Demos](http://codepen.io/ionic/public-list/) Command-line flags/options: - --app-name, -a ...... Human readable name for the app (Use quotes around the name) - --id, -i ............ Package name set in the config, ie: com.mycompany.myapp + --app-name, -a ...... Human readable name for the app + (Use quotes around the name) + --id, -i ............ Package name set in the config + ex: com.mycompany.myapp --no-cordova, -w .... Do not create an app targeted for Cordova @@ -71,7 +80,7 @@ $ ionic run ios ## Update Ionic lib Update Ionic library files, which are found in the `www/lib/ionic` directory. If bower is being used -by the project, this command will automatically run `bower update ionic`, otherwise this command updates +by the project, this command will automatically run `bower update ionic`, otherwise this command updates the local static files from Ionic's CDN. ```bash diff --git a/package.json b/package.json index 5f3e09afe1..06a22f33fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.12-beta1", + "version": "1.1.12", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From ee8238b3e5088cd94fa5f773f0b8c882932de218 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 30 Aug 2014 21:16:51 -0500 Subject: [PATCH 202/850] fix start stats --- lib/ionic.js | 8 ++++++++ lib/ionic/start.js | 2 ++ lib/ionic/stats.js | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/lib/ionic.js b/lib/ionic.js index 2a6013b341..bf0dd6f2f1 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -423,6 +423,14 @@ Ionic = { return this._printHelpLines(); } + if(argv['stats-opt-out']) { + var ionicConfig = new IonicStore('ionic.config'); + ionicConfig.set('statsOptOut', true); + ionicConfig.save(); + console.log('Successful stats opt-out'); + return; + } + var task = this._tryBuildingTask(); if(!task) { return this._printAvailableTasks(); diff --git a/lib/ionic/start.js b/lib/ionic/start.js index c7338606aa..b933496bfe 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -531,6 +531,8 @@ IonicStartTask.prototype.finalize = function() { } catch(e) {} this.printQuickHelp(); + + IonicStats.t(); }; diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index ffd7ab3041..7c47ecd853 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -523,6 +523,10 @@ exports.IonicStats = { if(process.argv.length < 3) return; + if( ionicConfig.get('statsOptOut') === true ) { + return; + } + var cmdName = process.argv[2].toLowerCase(); var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); // skip the cmdName From 86d3e1c86d2778511ee1a6af7acac058bfd502e4 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sun, 31 Aug 2014 01:17:53 -0500 Subject: [PATCH 203/850] live reload for run command --- README.md | 12 +++ lib/ionic.js | 5 +- lib/ionic/cordova.js | 181 ++++++++++++++++++++++++++++++++++++++++++- lib/ionic/serve.js | 73 ++++++++++------- package.json | 2 +- 5 files changed, 239 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 445e299d73..9195d8ee84 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,18 @@ $ ionic emulate ios $ ionic run ios ``` +Command-line flags/options: + + [--live-reload|-l] ... Live reload app dev files from the device (beta) + [--debug|--release] + +### Live Reload Within Cordova + +The `run` command will deploy the app to the specified platform devices and emulators. You can also run __live reload__ on the specified platform device by adding the `--live-reload` option. The `run` command's live reload functionality is similar to `ionic serve`, but instead of using a standard browser, the Cordova app itself is watching for any changes to its files and reloading when needed. This reduces the requirement to constantly rebuild the Cordova app for small changes. However, any changes to plugins will still require a full rebuild. + +In order for live reload to work, symlinks are automatically created and added to the `www` root, and the `` node in the config.xml file is updated to point to the dev server created by Ionic's CLI. On exit (by typing "exit" or using ctrl+c), the app's original settings will be restored and the symlinks should automatically be deleted. __Currently in beta__ + + ## Update Ionic lib Update Ionic library files, which are found in the `www/lib/ionic` directory. If bower is being used diff --git a/lib/ionic.js b/lib/ionic.js index bf0dd6f2f1..4142cfd653 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -21,7 +21,7 @@ var IonicStartTask = require('./ionic/start').IonicStartTask, IonicPackageTask = require('./ionic/package').IonicPackageTask, IonicLibTask = require('./ionic/lib').IonicLibTask, IonicSetupTask = require('./ionic/setup').IonicSetupTask, - IonicServeTask = require('./ionic/serve'), + IonicServeTask = require('./ionic/serve').IonicServeTask, IonicProject = require('./ionic/project'), IonicStore = require('./ionic/store').IonicStore, path = require('path'), @@ -116,6 +116,7 @@ var TASKS = [ '': '' }, options: { + '--live-reload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, '--debug|--release': '', '--device|--emulator|--target=FOO': '' }, @@ -159,7 +160,7 @@ var TASKS = [ title: 'package', name: 'package', alt: ['pack'], - summary: 'Package an app using the Ionic Build service' + ' (beta)'.yellow, + summary: 'Package an app using the Ionic Build service' + ' (beta)'.yellow, args: { '[options]': '', '': '"debug" or "release"', diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 2d97530118..27569334bd 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -1,6 +1,8 @@ var IonicTask = require('./task').IonicTask, IonicStats = require('./stats').IonicStats, fs = require('fs'), + argv = require('optimist').argv, + xml2js = require('xml2js'), path = require('path'), exec = require('child_process').exec, colors = require('colors'); @@ -10,9 +12,17 @@ var IonicCordovaTask = function() {}; IonicCordovaTask.prototype = new IonicTask(); IonicCordovaTask.prototype.run = function(ionic) { + var self = this; + self.ionic = ionic; var cmdName = process.argv[2].toLowerCase(); var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); + self.isLiveReload = (cmdName == 'run' && (argv.livereload || argv['live-reload'] || argv.l)); + + if(self.isLiveReload) { + self.setupLiveReload(); + } + // backwards compatibility prior to fully wrapping cordova cmds if(cmdName == 'platform') { // `ionic platform ` used to actually run `ionic platform add ` @@ -37,22 +47,187 @@ IonicCordovaTask.prototype.run = function(ionic) { cmdArgs.unshift(cmdName); - var cordovaCmd = exec('cordova ' + cmdArgs.join(' ')); + var cordovaProcess = exec('cordova ' + cmdArgs.join(' ')); - cordovaCmd.stdout.on('data', function (data) { + cordovaProcess.stdout.on('data', function (data) { process.stdout.write(data); }); - cordovaCmd.stderr.on('data', function (data) { + cordovaProcess.stderr.on('data', function (data) { if(data) { process.stderr.write(data.toString().error.bold); } }); + cordovaProcess.on('exit', function(){ + if(self.isLiveReload) { + self.wwwSymlinks(true); + self.setConfigXml({ + resetContent: true + }); + } + }); + + if(self.isLiveReload) { + if (process.platform === 'win32'){ + // emit SIGINT on windows + var readline = require ('readline'), + rl = readline.createInterface ({ + input: process.stdin, + output: process.stdout + }); + + rl.on ('SIGINT', function (){ + process.emit('SIGINT'); + }); + } + + process.on('SIGINT', function(){ + // doing this so the exit event fires on Cmd + c + process.exit(); + }); + process.on('exit', function() { + // remove the symlinks + self.wwwSymlinks(false); + }); + } + IonicStats.t(); }; +IonicCordovaTask.prototype.setupLiveReload = function() { + console.log('Setup Live Reload'.green.bold); + + var serve = new require('./serve'); + var serveTask = new serve.IonicServeTask(); + serveTask.loadSettings(); + serveTask.runLivereload = true; + serveTask.launchBrowser = false; + serveTask.start(this.ionic); + + this.setConfigXml({ + devServer: serveTask.devServer + }); +}; + + +IonicCordovaTask.prototype.setConfigXml = function(options) { + var self = this; + var madeChange = false; + + try { + var configXmlPath = path.resolve('config.xml'); + var configString = fs.readFileSync(configXmlPath, { encoding: 'utf8' }); + + var parseString = xml2js.parseString; + parseString(configString, function (err, jsonConfig) { + if(err) { + return self.ionic.fail('Error parsing config.xml: ' + err); + } + + if(options.devServer) { + if( !jsonConfig.widget.content[0].$['original-src'] ) { + jsonConfig.widget.content[0].$['original-src'] = jsonConfig.widget.content[0].$.src; + madeChange = true; + } + if(jsonConfig.widget.content[0].$.src !== options.devServer) { + jsonConfig.widget.content[0].$.src = options.devServer; + madeChange = true; + } + + } else if(options.resetContent) { + if( jsonConfig.widget.content[0].$['original-src'] ) { + jsonConfig.widget.content[0].$.src = jsonConfig.widget.content[0].$['original-src']; + delete jsonConfig.widget.content[0].$['original-src']; + madeChange = true; + } + } + + if(madeChange) { + var xmlBuilder = new xml2js.Builder(); + configString = xmlBuilder.buildObject(jsonConfig); + + fs.writeFileSync(configXmlPath, configString); + } + + }); + + } catch(e) { + return self.ionic.fail('Error updating config.xml file: ' + e); + } +}; + + +IonicCordovaTask.prototype.wwwSymlinks = function(createSymlinks) { + var platformCordovaJs, platformPluginJs, platformPluginsDir; + + var wwwCordovaJs = path.resolve( path.join('www', 'cordova.js') ); + var wwwPluginJs = path.resolve( path.join('www', 'cordova_plugins.js') ); + var wwwPluginsDir = path.resolve( path.join('www', 'plugins') ); + + if(createSymlinks) { + + var platform; + var platforms = 'android ios'.split(' '); + for(var x=0; x -1) continue; ifaces[dev].forEach(function(details){ if (details.family == 'IPv4' && !details.internal) { addresses.push(details.address); @@ -134,4 +151,4 @@ IonicServeTask.prototype.host = function(port) { return 'http://' + (addresses.length === 1 ? addresses[0] : 'localhost') + ':' + port; }; -module.exports = IonicServeTask; +exports.IonicServeTask = IonicServeTask; diff --git a/package.json b/package.json index 06a22f33fd..8ca102be71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.12", + "version": "1.1.13", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From bdeaba3167eab0c0f0f67316538622efe1dc8738 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sun, 31 Aug 2014 01:21:58 -0500 Subject: [PATCH 204/850] update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9195d8ee84..0d00ccc88d 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,11 @@ Command-line flags/options: [--live-reload|-l] ... Live reload app dev files from the device (beta) [--debug|--release] -### Live Reload Within Cordova +### Live Reload Within Cordova (beta) The `run` command will deploy the app to the specified platform devices and emulators. You can also run __live reload__ on the specified platform device by adding the `--live-reload` option. The `run` command's live reload functionality is similar to `ionic serve`, but instead of using a standard browser, the Cordova app itself is watching for any changes to its files and reloading when needed. This reduces the requirement to constantly rebuild the Cordova app for small changes. However, any changes to plugins will still require a full rebuild. -In order for live reload to work, symlinks are automatically created and added to the `www` root, and the `` node in the config.xml file is updated to point to the dev server created by Ionic's CLI. On exit (by typing "exit" or using ctrl+c), the app's original settings will be restored and the symlinks should automatically be deleted. __Currently in beta__ +In order for live reload to work, symlinks are automatically created and added to the `www` root, and the `` node in the config.xml file is updated to point to the dev server created by Ionic's CLI. On exit (by typing "exit" or using ctrl+c), the app's original settings will be restored and the symlinks will be removed. __Currently in beta.__ ## Update Ionic lib From 5dea143c3e7ffe561633768d81b95a3cd9df1b79 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 2 Sep 2014 15:17:22 -0500 Subject: [PATCH 205/850] app live reload --- README.md | 48 ++++++---- lib/ionic.js | 53 ++++++----- lib/ionic/cordova.js | 108 +++-------------------- lib/ionic/lib.js | 3 +- lib/ionic/serve.js | 206 ++++++++++++++++++++++++++++++++++++++++--- lib/ionic/start.js | 44 ++++++++- package.json | 4 +- 7 files changed, 316 insertions(+), 150 deletions(-) diff --git a/README.md b/README.md index 0d00ccc88d..2f2157598d 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ Use the `ionic --help` command for more detailed task information. ## Installing ```bash -$ sudo npm install -g ionic +$ npm install -g ionic ``` +Note: For a global install of `-g ionic`, OSX/Linux users may need to prefix the command with `sudo`. + + ## Starting an Ionic App ```bash @@ -32,7 +35,7 @@ Codepen URL starters: Command-line flags/options: - --app-name, -a ...... Human readable name for the app + --appname, -a ....... Human readable name for the app (Use quotes around the name) --id, -i ............ Package name set in the config ex: com.mycompany.myapp @@ -44,13 +47,17 @@ Command-line flags/options: Use `ionic serve` to start a local development server for app dev and testing. This is useful for both desktop browser testing, and to test within a device browser which is connected to the same network. Additionally, this command starts LiveReload which is used to monitor changes in the file system. As soon as you save a file the browser is refreshed automatically. View [Using Sass](https://github.com/driftyco/ionic-cli/blob/master/README.md#using-sass) if you would also like to have `ionic serve` watch the project's Sass files. ```bash -$ ionic serve [http-port] [livereload-port] [options] +$ ionic serve [options] ``` Command-line flags/options: - [--nobrowser|-b] ...... Disable launching a browser - [--nolivereload|-r] ... Do not start live reload + [--consolelogs|-c] ...... Print app console logs to Ionic CLI + [--serverlogs|-s] ....... Print dev server logs to Ionic CLI + [--port|-p] ............. Dev server HTTP port (8100 default) + [--livereload-port|-i] .. Live Reload port (35729 default) + [--nobrowser|-b] ........ Disable launching a browser + [--nolivereload|-r] ..... Do not start live reload ## Adding a platform target @@ -65,28 +72,37 @@ $ ionic platform ios android $ ionic build ios ``` -## Emulating your app - -```bash -$ ionic emulate ios -``` - ## Running your app +Deploys the Ionic app on specified platform devices. + ```bash -$ ionic run ios +$ ionic run ios [options] ``` Command-line flags/options: - [--live-reload|-l] ... Live reload app dev files from the device (beta) + [--livereload|-l] ....... Live Reload app dev files from the device (beta) + [--consolelogs|-c] ...... Print app console logs to Ionic CLI (live reload req.) + [--serverlogs|-s] ....... Print dev server logs to Ionic CLI (live reload req.) + [--port|-p] ............. Dev server HTTP port (8100 default, live reload req.) + [--livereload-port|-i] .. Live Reload port (35729 default, live reload req.) [--debug|--release] -### Live Reload Within Cordova (beta) +### Live Reload App During Development (beta) -The `run` command will deploy the app to the specified platform devices and emulators. You can also run __live reload__ on the specified platform device by adding the `--live-reload` option. The `run` command's live reload functionality is similar to `ionic serve`, but instead of using a standard browser, the Cordova app itself is watching for any changes to its files and reloading when needed. This reduces the requirement to constantly rebuild the Cordova app for small changes. However, any changes to plugins will still require a full rebuild. +The `run` or `emulate` command will deploy the app to the specified platform devices/emulators. You can also run __live reload__ on the specified platform device by adding the `--livereload` option. The live reload functionality is similar to `ionic serve`, but instead of developing and debugging an app using a standard browser, the compiled hybrid app itself is watching for any changes to its files and reloading the app when needed. This reduces the requirement to constantly rebuild the app for small changes. However, any changes to plugins will still require a full rebuild. For live reload to work, the dev machine and device must be on the same local network. -In order for live reload to work, symlinks are automatically created and added to the `www` root, and the `` node in the config.xml file is updated to point to the dev server created by Ionic's CLI. On exit (by typing "exit" or using ctrl+c), the app's original settings will be restored and the symlinks will be removed. __Currently in beta.__ +With live reload enabled, an app's console logs can also be printed to the terminal/command prompt by including the `--consolelogs` or `-c` option. Additionally, the development server's request logs can be printed out using `--serverlogs` or `-s` options. + + +## Emulating your app + +Deploys the Ionic app on specified platform emulator. This is simply an alias for `run --emulator`. Live reload options are the same as the `run` options listed above. + +```bash +$ ionic emulate ios [options] +``` ## Update Ionic lib diff --git a/lib/ionic.js b/lib/ionic.js index 4142cfd653..d38f10792c 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -77,13 +77,15 @@ var TASKS = [ name: 'serve', summary: 'Start a local development server for app dev and testing', args: { - '[options]': '', - '[port]': '', - '[livereload-port]': '' + '[options]': '' }, options: { - '--nobrowser|-b': 'Disable auto browser launch', - '--nolivereload|-r': 'Do not start live reload' + '--consolelogs|-c': 'Print app console logs to Ionic CLI', + '--serverlogs|-s': 'Print dev server logs to Ionic CLI', + '--port|-p': 'Dev server HTTP port (8100 default)', + '--livereload-port|-r': 'Live Reload port (35729 default)', + '--nobrowser|-b': 'Disable launching a browser', + '--nolivereload': 'Do not start live reload' }, task: IonicServeTask }, @@ -98,25 +100,38 @@ var TASKS = [ task: IonicCordovaTask }, { - title: 'emulate', - name: 'emulate', - summary: 'Emulate an Ionic project on a simulator or emulator', + title: 'run', + name: 'run', + summary: 'Run an Ionic project on a connected device', args: { '[options]': '', '': '' }, + options: { + '--livereload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, + '--port|-p': 'Dev server HTTP port (8100 default, livereload required)', + '--livereload-port|-r': 'Live Reload port (35729 default, livereload req.)', + '--consolelogs|-c': 'Print app console logs to Ionic CLI (livereload req.)', + '--serverlogs|-s': 'Print dev server logs to Ionic CLI (livereload req.)', + '--debug|--release': '', + '--device|--emulator|--target=FOO': '' + }, task: IonicCordovaTask }, { - title: 'run', - name: 'run', - summary: 'Run an ionic project on a connected device', + title: 'emulate', + name: 'emulate', + summary: 'Emulate an Ionic project on a simulator or emulator', args: { '[options]': '', '': '' }, options: { - '--live-reload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, + '--livereload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, + '--port|-p': 'Dev server HTTP port (8100 default, livereload required)', + '--livereload-port|-r': 'Live Reload port (35729 default, livereload req.)', + '--consolelogs|-c': 'Print app console logs to Ionic CLI (livereload req.)', + '--serverlogs|-s': 'Print dev server logs to Ionic CLI (livereload req.)', '--debug|--release': '', '--device|--emulator|--target=FOO': '' }, @@ -125,7 +140,7 @@ var TASKS = [ { title: 'build', name: 'build', - summary: 'Locally build an ionic project for a given platform', + summary: 'Locally build an Ionic project for a given platform', args: { '[options]': '', '': '' @@ -196,13 +211,13 @@ var TASKS = [ { title: 'lib', name: 'lib', - summary: 'Ionic library version info or updates the Ionic library', + summary: 'Gets Ionic library version or updates the Ionic library', args: { '[options]': '', '[update]': 'Updates the Ionic Framework in www/lib/ionic' }, options: { - '--version|-v': 'Ionic version, otherwise it will default to the latest' + '--version|-v': 'Spcific Ionic version, otherwise it defaults to the latest' }, task: IonicLibTask }, @@ -349,7 +364,7 @@ Ionic = { _printAvailableTasks: function() { this._printIonic(); - process.stderr.write('\nUsage: ionic task args\n\n===============\n\n'); + process.stderr.write('\nUsage: ionic task args\n\n=======================\n\n'); if(process.argv.length > 2) { process.stderr.write( (process.argv[2] + ' is not a valid task\n\n').bold.red ); @@ -403,10 +418,6 @@ Ionic = { }, - _loadTaskRunner: function(which) { - - }, - run: function() { var self = this; @@ -462,7 +473,7 @@ Ionic = { }, version: function() { - process.stderr.write('v' + settings.version + '\n'); + process.stderr.write(settings.version + '\n'); }, checkLatestVersion: function() { diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 27569334bd..5db1181e6f 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -17,7 +17,18 @@ IonicCordovaTask.prototype.run = function(ionic) { var cmdName = process.argv[2].toLowerCase(); var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); - self.isLiveReload = (cmdName == 'run' && (argv.livereload || argv['live-reload'] || argv.l)); + // clean out any cmds that may confuse cordova + var port = argv.port || argv.p || ''; + var liveReloadPort = argv.livereloadport || argv['livereload-port'] || argv.i || ''; + if(port || liveReloadPort) { + for(var x=0; x -1 || ua.indexOf('ipad') > -1 || ua.indexOf('ipod') > -1) { + platformPath = path.join('platforms', 'ios', 'www'); + + } else if(ua.indexOf('android') > -1) { + platformPath = path.join('platforms', 'android', 'assets', 'www'); + } + } + + return platformPath; +} + + +function insertConsoleLogScript(html) { + try{ + var headTag = html.match(//gi)[0]; + + return html.replace(headTag, headTag + '\n\ + '); + }catch(e){} + + return html; +} + IonicServeTask.prototype._changed = function(filePath) { // Cleanup the path a bit var pwd = process.cwd(); filePath = filePath.replace(pwd + '/', ''); - console.log( (' changed: ' + filePath).green ); + if( filePath.indexOf('.css') > 0 ) { + console.log( (' CSS changed: ' + filePath).green ); + } else if( filePath.indexOf('.js') > 0 ) { + console.log( (' JS changed: ' + filePath).green ); + } else if( filePath.indexOf('.html') > 0 ) { + console.log( ('HTML changed: ' + filePath).green ); + } else { + console.log( ('File changed: ' + filePath).green ); + } var req = request.post('http://localhost:' + this.liveReloadPort + '/changed', { path: '/changed', diff --git a/lib/ionic/start.js b/lib/ionic/start.js index b933496bfe..33d5dfc7f5 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -35,7 +35,7 @@ IonicStartTask.prototype.run = function(ionic) { this.appDirectory = argv._[1]; // Grab the name of the app from -a or --app. Defaults to appDirectory if none provided - this.appName = argv['app-name'] || argv.a; + this.appName = argv.appname || argv['app-name'] || argv.a; if(!this.appName) { var appNameSplit = this.appDirectory.split('/'); appNameSplit = appNameSplit[ appNameSplit.length -1 ].split('\\'); @@ -267,7 +267,7 @@ IonicStartTask.prototype.convertTemplates = function(html) { var tmpPath = path.join(self.targetPath, 'www', path.dirname(tmpl.path)); if(!fs.existsSync(tmpPath)) { - fs.mkdirSync(tmpPath) + fs.mkdirSync(tmpPath); } tmpPath = path.join(self.targetPath, 'www', tmpl.path); @@ -404,11 +404,46 @@ IonicStartTask.prototype.setupSass = function() { IonicStartTask.prototype.updateLibFiles = function() { var libPath = argv.lib || argv.l || 'lib/ionic'; - if(libPath == 'lib' && this.seedType == 'ionic-starter') { - // don't bother if it still will be the default + // create a symlink if the path exists locally + var libSymlinkPath = path.resolve(libPath); + if( fs.existsSync(libSymlinkPath) ) { + // rename the existing lib/ionic directory before creating symlink + var wwwIonicCssPath = path.resolve('www/lib/ionic/css'); + if( fs.existsSync(wwwIonicCssPath) ) { + mv( wwwIonicCssPath, path.resolve('www/lib/ionic/css_local') ); + } + + var wwwIonicJsPath = path.resolve('www/lib/ionic/js'); + if( fs.existsSync(wwwIonicJsPath) ) { + mv( wwwIonicJsPath, path.resolve('www/lib/ionic/js_local') ); + } + + var wwwIonicFontsPath = path.resolve('www/lib/ionic/fonts'); + if( fs.existsSync(wwwIonicFontsPath) ) { + mv( wwwIonicFontsPath, path.resolve('www/lib/ionic/fonts_local') ); + } + + var libCssSymlinkPath = path.join(libSymlinkPath, 'css'); + console.log('Create www/lib/ionic/css symlink to ' + libCssSymlinkPath); + fs.symlinkSync(libCssSymlinkPath, wwwIonicCssPath); + + var libJsSymlinkPath = path.join(libSymlinkPath, 'js'); + console.log('Create www/lib/ionic/js symlink to ' + libJsSymlinkPath); + fs.symlinkSync(libJsSymlinkPath, wwwIonicJsPath); + + var libFontsSymlinkPath = path.join(libSymlinkPath, 'fonts'); + console.log('Create www/lib/ionic/fonts symlink to ' + libFontsSymlinkPath); + fs.symlinkSync(libFontsSymlinkPath, wwwIonicFontsPath); + + libPath = 'lib/ionic'; + } + + if(libPath == 'lib/ionic' && this.seedType == 'ionic-starter') { + // don't bother if its still is the default which comes with the starters return; } + // path did not exist locally, so manually switch out the path in the html var libFiles = 'ionic.css ionic.min.css ionic.js ionic.min.js ionic.bundle.js ionic.bundle.min.js ionic-angular.js ionic-angular.min.js'.split(' '); function isLibFile(tag) { @@ -478,6 +513,7 @@ IonicStartTask.prototype.updateLibFiles = function() { } try { + console.log('Replacing Ionic lib references with ' + libPath); var indexPath = path.join(this.targetPath, 'www', 'index.html'); var html = fs.readFileSync(indexPath, 'utf8'); diff --git a/package.json b/package.json index 8ca102be71..dcb87ef311 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.1.13", + "version": "1.2.0", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -42,6 +42,8 @@ "archiver": "0.5.1", "colors": "^0.6.2", "connect": "^2.14.5", + "serve-static": "^1.5.3", + "finalhandler": "^0.1.0", "connect-livereload": "^0.4.0", "event-stream": "3.0.x", "form-data": "~0.1.0", From bbfb344b305dc336595eea70e809685e2b7ee99d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 2 Sep 2014 15:27:06 -0500 Subject: [PATCH 206/850] update --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2f2157598d..4b74fba3fe 100644 --- a/README.md +++ b/README.md @@ -72,15 +72,13 @@ $ ionic platform ios android $ ionic build ios ``` -## Running your app +## Live Reload App During Development (beta) -Deploys the Ionic app on specified platform devices. +The `run` or `emulate` command will deploy the app to the specified platform devices/emulators. You can also run __live reload__ on the specified platform device by adding the `--livereload` option. The live reload functionality is similar to `ionic serve`, but instead of developing and debugging an app using a standard browser, the compiled hybrid app itself is watching for any changes to its files and reloading the app when needed. This reduces the requirement to constantly rebuild the app for small changes. However, any changes to plugins will still require a full rebuild. For live reload to work, the dev machine and device must be on the same local network, and the device must support [web sockets](http://caniuse.com/websockets). -```bash -$ ionic run ios [options] -``` +With live reload enabled, an app's console logs can also be printed to the terminal/command prompt by including the `--consolelogs` or `-c` option. Additionally, the development server's request logs can be printed out using `--serverlogs` or `-s` options. -Command-line flags/options: +Command-line flags/options for `run` and `emulate`: [--livereload|-l] ....... Live Reload app dev files from the device (beta) [--consolelogs|-c] ...... Print app console logs to Ionic CLI (live reload req.) @@ -89,19 +87,22 @@ Command-line flags/options: [--livereload-port|-i] .. Live Reload port (35729 default, live reload req.) [--debug|--release] -### Live Reload App During Development (beta) -The `run` or `emulate` command will deploy the app to the specified platform devices/emulators. You can also run __live reload__ on the specified platform device by adding the `--livereload` option. The live reload functionality is similar to `ionic serve`, but instead of developing and debugging an app using a standard browser, the compiled hybrid app itself is watching for any changes to its files and reloading the app when needed. This reduces the requirement to constantly rebuild the app for small changes. However, any changes to plugins will still require a full rebuild. For live reload to work, the dev machine and device must be on the same local network. +## Emulating your app -With live reload enabled, an app's console logs can also be printed to the terminal/command prompt by including the `--consolelogs` or `-c` option. Additionally, the development server's request logs can be printed out using `--serverlogs` or `-s` options. +Deploys the Ionic app on specified platform emulator. This is simply an alias for `run --emulator`. +```bash +$ ionic emulate ios [options] +``` -## Emulating your app -Deploys the Ionic app on specified platform emulator. This is simply an alias for `run --emulator`. Live reload options are the same as the `run` options listed above. +## Running your app + +Deploys the Ionic app on specified platform devices. If a device is not found it'll then deploy to an emulator/simulator. ```bash -$ ionic emulate ios [options] +$ ionic run ios [options] ``` From 5d023f21884e27312b30ce6778d63192d80166b8 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 02:35:31 -0500 Subject: [PATCH 207/850] auto remove read me from root --- lib/ionic/start.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 33d5dfc7f5..a433d3dbbd 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -559,6 +559,13 @@ IonicStartTask.prototype.finalize = function() { ionicBower.setAppName(this.appName); } catch(e) {} + try { + // remove the README file in the root because it + // doesn't make sense because its the README for the repo + // and not helper text while developing an app + fs.unlinkSync(this.targetPath + '/README.md'); + } catch(e) {} + try { // remove the README file in the www root because it // doesn't make sense because its the README for the repo From 9f77b5ead5836c1d92af33fb1f34280c3e320cd4 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 02:38:30 -0500 Subject: [PATCH 208/850] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b74fba3fe..44065c5549 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Use the `ionic --help` command for more detailed task information. $ npm install -g ionic ``` -Note: For a global install of `-g ionic`, OSX/Linux users may need to prefix the command with `sudo`. +*Note: For a global install of `-g ionic`, OSX/Linux users may need to prefix the command with `sudo`.* ## Starting an Ionic App @@ -133,7 +133,7 @@ The third argument can be either `debug` or `release`, and the last argument can Ionic uses Cordova underneath, so you can also substitute Cordova commands to prepare/build/emulate/run, or to add additional plugins. -Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better. +*Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better.* ## Using Sass From 3b713d3caa5a284abc3fc5059cf4c4c49566a51d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 02:52:56 -0500 Subject: [PATCH 209/850] add platform class hook --- lib/hooks/after_prepare/010_add_platform_class.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/hooks/after_prepare/010_add_platform_class.js b/lib/hooks/after_prepare/010_add_platform_class.js index edd86c9065..ed0135f834 100755 --- a/lib/hooks/after_prepare/010_add_platform_class.js +++ b/lib/hooks/after_prepare/010_add_platform_class.js @@ -3,8 +3,9 @@ // Add Platform Class // v1.0 // Automatically adds the platform class to the body tag -// after the `prepare` command. This speeds up device rendering -// the correct layout/style for the specific platform. +// after the `prepare` command. By placing the platform CSS classes +// directly in the HTML built for the platform, it speeds up +// rendering the correct layout/style for the specific platform. var fs = require('fs'); var path = require('path'); From 6b75159a851ad0da58237cbafaed4a51e855a38a Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 03:06:15 -0500 Subject: [PATCH 210/850] update --- lib/hooks/after_prepare/010_add_platform_class.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/hooks/after_prepare/010_add_platform_class.js b/lib/hooks/after_prepare/010_add_platform_class.js index ed0135f834..bda3e41585 100755 --- a/lib/hooks/after_prepare/010_add_platform_class.js +++ b/lib/hooks/after_prepare/010_add_platform_class.js @@ -5,7 +5,8 @@ // Automatically adds the platform class to the body tag // after the `prepare` command. By placing the platform CSS classes // directly in the HTML built for the platform, it speeds up -// rendering the correct layout/style for the specific platform. +// rendering the correct layout/style for the specific platform +// instead of waiting for the JS to figure out the correct classes. var fs = require('fs'); var path = require('path'); @@ -37,7 +38,7 @@ function addPlatformBodyTag(indexPath, platform) { } else { // add class attribute to the body tag - newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">') + newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">'); } html = html.replace(bodyTag, newBodyTag); From 9d01ff2b3d5e8047f98cc4a464a9f9c7da166651 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 03:21:53 -0500 Subject: [PATCH 211/850] both app-name and appname work --- lib/ionic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic.js b/lib/ionic.js index d38f10792c..2d892f38b2 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -65,7 +65,7 @@ var TASKS = [ 'Defaults to Ionic "tabs" starter template' }, options: { - '--app-name|-a': 'Human readable name for the app (Use quotes around the name)', + '--appname|-a': 'Human readable name for the app (Use quotes around the name)', '--id|-i': 'Package name for config, ex: com.mycompany.myapp', '--no-cordova|-w': 'Create a basic structure without Cordova requirements', '--sass|-s': 'Setup the project to use Sass CSS precompiling' From 76915ae1037535d02c9583faa3db5ae5b63891e2 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 03:47:07 -0500 Subject: [PATCH 212/850] add platforms from start cmd --- lib/ionic/start.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index a433d3dbbd..09900ad962 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -326,10 +326,24 @@ IonicStartTask.prototype.initCordova = function() { if(this.ionic.hasFailed) return; + var cmds = [ + 'cordova plugin add org.apache.cordova.device', + 'cordova plugin add org.apache.cordova.console', + 'cordova plugin add com.ionic.keyboard' + ]; + + // platform add android with --android flag + if(argv.android) { + cmds.push('cordova platform add android'); + } + + // platform add ios with --android flag + if(argv.ios) { + cmds.push('cordova platform add ios'); + } + console.log('Initializing cordova project.'.info.bold); - exec('cordova plugin add org.apache.cordova.device && ' + - 'cordova plugin add org.apache.cordova.console && ' + - 'cordova plugin add com.ionic.keyboard', + exec(cmds.join(' && '), function(err, stdout, stderr) { if(err) { self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. ' + From eecf1ce49bea2e29f951e97937fed32b76a2b1e9 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 21:31:02 -0500 Subject: [PATCH 213/850] do not require all task modules on each run --- lib/ionic.js | 97 ++++++++++++++------------------------------ lib/ionic/cordova.js | 16 ++++---- lib/ionic/lib.js | 26 ++++++------ lib/ionic/login.js | 14 +++---- lib/ionic/package.js | 30 +++++++------- lib/ionic/project.js | 3 +- lib/ionic/serve.js | 33 +++++++++------ lib/ionic/setup.js | 16 ++++---- lib/ionic/start.js | 40 +++++++++--------- lib/ionic/task.js | 6 +-- lib/ionic/upload.js | 10 ++--- 11 files changed, 131 insertions(+), 160 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2d892f38b2..2dbf7e5530 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -14,25 +14,11 @@ Licensed under the MIT license. See LICENSE For more. Copyright 2014 Drifty (http://drifty.com/) */ -var IonicStartTask = require('./ionic/start').IonicStartTask, - IonicCordovaTask = require('./ionic/cordova').IonicCordovaTask, - IonicLoginTask = require('./ionic/login').IonicLoginTask, - IonicUploadTask = require('./ionic/upload').IonicUploadTask, - IonicPackageTask = require('./ionic/package').IonicPackageTask, - IonicLibTask = require('./ionic/lib').IonicLibTask, - IonicSetupTask = require('./ionic/setup').IonicSetupTask, - IonicServeTask = require('./ionic/serve').IonicServeTask, - IonicProject = require('./ionic/project'), - IonicStore = require('./ionic/store').IonicStore, - path = require('path'), - request = require('request'), - os = require('os'), - unzip = require('unzip'), +var argv = require('optimist').argv, colors = require('colors'), - spawn = require('child_process').spawn, Q = require('q'), - settings = require('../package.json'); - + settings = require('../package.json'), + shelljs = require('shelljs/global'),; colors.setTheme({ silly: 'rainbow', @@ -49,9 +35,6 @@ colors.setTheme({ }); -var fs = require('fs'), - argv = require('optimist').argv; - var TASKS = [ { title: 'start', @@ -70,7 +53,7 @@ var TASKS = [ '--no-cordova|-w': 'Create a basic structure without Cordova requirements', '--sass|-s': 'Setup the project to use Sass CSS precompiling' }, - task: IonicStartTask + module: './ionic/start' }, { title: 'serve', @@ -87,7 +70,7 @@ var TASKS = [ '--nobrowser|-b': 'Disable launching a browser', '--nolivereload': 'Do not start live reload' }, - task: IonicServeTask + module: './ionic/serve' }, { title: 'platform', @@ -97,7 +80,7 @@ var TASKS = [ '[options]': '', '': '' }, - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'run', @@ -116,7 +99,7 @@ var TASKS = [ '--debug|--release': '', '--device|--emulator|--target=FOO': '' }, - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'emulate', @@ -135,7 +118,7 @@ var TASKS = [ '--debug|--release': '', '--device|--emulator|--target=FOO': '' }, - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'build', @@ -145,7 +128,7 @@ var TASKS = [ '[options]': '', '': '' }, - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'plugin add', @@ -159,17 +142,17 @@ var TASKS = [ '--searchpath ': 'When looking up plugins by ID, look in this directory and\n' + 'subdirectories for the plugin before using the registry.' }, - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'prepare', name: 'prepare', - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'compile', name: 'compile', - task: IonicCordovaTask + module: './ionic/cordova' }, { title: 'package', @@ -195,7 +178,7 @@ var TASKS = [ '--email|-e': 'Ionic account email', '--password|-p': 'Ionic account password' }, - task: IonicPackageTask + module: './ionic/package' }, { title: 'upload', @@ -206,7 +189,7 @@ var TASKS = [ '--password|-p': 'Ionic account password' }, alt: ['up'], - task: IonicUploadTask + module: './ionic/upload' }, { title: 'lib', @@ -219,7 +202,7 @@ var TASKS = [ options: { '--version|-v': 'Spcific Ionic version, otherwise it defaults to the latest' }, - task: IonicLibTask + module: './ionic/lib' }, { title: 'setup', @@ -228,12 +211,12 @@ var TASKS = [ args: { '[sass]': 'Setup the project to use Sass CSS precompiling' }, - task: IonicSetupTask + module: './ionic/setup' }, { title: 'login', name: 'login', - task: IonicLoginTask + module: './ionic/login' } ]; @@ -436,6 +419,7 @@ Ionic = { } if(argv['stats-opt-out']) { + var IonicStore = require('./ionic/store').IonicStore; var ionicConfig = new IonicStore('ionic.config'); ionicConfig.set('statsOptOut', true); ionicConfig.save(); @@ -443,13 +427,14 @@ Ionic = { return; } - var task = this._tryBuildingTask(); - if(!task) { + var taskSetting = this._tryBuildingTask(); + if(!taskSetting) { return this._printAvailableTasks(); } + var taskModule = require(taskSetting.module).IonicTask; - var taskObj = new task.task(); - taskObj.run(this); + var taskInstance = new taskModule(); + taskInstance.run(this); }, fail: function(msg, taskHelp) { @@ -488,6 +473,7 @@ Ionic = { } // stay silent if it errors + var IonicStore = require('./ionic/store').IonicStore; var ionicConfig = new IonicStore('ionic.config'); var versionCheck = ionicConfig.get('versionCheck'); if(versionCheck && ((versionCheck + 86400000) > Date.now() )) { @@ -497,6 +483,7 @@ Ionic = { } var proxy = process.env.PROXY || null; + var request = require('request'); request({ url: 'http://registry.npmjs.org/ionic/latest', proxy: proxy }, function(err, res, body) { try { self.npmVersion = JSON.parse(body).version; @@ -529,39 +516,14 @@ Ionic = { }); }, - spawnPromise: function(cmd, args, onStdOut, onStdErr) { - var q = Q.defer(); - var child; - console.log('\nRUNNING:'.info.bold, cmd, args.join(' ')); - try { - child = spawn(cmd, args); - } catch(e) { - } - child.stdout.setEncoding('utf8'); - child.stdout.on('data', function(data) { - process.stdout.write(data); - onStdOut && onStdOut(data); - }); - child.stderr.on('data', function(data) { - process.stderr.write(data); - onStdErr && onStdErr(data); - }); - child.on('error', function(err) { - q.reject(err); - }); - child.on('exit', function(code) { - if(code === 0) { - q.resolve(); - } else { - q.reject(code); - } - }); - return q.promise; - }, /** * Download a zip file, unzip it to a specific folder. */ fetchArchive: function(targetPath, archiveUrl) { + var os = require('os'); + var fs = require('fs'); + var path = require('path'); + var unzip = require('unzip'); var q = Q.defer(); // The folder name the project will be downloaded and extracted to @@ -585,6 +547,7 @@ Ionic = { }; var proxy = process.env.PROXY || null; + var request = require('request'); request({ url: archiveUrl, encoding: null, proxy: proxy }, function(err, res, body) { if(!res || res.statusCode !== 200) { q.reject(res); diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 5db1181e6f..40f898c118 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -1,4 +1,4 @@ -var IonicTask = require('./task').IonicTask, +var Task = require('./task').Task, IonicStats = require('./stats').IonicStats, fs = require('fs'), argv = require('optimist').argv, @@ -7,11 +7,11 @@ var IonicTask = require('./task').IonicTask, exec = require('child_process').exec, colors = require('colors'); -var IonicCordovaTask = function() {}; +var IonicTask = function() {}; -IonicCordovaTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicCordovaTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { var self = this; self.ionic = ionic; var cmdName = process.argv[2].toLowerCase(); @@ -82,7 +82,7 @@ IonicCordovaTask.prototype.run = function(ionic) { }; -IonicCordovaTask.prototype.setupLiveReload = function() { +IonicTask.prototype.setupLiveReload = function() { console.log('Setup Live Reload'.green.bold); var serve = new require('./serve'); @@ -99,7 +99,7 @@ IonicCordovaTask.prototype.setupLiveReload = function() { }; -IonicCordovaTask.prototype.setConfigXml = function(options) { +IonicTask.prototype.setConfigXml = function(options) { var self = this; var madeChange = false; @@ -146,7 +146,7 @@ IonicCordovaTask.prototype.setConfigXml = function(options) { }; -IonicCordovaTask.prototype.addHooks = function() { +IonicTask.prototype.addHooks = function() { // Add hooks which this Ionic project doesn't already have // note: hook scripts must be executable! @@ -212,4 +212,4 @@ IonicCordovaTask.prototype.addHooks = function() { }; -exports.IonicCordovaTask = IonicCordovaTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 57372c0212..eefc6e6872 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -8,14 +8,14 @@ var fs = require('fs'), colors = require('colors'), exec = require('child_process').exec, Q = require('q'), - IonicTask = require('./task').IonicTask, + Task = require('./task').Task, IonicStats = require('./stats').IonicStats; -var IonicLibTask = function() {}; +var IonicTask = function() {}; -IonicLibTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicLibTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { var self = this; self.local = {}; self.versionData = {}; @@ -37,7 +37,7 @@ IonicLibTask.prototype.run = function(ionic) { }; -IonicLibTask.prototype.loadVersionData = function() { +IonicTask.prototype.loadVersionData = function() { this.versionFilePath = path.resolve('www/lib/ionic/version.json'); if( !fs.existsSync(this.versionFilePath) ) { this.versionFilePath = path.resolve('www/lib/ionic/bower.json'); @@ -52,7 +52,7 @@ IonicLibTask.prototype.loadVersionData = function() { }; -IonicLibTask.prototype.printLibVersions = function() { +IonicTask.prototype.printLibVersions = function() { var self = this; console.log('Local Ionic version: '.bold.green + this.local.version + ' (' + this.versionFilePath + ')'); @@ -69,7 +69,7 @@ IonicLibTask.prototype.printLibVersions = function() { }; -IonicLibTask.prototype.getVersionData = function(version) { +IonicTask.prototype.getVersionData = function(version) { var q = Q.defer(); var self = this; @@ -110,7 +110,7 @@ IonicLibTask.prototype.getVersionData = function(version) { }; -IonicLibTask.prototype.updateLibVersion = function() { +IonicTask.prototype.updateLibVersion = function() { var self = this; if(self.usesBower) { @@ -158,7 +158,7 @@ IonicLibTask.prototype.updateLibVersion = function() { }; -IonicLibTask.prototype.getLatest = function() { +IonicTask.prototype.getLatest = function() { var self = this; var dirPath = path.resolve('www/lib/'); @@ -188,7 +188,7 @@ IonicLibTask.prototype.getLatest = function() { }; -IonicLibTask.prototype.downloadZip = function(version) { +IonicTask.prototype.downloadZip = function(version) { var self = this; var archivePath = 'https://github.com/driftyco/ionic-bower/archive/v' + version + '.zip'; @@ -253,7 +253,7 @@ IonicLibTask.prototype.downloadZip = function(version) { }; -IonicLibTask.prototype.updateFiles = function(version) { +IonicTask.prototype.updateFiles = function(version) { var self = this; var ionicLibDir = path.resolve('www/lib/ionic'); var readStream = fs.createReadStream(self.tmpZipPath); @@ -315,7 +315,7 @@ IonicLibTask.prototype.updateFiles = function(version) { } }; -IonicLibTask.prototype.writeVersionData = function() { +IonicTask.prototype.writeVersionData = function() { try { var versionData = { "version": this.versionData.version_number || this.versionData.version, @@ -331,4 +331,4 @@ IonicLibTask.prototype.writeVersionData = function() { } }; -exports.IonicLibTask = IonicLibTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/login.js b/lib/ionic/login.js index ce1109faae..e94a7edff8 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -4,13 +4,13 @@ var fs = require('fs'), prompt = require('prompt'), IonicProject = require('./project'), IonicStore = require('./store').IonicStore, - IonicTask = require('./task').IonicTask; + Task = require('./task').Task; -var IonicLoginTask = function() {}; +var IonicTask = function() {}; -IonicLoginTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicLoginTask.prototype.get = function(ionic, callback) { +IonicTask.prototype.get = function(ionic, callback) { this.cookieData = new IonicStore('cookies'); if(ionic.jar) { @@ -48,7 +48,7 @@ IonicLoginTask.prototype.get = function(ionic, callback) { this.run(ionic, callback); }; -IonicLoginTask.prototype.run = function(ionic, callback) { +IonicTask.prototype.run = function(ionic, callback) { var self = this; if(!this.email && !this.password) { @@ -92,7 +92,7 @@ IonicLoginTask.prototype.run = function(ionic, callback) { }; -IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { +IonicTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { var self = this; var jar = request.jar(); @@ -136,4 +136,4 @@ IonicLoginTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { }); }; -exports.IonicLoginTask = IonicLoginTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 32a3171f2d..e296b0d1dc 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -8,16 +8,16 @@ var fs = require('fs'), FormData = require('form-data'), IonicProject = require('./project'), IonicStore = require('./store').IonicStore, - IonicTask = require('./task').IonicTask, + Task = require('./task').Task, IonicUploadTask = require('./upload').IonicUploadTask, IonicStats = require('./stats').IonicStats, IonicLoginTask = require('./login').IonicLoginTask; -var IonicPackageTask = function() {}; +var IonicTask = function() {}; -IonicPackageTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicPackageTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { var self = this; self.ionic = ionic; @@ -51,7 +51,7 @@ IonicPackageTask.prototype.run = function(ionic) { }; -IonicPackageTask.prototype.loadProject = function() { +IonicTask.prototype.loadProject = function() { var appName = this.project.get('name') || "app"; console.log( ('Loading ' + appName + '...').bold.green ); @@ -83,7 +83,7 @@ IonicPackageTask.prototype.loadProject = function() { }; -IonicPackageTask.prototype.loadPlugins = function() { +IonicTask.prototype.loadPlugins = function() { this.plugins = []; try { @@ -105,7 +105,7 @@ IonicPackageTask.prototype.loadPlugins = function() { }; -IonicPackageTask.prototype.getCmdLineOptions = function() { +IonicTask.prototype.getCmdLineOptions = function() { var self = this; function getCmdArgValue(propertyName, shortName) { @@ -138,7 +138,7 @@ IonicPackageTask.prototype.getCmdLineOptions = function() { }; -IonicPackageTask.prototype.loadAppSigning = function(callback) { +IonicTask.prototype.loadAppSigning = function(callback) { var self = this; if(self.useCmdArgs) { @@ -195,7 +195,7 @@ IonicPackageTask.prototype.loadAppSigning = function(callback) { }; -IonicPackageTask.prototype.initPlatforms = function() { +IonicTask.prototype.initPlatforms = function() { var self = this; if(self.useCmdArgs) { @@ -231,7 +231,7 @@ IonicPackageTask.prototype.initPlatforms = function() { }; -IonicPackageTask.prototype.packagePlatforms = function() { +IonicTask.prototype.packagePlatforms = function() { var self = this; var upload = new IonicUploadTask(); @@ -244,7 +244,7 @@ IonicPackageTask.prototype.packagePlatforms = function() { }; -IonicPackageTask.prototype.buildPromptProperties = function() { +IonicTask.prototype.buildPromptProperties = function() { // Just prompt for some build properties var promptProperties = {}; @@ -325,7 +325,7 @@ IonicPackageTask.prototype.buildPromptProperties = function() { }; -IonicPackageTask.prototype.buildPostRequest = function(platform) { +IonicTask.prototype.buildPostRequest = function(platform) { var form = new FormData(); form.append('build_status_email', this.buildStatusEmail.toString()); @@ -370,7 +370,7 @@ IonicPackageTask.prototype.buildPostRequest = function(platform) { }; -IonicPackageTask.prototype.submitPostRequest = function(form, platform) { +IonicTask.prototype.submitPostRequest = function(form, platform) { var self = this; var params = parseUrl(self.ionic.IONIC_DASH + self.ionic.IONIC_API + 'app/' + self.project.get('app_id') + '/package'); @@ -444,7 +444,7 @@ IonicPackageTask.prototype.submitPostRequest = function(form, platform) { }; -IonicPackageTask.prototype.clearSigning = function() { +IonicTask.prototype.clearSigning = function() { var self = this; console.log('Clearing app signing and credential information...'.yellow.bold); @@ -612,4 +612,4 @@ function resolvePath (p) { return path.resolve(p); } -exports.IonicPackageTask = IonicPackageTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/project.js b/lib/ionic/project.js index 366a2c4e89..d5c294fa01 100644 --- a/lib/ionic/project.js +++ b/lib/ionic/project.js @@ -1,6 +1,5 @@ var fs = require('fs'), - path = require('path'), - ionic = require('../ionic'); + path = require('path'); module.exports = { PROJECT_FILE: 'ionic.project', diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 1194024d23..bd5bdee492 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -13,17 +13,17 @@ var fs = require('fs'), Q = require('q'), spawn = require('child_process').spawn, IonicProject = require('./project'), - IonicTask = require('./task').IonicTask; + Task = require('./task').Task; IonicStats = require('./stats').IonicStats; var DEFAULT_HTTP_PORT = 8100; var DEFAULT_LIVE_RELOAD_PORT = 35729; -var IonicServeTask = function() {}; +var IonicTask = function() {}; -IonicServeTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicServeTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { this.port = argv._[1]; this.liveReloadPort = argv._[2]; @@ -38,7 +38,7 @@ IonicServeTask.prototype.run = function(ionic) { }; -IonicServeTask.prototype.loadSettings = function() { +IonicTask.prototype.loadSettings = function() { var project = IonicProject.load(); this.port = this.port || argv.port || argv.p || DEFAULT_HTTP_PORT; @@ -51,7 +51,7 @@ IonicServeTask.prototype.loadSettings = function() { this.printConsoleLogs = argv.consolelogs || argv['console-logs'] || argv.c; }; -IonicServeTask.prototype.start = function(ionic) { +IonicTask.prototype.start = function(ionic) { var self = this; var app = connect(); @@ -180,14 +180,14 @@ IonicServeTask.prototype.start = function(ionic) { }; -IonicServeTask.prototype.serverLog = function(msg) { +IonicTask.prototype.serverLog = function(msg) { if(this.printServerLogs) { console.log( ('serve: ' + msg).yellow ); } }; -IonicServeTask.prototype.consoleLog = function(req) { +IonicTask.prototype.consoleLog = function(req) { var body = ''; req.on('data', function (data) { @@ -209,7 +209,16 @@ IonicServeTask.prototype.consoleLog = function(req) { while(msg.length < 14) { msg += ' '; } - msg += log.args.join(', '); + + if(log.method == 'dir') { + var dirObjs = []; + log.args.forEach(function(objStr){ + dirObjs.push( JSON.stringify( JSON.parse(objStr) ) ); + }); + msg += dirObjs.join('\n'); + } else { + msg += log.args.join(', '); + } if(log.method == 'error' || log.method == 'exception') msg = msg.red; else if(log.method == 'warn') msg = msg.yellow; @@ -286,7 +295,7 @@ function insertConsoleLogScript(html) { return html; } -IonicServeTask.prototype._changed = function(filePath) { +IonicTask.prototype._changed = function(filePath) { // Cleanup the path a bit var pwd = process.cwd(); filePath = filePath.replace(pwd + '/', ''); @@ -315,7 +324,7 @@ IonicServeTask.prototype._changed = function(filePath) { }; -IonicServeTask.prototype.host = function(port) { +IonicTask.prototype.host = function(port) { var addresses = []; try { @@ -335,4 +344,4 @@ IonicServeTask.prototype.host = function(port) { return 'http://' + (addresses.length === 1 ? addresses[0] : 'localhost') + ':' + port; }; -exports.IonicServeTask = IonicServeTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js index 68263d22ec..60f6345b82 100644 --- a/lib/ionic/setup.js +++ b/lib/ionic/setup.js @@ -1,4 +1,4 @@ -var IonicTask = require('./task').IonicTask, +var Task = require('./task').Task, IonicStats = require('./stats').IonicStats, fs = require('fs'), path = require('path'), @@ -8,11 +8,11 @@ var IonicTask = require('./task').IonicTask, IonicProject = require('./project'), colors = require('colors'); -var IonicSetupTask = function() {}; +var IonicTask = function() {}; -IonicSetupTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicSetupTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { if( argv._.length < 2 ) { return ionic.fail('Missing setup task command.', 'setup'); } @@ -31,7 +31,7 @@ IonicSetupTask.prototype.run = function(ionic) { }; -IonicSetupTask.prototype.sassSetup = function(ionic) { +IonicTask.prototype.sassSetup = function(ionic) { var q = Q.defer(); var self = this; @@ -100,7 +100,7 @@ IonicSetupTask.prototype.sassSetup = function(ionic) { }; -IonicSetupTask.prototype.buildSass = function() { +IonicTask.prototype.buildSass = function() { var q = Q.defer(); var childProcess = exec('gulp sass'); @@ -130,7 +130,7 @@ IonicSetupTask.prototype.buildSass = function() { }; -IonicSetupTask.prototype.npmInstall = function() { +IonicTask.prototype.npmInstall = function() { var q = Q.defer(); var childProcess = exec('npm install'); @@ -163,4 +163,4 @@ IonicSetupTask.prototype.npmInstall = function() { }; -exports.IonicSetupTask = IonicSetupTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 09900ad962..4bfffa9e87 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -12,18 +12,18 @@ var fs = require('fs'), xml2js = require('xml2js'), setup = require('./setup'), IonicProject = require('./project'), - IonicTask = require('./task').IonicTask; + Task = require('./task').Task; IonicStats = require('./stats').IonicStats; -var IonicStartTask = function() {}; +var IonicTask = function() {}; // The URL for the cordova wrapper project -IonicStartTask.WRAPPER_REPO_NAME = 'ionic-app-base'; +IonicTask.WRAPPER_REPO_NAME = 'ionic-app-base'; -IonicStartTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicStartTask.prototype.run = function(ionic) { +IonicTask.prototype.run = function(ionic) { this.ionic = ionic; var self = this; @@ -94,7 +94,7 @@ IonicStartTask.prototype.run = function(ionic) { }; -IonicStartTask.prototype.startApp = function() { +IonicTask.prototype.startApp = function() { var self = this; self.fetchWrapper() @@ -117,14 +117,14 @@ IonicStartTask.prototype.startApp = function() { }; -IonicStartTask.prototype.fetchWrapper = function() { +IonicTask.prototype.fetchWrapper = function() { var q = Q.defer(); var self = this; - var repoUrl = 'https://github.com/driftyco/' + IonicStartTask.WRAPPER_REPO_NAME + '/archive/master.zip'; + var repoUrl = 'https://github.com/driftyco/' + IonicTask.WRAPPER_REPO_NAME + '/archive/master.zip'; Ionic.fetchArchive(self.targetPath, repoUrl).then(function() { - var repoFolderName = IonicStartTask.WRAPPER_REPO_NAME + '-master'; + var repoFolderName = IonicTask.WRAPPER_REPO_NAME + '-master'; cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath); rm('-rf', self.targetPath + '/' + repoFolderName + '/'); cd(self.targetPath); @@ -148,7 +148,7 @@ IonicStartTask.prototype.fetchWrapper = function() { }; -IonicStartTask.prototype.fetchSeed = function() { +IonicTask.prototype.fetchSeed = function() { if(this.template.toLowerCase().indexOf('codepen') > -1) { this.seedType = 'codepen'; @@ -160,7 +160,7 @@ IonicStartTask.prototype.fetchSeed = function() { }; -IonicStartTask.prototype.fetchCodepen = function() { +IonicTask.prototype.fetchCodepen = function() { var self = this; var codepenUrl = this.template.split('?')[0].split('#')[0]; var wwwPath = path.join(this.targetPath, 'www'); @@ -225,7 +225,7 @@ IonicStartTask.prototype.fetchCodepen = function() { }; -IonicStartTask.prototype.convertTemplates = function(html) { +IonicTask.prototype.convertTemplates = function(html) { var templates = []; var self = this; @@ -283,7 +283,7 @@ IonicStartTask.prototype.convertTemplates = function(html) { }; -IonicStartTask.prototype.fetchIonicStarter = function() { +IonicTask.prototype.fetchIonicStarter = function() { var self = this; var q = Q.defer(); @@ -316,7 +316,7 @@ IonicStartTask.prototype.fetchIonicStarter = function() { }; -IonicStartTask.prototype.initCordova = function() { +IonicTask.prototype.initCordova = function() { var self = this; var q = Q.defer(); @@ -362,7 +362,7 @@ IonicStartTask.prototype.initCordova = function() { }; -IonicStartTask.prototype.updateConfigXml = function() { +IonicTask.prototype.updateConfigXml = function() { var self = this; console.log('\nUpdate config.xml'.info.bold); @@ -400,7 +400,7 @@ IonicStartTask.prototype.updateConfigXml = function() { }; -IonicStartTask.prototype.setupSass = function() { +IonicTask.prototype.setupSass = function() { if(argv.sass) { // auto setup sass if they set the option console.log('setup sass'.green.bold); @@ -415,7 +415,7 @@ IonicStartTask.prototype.setupSass = function() { }; -IonicStartTask.prototype.updateLibFiles = function() { +IonicTask.prototype.updateLibFiles = function() { var libPath = argv.lib || argv.l || 'lib/ionic'; // create a symlink if the path exists locally @@ -547,7 +547,7 @@ IonicStartTask.prototype.updateLibFiles = function() { }; -IonicStartTask.prototype.finalize = function() { +IonicTask.prototype.finalize = function() { this.updateLibFiles(); @@ -593,7 +593,7 @@ IonicStartTask.prototype.finalize = function() { }; -IonicStartTask.prototype.printQuickHelp = function() { +IonicTask.prototype.printQuickHelp = function() { console.log('\nYour Ionic project is ready to go!'.green.bold, 'Some quick tips:'); console.log('\n * cd into your project:', ('$ cd ' + this.appDirectory).info.bold); @@ -618,4 +618,4 @@ IonicStartTask.prototype.printQuickHelp = function() { }; -exports.IonicStartTask = IonicStartTask; +exports.IonicTask = IonicTask; diff --git a/lib/ionic/task.js b/lib/ionic/task.js index 20ffec018f..3385c4af82 100644 --- a/lib/ionic/task.js +++ b/lib/ionic/task.js @@ -1,8 +1,8 @@ -var IonicTask = function() { }; +var Task = function() { }; -IonicTask.prototype = { +Task.prototype = { run: function(ionic) { } }; -exports.IonicTask = IonicTask; +exports.Task = Task; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index e0400a4f6a..5ba96d3cbd 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -5,16 +5,16 @@ var fs = require('fs'), argv = require('optimist').argv, FormData = require('form-data'), IonicProject = require('./project'), - IonicTask = require('./task').IonicTask, + Task = require('./task').Task, IonicStats = require('./stats').IonicStats, IonicLoginTask = require('./login').IonicLoginTask, Q = require('q'); -var IonicUploadTask = function() {}; +var IonicTask = function() {}; -IonicUploadTask.prototype = new IonicTask(); +IonicTask.prototype = new Task(); -IonicUploadTask.prototype.run = function(ionic, callback) { +IonicTask.prototype.run = function(ionic, callback) { var project = IonicProject.load(); var q = Q.defer(); @@ -129,4 +129,4 @@ IonicUploadTask.prototype.run = function(ionic, callback) { }); }; -exports.IonicUploadTask = IonicUploadTask; +exports.IonicTask = IonicTask; From c732e44e2da3ca3d7fd91e4cf01484356dc7a4f5 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 21:52:12 -0500 Subject: [PATCH 214/850] remove white text, closes #70 --- lib/ionic.js | 19 ++++++++++--------- lib/ionic/lib.js | 2 +- lib/ionic/login.js | 2 +- lib/ionic/setup.js | 6 +++--- lib/ionic/start.js | 32 ++++++++++++++++---------------- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2dbf7e5530..4c41e65b0a 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -18,7 +18,7 @@ var argv = require('optimist').argv, colors = require('colors'), Q = require('q'), settings = require('../package.json'), - shelljs = require('shelljs/global'),; + shelljs = require('shelljs/global'); colors.setTheme({ silly: 'rainbow', @@ -58,7 +58,7 @@ var TASKS = [ { title: 'serve', name: 'serve', - summary: 'Start a local development server for app dev and testing', + summary: 'Start a local development server for app dev/testing', args: { '[options]': '' }, @@ -92,7 +92,7 @@ var TASKS = [ }, options: { '--livereload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, - '--port|-p': 'Dev server HTTP port (8100 default, livereload required)', + '--port|-p': 'Dev server HTTP port (8100 default, livereload req.)', '--livereload-port|-r': 'Live Reload port (35729 default, livereload req.)', '--consolelogs|-c': 'Print app console logs to Ionic CLI (livereload req.)', '--serverlogs|-s': 'Print dev server logs to Ionic CLI (livereload req.)', @@ -111,7 +111,7 @@ var TASKS = [ }, options: { '--livereload|-l': 'Live reload app dev files from the device' + ' (beta)'.yellow, - '--port|-p': 'Dev server HTTP port (8100 default, livereload required)', + '--port|-p': 'Dev server HTTP port (8100 default, livereload req.)', '--livereload-port|-r': 'Live Reload port (35729 default, livereload req.)', '--consolelogs|-c': 'Print app console logs to Ionic CLI (livereload req.)', '--serverlogs|-s': 'Print dev server logs to Ionic CLI (livereload req.)', @@ -139,8 +139,9 @@ var TASKS = [ '': 'Can be a plugin ID, a local path, or a git URL.' }, options: { - '--searchpath ': 'When looking up plugins by ID, look in this directory and\n' + - 'subdirectories for the plugin before using the registry.' + '--searchpath ': 'When looking up plugins by ID, look in this directory\n' + + 'and subdirectories first for the plugin before\n' + + 'looking it up in the registry.' }, module: './ionic/cordova' }, @@ -200,7 +201,7 @@ var TASKS = [ '[update]': 'Updates the Ionic Framework in www/lib/ionic' }, options: { - '--version|-v': 'Spcific Ionic version, otherwise it defaults to the latest' + '--version|-v': 'Spcific Ionic version\nOtherwise it defaults to the latest version' }, module: './ionic/lib' }, @@ -504,7 +505,7 @@ Ionic = { process.stdout.write('Ionic CLI is out of date:\n'.bold.yellow); process.stdout.write( (' * Locally installed version: ' + settings.version + '\n').yellow ); process.stdout.write( (' * Latest version: ' + this.npmVersion + '\n').yellow ); - process.stdout.write( ' * Run '.yellow + 'npm update -g ionic'.info.bold + ' to update\n'.yellow ); + process.stdout.write( ' * Run '.yellow + 'npm update -g ionic'.bold + ' to update\n'.yellow ); process.stdout.write('-------------------------\n\n'.red); this.npmVersion = null; } @@ -527,7 +528,7 @@ Ionic = { var q = Q.defer(); // The folder name the project will be downloaded and extracted to - console.log('\nDownloading:'.info.bold, archiveUrl); + console.log('\nDownloading:'.bold, archiveUrl); var tmpFolder = os.tmpdir(); var tempZipFilePath = path.join(tmpFolder, 'ionic-starter-' + new Date().getTime() + '.zip'); diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index eefc6e6872..bb5bbbf282 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -135,7 +135,7 @@ IonicTask.prototype.updateLibVersion = function() { var libPath = path.resolve('www/lib/ionic/'); - console.log('Are you sure you want to replace '.green.bold + libPath.info.bold + ' with an updated version of Ionic?'.green.bold); + console.log('Are you sure you want to replace '.green.bold + libPath.bold + ' with an updated version of Ionic?'.green.bold); var promptProperties = { areYouSure: { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index e94a7edff8..9b29a04371 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -67,7 +67,7 @@ IonicTask.prototype.run = function(ionic, callback) { // prompt for log console.log('\nTo continue, please login to your Ionic account.'.bold.green); - console.log('Don\'t have one? Create a one at: '.bold + (ionic.IONIC_DASH + '/signup').info.bold + '\n'); + console.log('Don\'t have one? Create a one at: '.bold + (ionic.IONIC_DASH + '/signup').bold + '\n'); prompt.override = argv; prompt.message = ''; diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js index 60f6345b82..0528d4990b 100644 --- a/lib/ionic/setup.js +++ b/lib/ionic/setup.js @@ -49,7 +49,7 @@ IonicTask.prototype.sassSetup = function(ionic) { } try { - var activeRemoving = false; + activeRemoving = false; for(x=0; x'.info.bold); - console.log('\n * Simulate your app:', 'ionic emulate '.info.bold); - console.log('\n * Run your app on a device:', 'ionic run '.info.bold); - console.log('\n * Package an app using Ionic package service:', 'ionic package '.info.bold); + console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.bold); + console.log(' Note: iOS development requires OS X currently'.small); + console.log(' See the Android Platform Guide for full Android installation instructions:'.small); + console.log(' https://cordova.apache.org/docs/en/edge/guide_platforms_android_index.md.html'.small); + console.log('\n * Build your app:', 'ionic build '.bold); + console.log('\n * Simulate your app:', 'ionic emulate '.bold); + console.log('\n * Run your app on a device:', 'ionic run '.bold); + console.log('\n * Package an app using Ionic package service:', 'ionic package '.bold); } - console.log('\nFor more help use', 'ionic --help'.info.bold, 'or visit the Ionic docs:', 'http://ionicframework.com/docs\n'.info.bold); + console.log('\nFor more help use', 'ionic --help'.bold, 'or visit the Ionic docs:', 'http://ionicframework.com/docs\n'.bold); }; From ee226be9326c444415bb816623efa5aee8a920c0 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 22:13:34 -0500 Subject: [PATCH 215/850] console.dir --- lib/ionic/serve.js | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index bd5bdee492..54a5a63690 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -210,12 +210,32 @@ IonicTask.prototype.consoleLog = function(req) { msg += ' '; } + var msgIndent = ''; + while(msgIndent.length < msg.length) { + msgIndent += ' '; + } + if(log.method == 'dir') { - var dirObjs = []; - log.args.forEach(function(objStr){ - dirObjs.push( JSON.stringify( JSON.parse(objStr) ) ); + var isFirstLine = true; + + log.args.forEach(function(argObj){ + + for(objKey in argObj) { + if(isFirstLine) { + isFirstLine = false; + } else { + msg += '\n' + msgIndent; + } + msg += objKey + ': '; + try { + msg += ( JSON.stringify(argObj[objKey], null, 1) ).replace(/\n/g, ''); + } catch(e) { + msg += argObj[objKey]; + } + } + }); - msg += dirObjs.join('\n'); + } else { msg += log.args.join(', '); } From 11d17a29f4f9b5a79a5b5a520f0984055d06062a Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 3 Sep 2014 22:14:07 -0500 Subject: [PATCH 216/850] v update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dcb87ef311..153ac78d0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.0", + "version": "1.2.1-beta1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 090fb4cf321c980c2981fedf3c7a3e7d269cec8a Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 4 Sep 2014 11:19:36 -0500 Subject: [PATCH 217/850] fix module references --- lib/ionic/package.js | 4 ++-- lib/ionic/upload.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ionic/package.js b/lib/ionic/package.js index e296b0d1dc..55ae310364 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -9,9 +9,9 @@ var fs = require('fs'), IonicProject = require('./project'), IonicStore = require('./store').IonicStore, Task = require('./task').Task, - IonicUploadTask = require('./upload').IonicUploadTask, + IonicUploadTask = require('./upload').IonicTask, IonicStats = require('./stats').IonicStats, - IonicLoginTask = require('./login').IonicLoginTask; + IonicLoginTask = require('./login').IonicTask; var IonicTask = function() {}; diff --git a/lib/ionic/upload.js b/lib/ionic/upload.js index 5ba96d3cbd..53bd0973f9 100644 --- a/lib/ionic/upload.js +++ b/lib/ionic/upload.js @@ -7,7 +7,7 @@ var fs = require('fs'), IonicProject = require('./project'), Task = require('./task').Task, IonicStats = require('./stats').IonicStats, - IonicLoginTask = require('./login').IonicLoginTask, + IonicLoginTask = require('./login').IonicTask, Q = require('q'); var IonicTask = function() {}; From c2048197ba8558af9c230537b1fd1c2d42d0e520 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 4 Sep 2014 11:20:23 -0500 Subject: [PATCH 218/850] clean cordova cmds / ensure config reset --- lib/ionic/cordova.js | 54 ++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 40f898c118..cd54d55766 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -16,22 +16,17 @@ IonicTask.prototype.run = function(ionic) { self.ionic = ionic; var cmdName = process.argv[2].toLowerCase(); var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); - - // clean out any cmds that may confuse cordova - var port = argv.port || argv.p || ''; - var liveReloadPort = argv.livereloadport || argv['livereload-port'] || argv.i || ''; - if(port || liveReloadPort) { - for(var x=0; x Date: Thu, 4 Sep 2014 21:40:52 -0500 Subject: [PATCH 219/850] always fs.chmodSync(projectScript, '755'); --- lib/ionic/cordova.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index cd54d55766..bb31d764fe 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -192,16 +192,7 @@ IonicTask.prototype.addHooks = function() { // check if this hook script has already been added to this ionic project var projectHookPath = path.join('hooks', hookDirectoryName, hookFilename); - if( !fs.existsSync(projectHookPath) ) { - addHookScript(cliHookPath, hookDirectoryName, hookFilename); - } - - // make the script file executable - try { - fs.chmodSync(projectScript, '755'); - } catch(e) { - console.log( ('addcliHookDirectory fs.chmodSync: ' + e).error ); - } + addHookScript(cliHookPath, hookDirectoryName, hookFilename); } }); } @@ -220,10 +211,24 @@ IonicTask.prototype.addHooks = function() { fs.mkdirSync(projectHookPath); } - // copy the hook script to the project - var cliScript = path.join(cliHookPath, hookFilename); var projectScript = path.join(projectHookPath, hookFilename); - fs.createReadStream( cliScript ).pipe(fs.createWriteStream( projectScript )); + if( !fs.existsSync(projectHookPath) ) { + // copy the hook script to the project + try { + var cliScript = path.join(cliHookPath, hookFilename); + fs.createReadStream( cliScript ).pipe(fs.createWriteStream( projectScript )); + } catch(e) { + console.log( ('addcliHookDirectory fs.createReadStream: ' + e).error ); + return; + } + } + + // make the script file executable + try { + fs.chmodSync(projectScript, '755'); + } catch(e) { + console.log( ('addcliHookDirectory fs.chmodSync: ' + e).error ); + } } catch(e) { console.log('Error adding hook script ' + hookDirectoryName + '/' + hookFilename + ', ' + e); From f5342357c97093ec34ee9b94d4fe500a3a6e5027 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 4 Sep 2014 22:31:13 -0500 Subject: [PATCH 220/850] always 200 response --- lib/ionic/serve.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 54a5a63690..a33458cf21 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -120,9 +120,8 @@ IonicTask.prototype.start = function(ionic) { fs.readFile( path.resolve(path.join(platformWWW, platformUrl)), function (err, buf) { res.setHeader('Content-Type', 'application/javascript'); if (err) { - self.serverLog(req.url + ' (Error ' + platformWWW + ')'); - res.statusCode = 404; - res.end('// 404'); + self.serverLog(req.url + ' (' + platformWWW + ')'); + res.end('// mocked cordova.js response to prevent 404 errors during development'); } else { self.serverLog(req.url + ' (' + platformWWW + ')'); res.end(buf); From 151816b8ad947ef6f24ca8f4c0c168ffc7ac62aa Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 10:12:24 -0500 Subject: [PATCH 221/850] log read/write errors --- lib/ionic.js | 10 ++++++++++ lib/ionic/lib.js | 17 ++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 4c41e65b0a..2880ce0034 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -534,14 +534,24 @@ Ionic = { var tempZipFilePath = path.join(tmpFolder, 'ionic-starter-' + new Date().getTime() + '.zip'); var tempZipFileStream = fs.createWriteStream(tempZipFilePath); + tempZipFileStream.on('error', function(err) { + console.log( ('fetchArchive tempZipFileStream: ' + err).error ); + q.reject(err); + }); + var unzipRepo = function(fileName) { var readStream = fs.createReadStream(fileName); + readStream.on('error', function(err) { + console.log( ('unzipRepo readStream: ' + err).error ); + q.reject(err); + }); var writeStream = unzip.Extract({ path: targetPath }); writeStream.on('close', function() { q.resolve(); }); writeStream.on('error', function(err) { + console.log( ('unzipRepo writeStream: ' + err).error ); q.reject(err); }); readStream.pipe(writeStream); diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index bb5bbbf282..6df94a0e00 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -197,6 +197,10 @@ IonicTask.prototype.downloadZip = function(version) { console.log('Downloading: '.green.bold + archivePath); var file = fs.createWriteStream(self.tmpZipPath); + file.on('error', function(err) { + console.log( ('downloadZip createWriteStream: ' + err).error ); + }); + var proxy = process.env.PROXY || null; request({ url: archivePath, encoding: null, proxy: proxy }, function(err, res, body) { if(err) { @@ -275,7 +279,7 @@ IonicTask.prototype.updateFiles = function(version) { } else { var writeStream = fs.createWriteStream(libEntryPath); writeStream.on('error', function(err) { - console.log( ('Error writing, ' + libEntryPath + ': ' + err).bold.red ); + console.log( ('updateFiles error writing, ' + libEntryPath + ': ' + err).error ); }); entry.pipe(writeStream); } @@ -301,7 +305,7 @@ IonicTask.prototype.updateFiles = function(version) { }); readStream.on('error', function(err){ - console.log('Error: ' + err); + console.log( ('updateFiles readStream: ' + err).error ); }); readStream.on('close', function(err){ @@ -323,9 +327,12 @@ IonicTask.prototype.writeVersionData = function() { "date": this.versionData.release_date || this.versionData.date }; - var file = fs.createWriteStream( path.resolve('www/lib/ionic/version.json') ); - file.write( JSON.stringify(versionData, null, 2) ); - file.close(); + var fstream = fs.createWriteStream( path.resolve('www/lib/ionic/version.json') ); + fstream.on('error', function(err) { + console.log( ('writeVersionData err: ' + err).error ); + }); + fstream.write( JSON.stringify(versionData, null, 2) ); + fstream.close(); } catch(e) { console.log( ('Error writing version data: ' + e).error.bold ); } From db8eb6625e3fdfa6dee2ddf9d9a3c7f426f606fe Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 10:12:55 -0500 Subject: [PATCH 222/850] reset config.xml after cordova exit --- lib/ionic/cordova.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index bb31d764fe..61adda5350 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -88,9 +88,11 @@ IonicTask.prototype.run = function(ionic) { cordovaProcess.on('exit', function(){ if(self.isLiveReload) { - self.setConfigXml({ - resetContent: true - }); + setTimeout(function(){ + self.setConfigXml({ + resetContent: true + }); + }, 5000); } }); @@ -136,12 +138,15 @@ IonicTask.prototype.setConfigXml = function(options) { } if(jsonConfig.widget.content[0].$.src !== options.devServer) { jsonConfig.widget.content[0].$.src = options.devServer; + console.log( ('Update config.xml for live reload: content[src="' + options.devServer + '"]').yellow ); madeChange = true; } } else if(options.resetContent) { + if( jsonConfig.widget.content[0].$['original-src'] ) { jsonConfig.widget.content[0].$.src = jsonConfig.widget.content[0].$['original-src']; + console.log( ('Reset config.xml after live reload build, return to content[src="' + jsonConfig.widget.content[0].$.src + '"]').yellow ); delete jsonConfig.widget.content[0].$['original-src']; madeChange = true; } @@ -150,7 +155,6 @@ IonicTask.prototype.setConfigXml = function(options) { if(madeChange) { var xmlBuilder = new xml2js.Builder(); configString = xmlBuilder.buildObject(jsonConfig); - fs.writeFileSync(configXmlPath, configString); } @@ -178,11 +182,11 @@ IonicTask.prototype.addHooks = function() { if(err) return; for(var x=0; x -1) continue; - addcliHookDirectory( path.join(cliHooksPath, files[x]), files[x] ); + addCliHookDirectory( path.join(cliHooksPath, files[x]), files[x] ); } }); - function addcliHookDirectory(cliHookPath, hookDirectoryName) { + function addCliHookDirectory(cliHookPath, hookDirectoryName) { fs.readdir(cliHookPath, function(err, files){ // loop through each of the scripts in the ionic-cli hook directory if(err) return; @@ -218,7 +222,7 @@ IonicTask.prototype.addHooks = function() { var cliScript = path.join(cliHookPath, hookFilename); fs.createReadStream( cliScript ).pipe(fs.createWriteStream( projectScript )); } catch(e) { - console.log( ('addcliHookDirectory fs.createReadStream: ' + e).error ); + console.log( ('addCliHookDirectory fs.createReadStream: ' + e).error ); return; } } @@ -227,7 +231,7 @@ IonicTask.prototype.addHooks = function() { try { fs.chmodSync(projectScript, '755'); } catch(e) { - console.log( ('addcliHookDirectory fs.chmodSync: ' + e).error ); + console.log( ('addCliHookDirectory fs.chmodSync: ' + e).error ); } } catch(e) { From 55dbf15b96f44c2925715fe7c4671453e6bb30ec Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 10:13:23 -0500 Subject: [PATCH 223/850] update logging --- lib/ionic/serve.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index a33458cf21..3d1b059081 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -120,8 +120,12 @@ IonicTask.prototype.start = function(ionic) { fs.readFile( path.resolve(path.join(platformWWW, platformUrl)), function (err, buf) { res.setHeader('Content-Type', 'application/javascript'); if (err) { - self.serverLog(req.url + ' (' + platformWWW + ')'); res.end('// mocked cordova.js response to prevent 404 errors during development'); + if(req.url == '/cordova.js') { + self.serverLog(req.url + ' (mocked)'); + } else { + self.serverLog(req.url + ' (Error ' + platformWWW + ')'); + } } else { self.serverLog(req.url + ' (' + platformWWW + ')'); res.end(buf); @@ -181,7 +185,7 @@ IonicTask.prototype.start = function(ionic) { IonicTask.prototype.serverLog = function(msg) { if(this.printServerLogs) { - console.log( ('serve: ' + msg).yellow ); + console.log( ('serve ' + msg).yellow ); } }; @@ -200,12 +204,14 @@ IonicTask.prototype.consoleLog = function(req) { var log = JSON.parse(body); var msg = log.index + ' '; - while(msg.length < 4) { + while(msg.length < 5) { msg += ' '; } + msg += ' ' + (log.ts + '').substr(7) + ' '; + msg += log.method; - while(msg.length < 14) { + while(msg.length < 24) { msg += ' '; } @@ -285,17 +291,17 @@ function insertConsoleLogScript(html) { var methods = "assert clear count debug dir dirxml error exception group groupCollapsed groupEnd info log markTimeline profile profileEnd table time timeEnd timeStamp trace warn".split(" ");\n\ var console = (window.console=window.console || {});\n\ var logCount = 0;\n\ + window.onerror = function(msg, url, line) {\n\ + if(msg && url) console.error(msg, url, (line ? "Line: " + line : ""));\n\ + };\n\ function sendConsoleLog(method, args) {\n\ try {\n\ var xhr = new XMLHttpRequest();\n\ xhr.open("POST", "/__ionic-cli/console", true);\n\ - xhr.send(JSON.stringify({ index: logCount, method: method, args: args }));\n\ + xhr.send(JSON.stringify({ index: logCount, method: method, ts: Date.now(), args: args }));\n\ logCount++;\n\ } catch(e){}\n\ }\n\ - window.onerror = function(msg, url, line) {\n\ - if(msg && url) console.error(msg, url, (line ? "Line: " + line : ""));\n\ - };\n\ for(var x=0; x Date: Fri, 5 Sep 2014 12:10:44 -0500 Subject: [PATCH 224/850] ask for which ip --- lib/ionic.js | 5 +++ lib/ionic/cordova.js | 69 +++++++++++++++++++++-------- lib/ionic/serve.js | 100 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 139 insertions(+), 35 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index 2880ce0034..d5ef6b44c4 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -218,6 +218,11 @@ var TASKS = [ title: 'login', name: 'login', module: './ionic/login' + }, + { + title: 'ip', + name: 'ip', + module: './ionic/serve' } ]; diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 61adda5350..77f15b973a 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -1,6 +1,7 @@ var Task = require('./task').Task, IonicStats = require('./stats').IonicStats, fs = require('fs'), + Q = require('q'), argv = require('optimist').argv, xml2js = require('xml2js'), path = require('path'), @@ -12,23 +13,34 @@ var IonicTask = function() {}; IonicTask.prototype = new Task(); IonicTask.prototype.run = function(ionic) { + this.ionic = ionic; var self = this; - self.ionic = ionic; var cmdName = process.argv[2].toLowerCase(); - var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); - var cmdArg, x, y; + var q; - self.isLiveReload = ((cmdName == 'run' || cmdName == 'emulate') && (argv.livereload || argv['live-reload'] || argv.l)); + this.isLiveReload = ((cmdName == 'run' || cmdName == 'emulate') && (argv.livereload || argv['live-reload'] || argv.l)); + + if(this.isLiveReload) { + q = self.setupLiveReload(); - if(self.isLiveReload) { - self.setupLiveReload(); } else { // ensure the content node was set back to its original - self.setConfigXml({ + q = this.setConfigXml({ resetContent: true }); } + q.then(function(){ + self.runCordova(cmdName); + }) +}; + + +IonicTask.prototype.runCordova = function(cmdName) { + var self = this; + var cmdArgs = (process.argv.length > 3 ? process.argv.slice(3) : []); + var cmdArg, x, y; + // backwards compatibility prior to fully wrapping cordova cmds if(cmdName == 'platform') { // `ionic platform ` used to actually run `ionic platform add ` @@ -86,38 +98,58 @@ IonicTask.prototype.run = function(ionic) { } }); - cordovaProcess.on('exit', function(){ - if(self.isLiveReload) { + if(self.isLiveReload) { + cordovaProcess.on('exit', function(){ setTimeout(function(){ + // set it back to the original src after a few seconds self.setConfigXml({ resetContent: true }); }, 5000); - } - }); + }); + + process.on('exit', function(){ + // verify it was set back + self.setConfigXml({ + resetContent: true + }); + }); + } IonicStats.t(); }; IonicTask.prototype.setupLiveReload = function() { + var d = Q.defer(); + console.log('Setup Live Reload'.green.bold); + var self = this; var serve = new require('./serve'); var serveTask = new serve.IonicTask(); - serveTask.loadSettings(); - serveTask.runLivereload = true; - serveTask.launchBrowser = false; serveTask.isPlatformServe = true; - serveTask.start(this.ionic); - this.setConfigXml({ - devServer: serveTask.devServer + serveTask.loadSettings(function(){ + serveTask.runLivereload = true; + serveTask.launchBrowser = false; + serveTask.start(self.ionic); + + self.setConfigXml({ + devServer: serveTask.devServer + }).then(function(){ + d.resolve(); + }); + }); + + return d.promise; }; IonicTask.prototype.setConfigXml = function(options) { + var d = Q.defer(); + var self = this; var madeChange = false; @@ -158,11 +190,14 @@ IonicTask.prototype.setConfigXml = function(options) { fs.writeFileSync(configXmlPath, configString); } + d.resolve(); }); } catch(e) { return self.ionic.fail('Error updating config.xml file: ' + e); } + + return d.promise; }; diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 3d1b059081..de91740a5f 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -5,13 +5,10 @@ var fs = require('fs'), finalhandler = require('finalhandler'), http = require('http'), serveStatic = require('serve-static'), - open = require('open'), tinylr = require('tiny-lr-fork'), lr = require('connect-livereload'), vfs = require('vinyl-fs'), request = require('request'), - Q = require('q'), - spawn = require('child_process').spawn, IonicProject = require('./project'), Task = require('./task').Task; IonicStats = require('./stats').IonicStats; @@ -24,21 +21,30 @@ var IonicTask = function() {}; IonicTask.prototype = new Task(); IonicTask.prototype.run = function(ionic) { + var self = this; + this.port = argv._[1]; this.liveReloadPort = argv._[2]; - this.loadSettings(); - this.start(ionic); + this.loadSettings(function(){ + + if(argv._[0] == 'ip') { + console.log( this.ip ); + return; + } + + self.start(ionic); - if(ionic.hasFailed) return; + if(ionic.hasFailed) return; - ionic.latestVersion.promise.then(function(){ - ionic.printVersionWarning(); + ionic.latestVersion.promise.then(function(){ + ionic.printVersionWarning(); + }); }); }; -IonicTask.prototype.loadSettings = function() { +IonicTask.prototype.loadSettings = function(cb) { var project = IonicProject.load(); this.port = this.port || argv.port || argv.p || DEFAULT_HTTP_PORT; @@ -49,6 +55,8 @@ IonicTask.prototype.loadSettings = function() { this.watchSass = project.get('sass') === true && !argv.nosass && !argv.n; this.printServerLogs = argv.serverlogs || argv['server-logs'] || argv.s; this.printConsoleLogs = argv.consolelogs || argv['console-logs'] || argv.c; + + this.getIp(cb); }; IonicTask.prototype.start = function(ionic) { @@ -60,6 +68,7 @@ IonicTask.prototype.start = function(ionic) { } if(this.watchSass) { + var spawn = require('child_process').spawn; var childProcess = spawn('gulp', ['sass','watch']); childProcess.stdout.on('data', function (data) { @@ -88,6 +97,7 @@ IonicTask.prototype.start = function(ionic) { } else { console.log('Running live reload server:'.green.bold, self.liveReloadServer.bold ); if(self.launchBrowser) { + var open = require('open'); open( self.host(self.port) ); } } @@ -348,25 +358,79 @@ IonicTask.prototype._changed = function(filePath) { }); }; - -IonicTask.prototype.host = function(port) { - var addresses = []; - +IonicTask.prototype.getIp = function(cb) { try { + var self = this; + var addresses = []; var os = require('os'); var ifaces = os.networkInterfaces(); for (var dev in ifaces) { - if(!dev || dev.indexOf('box') > -1) continue; ifaces[dev].forEach(function(details){ - if (details.family == 'IPv4' && !details.internal) { - addresses.push(details.address); + if (details.family == 'IPv4' && !details.internal && details.address) { + addresses.push({ + ip: details.address, + dev: dev + }); + } + }); + } + + if(addresses.length === 1) { + this._ip = addresses[0].ip; + cb(); + + } else if(addresses.length > 1 && this.isPlatformServe) { + console.log('\nMultiple IPv4 addresses available.'.error.bold); + console.log('Please select which address to use by entering its number from the list below:'.error.bold); + + for(var x=0; x Date: Fri, 5 Sep 2014 14:10:30 -0500 Subject: [PATCH 225/850] no random package name for tmp --- lib/ionic/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 01858e3a14..ae4a41b5ec 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -377,7 +377,7 @@ IonicTask.prototype.updateConfigXml = function() { } if(!self.packageName) { - var packageName = self.appDirectory + Math.round((Math.random() * 899999) + 100000); + var packageName = self.appDirectory + (self.appDirectory !== 'tmp' ? Math.round((Math.random() * 899999) + 100000) : ''); self.packageName = 'com.ionicframework.' + packageName.replace(/\./g, ''); } From c4053583c508fd72ade002d063762e7b93f70744 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 14:11:10 -0500 Subject: [PATCH 226/850] prevent bad console logs --- lib/ionic/serve.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index de91740a5f..00957213fa 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -230,7 +230,7 @@ IonicTask.prototype.consoleLog = function(req) { msgIndent += ' '; } - if(log.method == 'dir') { + if(log.method == 'dir' || log.method == 'table') { var isFirstLine = true; log.args.forEach(function(argObj){ @@ -251,7 +251,8 @@ IonicTask.prototype.consoleLog = function(req) { }); - } else { + } else if(log.args.length) { + if(log.args.length === 2 && log.args[0] === '%o' && log.args[1] == '[object Object]') return; msg += log.args.join(', '); } From 963d293984267fe4d2156c5399d08e8e5cb08232 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 14:11:30 -0500 Subject: [PATCH 227/850] 1.2.1-beta2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 153ac78d0f..b2b9a6fe3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.1-beta1", + "version": "1.2.1-beta2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From da30b43d7a638fb91159d5cfdfa632c67dec14df Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 14:38:05 -0500 Subject: [PATCH 228/850] fix ip --- lib/ionic/serve.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 00957213fa..860080d787 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -28,8 +28,8 @@ IonicTask.prototype.run = function(ionic) { this.loadSettings(function(){ - if(argv._[0] == 'ip') { - console.log( this.ip ); + if(self.isIpCmd) { + console.log( self.ip ); return; } @@ -55,8 +55,16 @@ IonicTask.prototype.loadSettings = function(cb) { this.watchSass = project.get('sass') === true && !argv.nosass && !argv.n; this.printServerLogs = argv.serverlogs || argv['server-logs'] || argv.s; this.printConsoleLogs = argv.consolelogs || argv['console-logs'] || argv.c; + this.isIpCmd = argv._[0].toLowerCase() == 'ip'; this.getIp(cb); + + process.stdin.on('readable', function() { + var chunk = process.stdin.read(); + if (chunk !== null && /exit|quit|close|stop/gi.test(chunk)) { + process.exit(); + } + }); }; IonicTask.prototype.start = function(ionic) { @@ -95,7 +103,7 @@ IonicTask.prototype.start = function(ionic) { if(err) { return ionic.fail('Unable to start live reload server:', err); } else { - console.log('Running live reload server:'.green.bold, self.liveReloadServer.bold ); + console.log('Running live reload server:'.green.bold, self.liveReloadServer ); if(self.launchBrowser) { var open = require('open'); open( self.host(self.port) ); @@ -182,14 +190,7 @@ IonicTask.prototype.start = function(ionic) { app.use(server); app.listen(this.port); - console.log('Running dev server:'.green.bold, this.devServer.bold); - - process.stdin.on('readable', function() { - var chunk = process.stdin.read(); - if (chunk !== null && /exit|quit|close|stop/gi.test(chunk)) { - process.exit(); - } - }); + console.log('Running dev server:'.green.bold, this.devServer); }; @@ -378,10 +379,10 @@ IonicTask.prototype.getIp = function(cb) { } if(addresses.length === 1) { - this._ip = addresses[0].ip; + this.ip = addresses[0].ip; cb(); - } else if(addresses.length > 1 && this.isPlatformServe) { + } else if(addresses.length > 1) { console.log('\nMultiple IPv4 addresses available.'.error.bold); console.log('Please select which address to use by entering its number from the list below:'.error.bold); @@ -412,13 +413,16 @@ IonicTask.prototype.getIp = function(cb) { for(var x=0; x Date: Fri, 5 Sep 2014 14:38:18 -0500 Subject: [PATCH 229/850] add livereload --- lib/ionic/stats.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index 7c47ecd853..5d05ffb4b5 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -542,7 +542,9 @@ exports.IonicStats = { '-w': '--no-cordova', '-b': '--nobrowser', '-r': '--nolivereload', - '-l': '--clear-signing', + '-l': '--livereload', + '-c': '--consolelogs', + '-s': '--serverlogs', '-n': '--no-email', '-s': '--sass' }; @@ -555,7 +557,7 @@ exports.IonicStats = { } var platformWhitelist = 'android ios firefoxos wp7 wp8 amazon-fireos blackberry10 tizen'.split(' '); - var argsWhitelist = 'add remove list update check debug release search --no-cordova --nobrowser --nolivereload --no-email --debug --release --device --emulator --sass'.split(' '); + var argsWhitelist = 'add remove list update check debug release search --livereload --consolelogs --serverlogs --no-cordova --nobrowser --nolivereload --no-email --debug --release --device --emulator --sass'.split(' '); // collect only certain args, skip over everything else for(x=0; x Date: Fri, 5 Sep 2014 14:38:37 -0500 Subject: [PATCH 230/850] 1.2.1-beta3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2b9a6fe3f..1932a0eace 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.1-beta2", + "version": "1.2.1-beta3", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From a4bf801fe88f90d1ecd943ffc74076fee136e68d Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 15:34:37 -0500 Subject: [PATCH 231/850] allow content src other than index.html --- lib/ionic.js | 33 +++++++++++++++++++++++++++++++++ lib/ionic/cordova.js | 1 + lib/ionic/serve.js | 32 +++++++++++++++++++------------- lib/ionic/setup.js | 2 +- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index d5ef6b44c4..abde36a490 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -522,6 +522,39 @@ Ionic = { }); }, + getContentSrc: function() { + var self = this; + var contentSrc; + + try { + var fs = require('fs'); + var path = require('path'); + var configXmlPath = path.resolve('config.xml'); + if( !fs.existsSync(configXmlPath) ) { + return 'index.html'; + } + var configString = fs.readFileSync(configXmlPath, { encoding: 'utf8' }); + + var xml2js = require('xml2js'); + var parseString = xml2js.parseString; + parseString(configString, function (err, jsonConfig) { + if(err) { + return self.fail('Error parsing config.xml: ' + err); + } + try { + contentSrc = jsonConfig.widget.content[0].$.src; + } catch(e) { + return self.fail('Error parsing ' + configXmlPath + ': ' + e); + } + }); + + } catch(e) { + return self.fail('Error loading ' + configXmlPath + ': ' + e); + } + + return contentSrc; + }, + /** * Download a zip file, unzip it to a specific folder. */ diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 77f15b973a..f302559baf 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -128,6 +128,7 @@ IonicTask.prototype.setupLiveReload = function() { var self = this; var serve = new require('./serve'); var serveTask = new serve.IonicTask(); + serveTask.ionic = this.ionic; serveTask.isPlatformServe = true; serveTask.loadSettings(function(){ diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 860080d787..080d76fcd5 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -22,7 +22,7 @@ IonicTask.prototype = new Task(); IonicTask.prototype.run = function(ionic) { var self = this; - + this.ionic = ionic; this.port = argv._[1]; this.liveReloadPort = argv._[2]; @@ -56,6 +56,7 @@ IonicTask.prototype.loadSettings = function(cb) { this.printServerLogs = argv.serverlogs || argv['server-logs'] || argv.s; this.printConsoleLogs = argv.consolelogs || argv['console-logs'] || argv.c; this.isIpCmd = argv._[0].toLowerCase() == 'ip'; + this.contentSrc = path.join('www', this.ionic.getContentSrc()); this.getIp(cb); @@ -165,20 +166,25 @@ IonicTask.prototype.start = function(ionic) { return; } - if(req.url === '/') { - fs.readFile( path.resolve('www/index.html'), 'utf8', function (err, buf) { - res.setHeader('Content-Type', 'text/html'); - if (err) { - self.serverLog(req.url + ' : ERROR!'); - res.end(err.toString()); - } else { - self.serverLog(req.url); + } + + if(req.url === '/') { + + fs.readFile( path.resolve(self.contentSrc), 'utf8', function (err, buf) { + res.setHeader('Content-Type', 'text/html'); + if (err) { + self.serverLog(req.url + ' : ERROR!'); + res.end(err.toString()); + } else { + self.serverLog(req.url + ' (' + self.contentSrc + ')'); + if(self.printConsoleLogs) { res.end( insertConsoleLogScript(buf.toString('utf8')) ); + } else { + res.end(buf); } - }); - return; - } - + } + }); + return; } // root www directory file diff --git a/lib/ionic/setup.js b/lib/ionic/setup.js index 0528d4990b..940fdcf079 100644 --- a/lib/ionic/setup.js +++ b/lib/ionic/setup.js @@ -37,7 +37,7 @@ IonicTask.prototype.sassSetup = function(ionic) { this.npmInstall().then(function(){ - var indexPath = path.resolve('www/index.html'); + var indexPath = path.resolve( path.join('www', ionic.getContentSrc()) ); var lines, line, keepLine, activeRemoving; var cleanedLines = []; From c197d08cd7568b918bfd84276a960672c2ff1d52 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 15:35:08 -0500 Subject: [PATCH 232/850] 1.2.1-beta4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1932a0eace..37c0ede6a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.1-beta3", + "version": "1.2.1-beta4", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From dd3681b70e4e532d602189046741e45f3b105582 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Fri, 5 Sep 2014 15:45:58 -0500 Subject: [PATCH 233/850] v1.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37c0ede6a6..e758fb08cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.1-beta4", + "version": "1.2.1", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 91aee1d7b61d2a59008e410198101bda3a305078 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 6 Sep 2014 16:48:06 -0500 Subject: [PATCH 234/850] S fix --- lib/ionic/stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ionic/stats.js b/lib/ionic/stats.js index 5d05ffb4b5..230753c00f 100644 --- a/lib/ionic/stats.js +++ b/lib/ionic/stats.js @@ -596,7 +596,7 @@ exports.IonicStats = { if(statsData.cli_version.indexOf('beta') > -1) return; } catch(e2) {} - IonicStats.mp(cmdName, statsData); + this.mp(cmdName, statsData); //console.log(cmdName, statsData); } catch(e) { From 0718ed2015ec5ba6fbc3e3b21abf391d421d9b65 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Sat, 6 Sep 2014 16:48:22 -0500 Subject: [PATCH 235/850] Sfix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e758fb08cc..660e31570c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.1", + "version": "1.2.2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From f98ea25ab01ddc4d756798276533914e9fe64277 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 6 Sep 2014 20:50:50 -0500 Subject: [PATCH 236/850] remove reset config log --- lib/ionic/cordova.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index f302559baf..49d4c2ef3b 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -179,7 +179,6 @@ IonicTask.prototype.setConfigXml = function(options) { if( jsonConfig.widget.content[0].$['original-src'] ) { jsonConfig.widget.content[0].$.src = jsonConfig.widget.content[0].$['original-src']; - console.log( ('Reset config.xml after live reload build, return to content[src="' + jsonConfig.widget.content[0].$.src + '"]').yellow ); delete jsonConfig.widget.content[0].$['original-src']; madeChange = true; } From 5afe67dafd23f726557a353c6c25484c0dea8522 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 6 Sep 2014 21:26:06 -0500 Subject: [PATCH 237/850] remove config update log --- lib/ionic/cordova.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index 49d4c2ef3b..a024c7f88d 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -171,7 +171,6 @@ IonicTask.prototype.setConfigXml = function(options) { } if(jsonConfig.widget.content[0].$.src !== options.devServer) { jsonConfig.widget.content[0].$.src = options.devServer; - console.log( ('Update config.xml for live reload: content[src="' + options.devServer + '"]').yellow ); madeChange = true; } From 13228bdc02dc85d81e120f9cd606ef649f5d89fe Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 6 Sep 2014 22:17:32 -0500 Subject: [PATCH 238/850] correct errors when in wrong working directory --- lib/ionic/cordova.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/ionic/cordova.js b/lib/ionic/cordova.js index a024c7f88d..87098d5443 100644 --- a/lib/ionic/cordova.js +++ b/lib/ionic/cordova.js @@ -26,7 +26,8 @@ IonicTask.prototype.run = function(ionic) { } else { // ensure the content node was set back to its original q = this.setConfigXml({ - resetContent: true + resetContent: true, + errorWhenNotFound: false }); } @@ -103,7 +104,8 @@ IonicTask.prototype.runCordova = function(cmdName) { setTimeout(function(){ // set it back to the original src after a few seconds self.setConfigXml({ - resetContent: true + resetContent: true, + errorWhenNotFound: true }); }, 5000); }); @@ -111,7 +113,8 @@ IonicTask.prototype.runCordova = function(cmdName) { process.on('exit', function(){ // verify it was set back self.setConfigXml({ - resetContent: true + resetContent: true, + errorWhenNotFound: false }); }); } @@ -156,12 +159,24 @@ IonicTask.prototype.setConfigXml = function(options) { try { var configXmlPath = path.resolve('config.xml'); + + if(!fs.existsSync(configXmlPath)) { + // working directory does not have the config.xml file + if(options.errorWhenNotFound) { + d.reject('Unable to locate config.xml file. Please ensure the working directory is at the root of the app where the config.xml should be located.'); + } else { + d.resolve(); + } + return d.promise; + } + var configString = fs.readFileSync(configXmlPath, { encoding: 'utf8' }); var parseString = xml2js.parseString; parseString(configString, function (err, jsonConfig) { if(err) { - return self.ionic.fail('Error parsing config.xml: ' + err); + d.reject(err); + return self.ionic.fail('Error parsing ' + configXmlPath + ': ' + err); } if(options.devServer) { @@ -193,7 +208,8 @@ IonicTask.prototype.setConfigXml = function(options) { }); } catch(e) { - return self.ionic.fail('Error updating config.xml file: ' + e); + d.reject(e); + self.ionic.fail('Error updating ' + configXmlPath + ': ' + e); } return d.promise; From ff1ee3f7af9aab9ce974a37893d30ec47e1464ec Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sat, 6 Sep 2014 22:34:42 -0500 Subject: [PATCH 239/850] improve IPv4 error handling --- lib/ionic/serve.js | 38 +++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 080d76fcd5..12cbd532e6 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -30,7 +30,7 @@ IonicTask.prototype.run = function(ionic) { if(self.isIpCmd) { console.log( self.ip ); - return; + process.exit(); } self.start(ionic); @@ -373,15 +373,18 @@ IonicTask.prototype.getIp = function(cb) { var os = require('os'); var ifaces = os.networkInterfaces(); - for (var dev in ifaces) { - ifaces[dev].forEach(function(details){ - if (details.family == 'IPv4' && !details.internal && details.address) { - addresses.push({ - ip: details.address, - dev: dev - }); - } - }); + if(ifaces){ + for (var dev in ifaces) { + if(!dev) continue; + ifaces[dev].forEach(function(details){ + if (details && details.family == 'IPv4' && !details.internal && details.address) { + addresses.push({ + ip: details.address, + dev: dev + }); + } + }); + } } if(addresses.length === 1) { @@ -393,7 +396,7 @@ IonicTask.prototype.getIp = function(cb) { console.log('Please select which address to use by entering its number from the list below:'.error.bold); for(var x=0; x Date: Sun, 7 Sep 2014 01:46:00 -0500 Subject: [PATCH 240/850] go to url live reload plugin --- lib/ionic/serve.js | 100 ++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 12cbd532e6..fd0e33f2d7 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -46,6 +46,7 @@ IonicTask.prototype.run = function(ionic) { IonicTask.prototype.loadSettings = function(cb) { var project = IonicProject.load(); + var self = this; this.port = this.port || argv.port || argv.p || DEFAULT_HTTP_PORT; this.liveReloadPort = this.liveReloadPort || argv.livereloadport || argv['livereload-port'] || argv.i || DEFAULT_LIVE_RELOAD_PORT; @@ -61,8 +62,21 @@ IonicTask.prototype.loadSettings = function(cb) { this.getIp(cb); process.stdin.on('readable', function() { - var chunk = process.stdin.read(); - if (chunk !== null && /exit|quit|close|stop/gi.test(chunk)) { + var input = process.stdin.read(); + if (input === null) return; + input = (input + '').trim();; + + if(input.toLowerCase() == 'restart') { + self._goToUrl('/'); + + } else if(input.toLowerCase().indexOf('goto ') === 0) { + var url = input.replace(/goto /i, ''); + self._goToUrl(url); + + } else if(input.match(/^go\([+-]?[0-9]{1,9}\)$/)) { + self._goToHistory(input); + + } else if(/exit|quit|close|stop/i.test(input)) { process.exit(); } }); @@ -177,11 +191,14 @@ IonicTask.prototype.start = function(ionic) { res.end(err.toString()); } else { self.serverLog(req.url + ' (' + self.contentSrc + ')'); + + var html = injectGoToScript( buf.toString('utf8') ); + if(self.printConsoleLogs) { - res.end( insertConsoleLogScript(buf.toString('utf8')) ); - } else { - res.end(buf); + html = injectConsoleLogScript(html); } + + res.end(html); } }); return; @@ -298,7 +315,7 @@ function getPlatformWWW(req) { } -function insertConsoleLogScript(html) { +function injectConsoleLogScript(html) { try{ var headTag = html.match(//gi)[0]; @@ -338,34 +355,97 @@ function insertConsoleLogScript(html) { return html; } + +function injectGoToScript(html) { + try{ + var headTag = html.match(//gi)[0]; + + return html.replace(headTag, headTag + '\n\ + '); + }catch(e){} + + return html; +} + + IonicTask.prototype._changed = function(filePath) { // Cleanup the path a bit var pwd = process.cwd(); filePath = filePath.replace(pwd + '/', ''); if( filePath.indexOf('.css') > 0 ) { - console.log( (' CSS changed: ' + filePath).green ); + console.log( ('CSS changed: ' + filePath).green ); } else if( filePath.indexOf('.js') > 0 ) { - console.log( (' JS changed: ' + filePath).green ); + console.log( ('JS changed: ' + filePath).green ); } else if( filePath.indexOf('.html') > 0 ) { console.log( ('HTML changed: ' + filePath).green ); } else { console.log( ('File changed: ' + filePath).green ); } - var req = request.post('http://localhost:' + this.liveReloadPort + '/changed', { + this._postToLiveReload( [filePath] ); +}; + + +IonicTask.prototype._goToUrl = function(url) { + console.log( ('Loading: ' + url).green ); + this._postToLiveReload( ['__ionic_goto_url__' + url] ); +}; + +IonicTask.prototype._goToHistory = function(goHistory) { + goHistory = goHistory.replace('go(', '').replace(')', ''); + console.log( ('History Go: ' + goHistory).green ); + this._postToLiveReload( ['__ionic_history_go__' + goHistory] ); +}; + + +IonicTask.prototype._postToLiveReload = function(files) { + + request.post('http://localhost:' + this.liveReloadPort + '/changed', { path: '/changed', method: 'POST', body: JSON.stringify({ - files: [filePath] + files: files }) }, function(err, res, body) { if(err) { console.error('Unable to update live reload:', err); } }); + }; + IonicTask.prototype.getIp = function(cb) { try { var self = this; diff --git a/package.json b/package.json index 32fc3377d1..43aa2f33b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.3-beta1", + "version": "1.2.3-beta2", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From e53dcab453c1cf56d8099993f6d9cc84ee9c54d6 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sun, 7 Sep 2014 20:34:51 -0500 Subject: [PATCH 241/850] index.html cache busting and `r` alias for `restart` --- lib/ionic/serve.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index fd0e33f2d7..b8889acc93 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -66,8 +66,8 @@ IonicTask.prototype.loadSettings = function(cb) { if (input === null) return; input = (input + '').trim();; - if(input.toLowerCase() == 'restart') { - self._goToUrl('/'); + if(input.toLowerCase() == 'restart' || input.toLowerCase() == 'r') { + self._goToUrl('/?restart=' + Math.floor((Math.random() * 899999) + 100000)); } else if(input.toLowerCase().indexOf('goto ') === 0) { var url = input.replace(/goto /i, ''); @@ -172,18 +172,13 @@ IonicTask.prototype.start = function(ionic) { return; } - if(self.printConsoleLogs) { - - if(req.url === '/__ionic-cli/console') { - self.consoleLog(req); - res.end(''); - return; - } - + if(self.printConsoleLogs && req.url === '/__ionic-cli/console') { + self.consoleLog(req); + res.end(''); + return; } - if(req.url === '/') { - + if(req.url.split('?')[0] === '/') { fs.readFile( path.resolve(self.contentSrc), 'utf8', function (err, buf) { res.setHeader('Content-Type', 'text/html'); if (err) { From 4476985af206fd3a6902ab55c38735e757908609 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Sun, 7 Sep 2014 22:08:41 -0500 Subject: [PATCH 242/850] improve server cmds, script placement, logs --- lib/ionic/serve.js | 89 ++++++++++++++++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 67 insertions(+), 24 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index b8889acc93..da02c70bff 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -54,8 +54,8 @@ IonicTask.prototype.loadSettings = function(cb) { this.launchBrowser = !argv.nobrowser && !argv.b; this.runLivereload = !argv.nolivereload && !argv.r; this.watchSass = project.get('sass') === true && !argv.nosass && !argv.n; - this.printServerLogs = argv.serverlogs || argv['server-logs'] || argv.s; this.printConsoleLogs = argv.consolelogs || argv['console-logs'] || argv.c; + this.printServerLogs = argv.serverlogs || argv['server-logs'] || argv.s; this.isIpCmd = argv._[0].toLowerCase() == 'ip'; this.contentSrc = path.join('www', this.ionic.getContentSrc()); @@ -64,24 +64,48 @@ IonicTask.prototype.loadSettings = function(cb) { process.stdin.on('readable', function() { var input = process.stdin.read(); if (input === null) return; - input = (input + '').trim();; + input = (input + '').trim(); if(input.toLowerCase() == 'restart' || input.toLowerCase() == 'r') { self._goToUrl('/?restart=' + Math.floor((Math.random() * 899999) + 100000)); - } else if(input.toLowerCase().indexOf('goto ') === 0) { - var url = input.replace(/goto /i, ''); + } else if(input.toLowerCase().indexOf('goto ') === 0 || input.toLowerCase().indexOf('g ') === 0) { + var url = input.replace('goto ', '').replace('g ', ''); self._goToUrl(url); - } else if(input.match(/^go\([+-]?[0-9]{1,9}\)$/)) { + } else if(input.toLowerCase() == 'consolelogs' || input.toLowerCase() == 'c') { + self.printConsoleLogs = !self.printConsoleLogs; + console.log('Console log output: '.green + (self.printConsoleLogs ? 'enabled' : 'disabled')); + + } else if(input.toLowerCase() == 'serverlogs' || input.toLowerCase() == 's') { + self.printServerLogs = !self.printServerLogs; + console.log('Server log output: '.green + (self.printServerLogs ? 'enabled' : 'disabled')); + + } else if(input.match(/^go\([+\-]?[0-9]{1,9}\)$/)) { self._goToHistory(input); } else if(/exit|quit|close|stop/i.test(input)) { process.exit(); + } else { + console.log('Invalid server command'.error.bold); + self.printCommandTips(); } + }); }; + +IonicTask.prototype.printCommandTips = function(ionic) { + console.log('Server commands, enter:'.green.bold); + console.log(' restart' + ' or '.green + 'r' + ' to restart the app from the root'.green); + console.log(' goto' + ' or '.green + 'g' + ' and a url to have the app navigate to the given url'.green); + console.log(' consolelogs' + ' or '.green + 'c' + ' to enable/disable console log output'.green); + console.log(' serverlogs' + ' or '.green + 's' + ' to enable/disable server log output'.green); + console.log(' exit' + ' to shutdown the server and exit'.green); + console.log(''); +}; + + IonicTask.prototype.start = function(ionic) { var self = this; var app = connect(); @@ -123,6 +147,7 @@ IonicTask.prototype.start = function(ionic) { var open = require('open'); open( self.host(self.port) ); } + self.printCommandTips(); } }); @@ -131,11 +156,6 @@ IonicTask.prototype.start = function(ionic) { })); } - if(this.printConsoleLogs) { - self.consoleServer = self.host(self.consoleLogPort); - - } - this.devServer = this.host(this.port); // Serve up the www folder by default @@ -155,17 +175,17 @@ IonicTask.prototype.start = function(ionic) { if (err) { res.end('// mocked cordova.js response to prevent 404 errors during development'); if(req.url == '/cordova.js') { - self.serverLog(req.url + ' (mocked)'); + self.serverLog(req, '(mocked)'); } else { - self.serverLog(req.url + ' (Error ' + platformWWW + ')'); + self.serverLog(req, '(Error ' + platformWWW + ')'); } } else { - self.serverLog(req.url + ' (' + platformWWW + ')'); + self.serverLog(req, '(' + platformWWW + ')'); res.end(buf); } }); } else { - self.serverLog(req.url + ' (mocked)'); + self.serverLog(req, '(mocked)'); res.setHeader('Content-Type', 'application/javascript'); res.end('// mocked cordova.js response to prevent 404 errors during development'); } @@ -182,10 +202,10 @@ IonicTask.prototype.start = function(ionic) { fs.readFile( path.resolve(self.contentSrc), 'utf8', function (err, buf) { res.setHeader('Content-Type', 'text/html'); if (err) { - self.serverLog(req.url + ' : ERROR!'); + self.serverLog(req, 'ERROR!'); res.end(err.toString()); } else { - self.serverLog(req.url + ' (' + self.contentSrc + ')'); + self.serverLog(req, '(' + self.contentSrc + ')'); var html = injectGoToScript( buf.toString('utf8') ); @@ -200,7 +220,7 @@ IonicTask.prototype.start = function(ionic) { } // root www directory file - self.serverLog(req.url); + self.serverLog(req); serve(req, res, done); }); @@ -212,9 +232,26 @@ IonicTask.prototype.start = function(ionic) { }; -IonicTask.prototype.serverLog = function(msg) { +IonicTask.prototype.serverLog = function(req, msg) { if(this.printServerLogs) { - console.log( ('serve ' + msg).yellow ); + var log = 'serve '.yellow; + + log += (req.url.length > 60 ? req.url.substr(0, 57) + '...' : req.url).yellow; + + if(msg) { + log += ' ' + msg.yellow; + } + + var ua = (req.headers && req.headers['user-agent'] || ''); + if(ua.indexOf('Android') > 0) { + log += ' Android'.small; + } else if(ua.indexOf('iPhone') > -1 || ua.indexOf('iPad') > -1 || ua.indexOf('iPod') > -1) { + log += ' iOS'.small; + } else if(ua.indexOf('Windows Phone') > -1) { + log += ' Windows Phone'.small; + } + + console.log(log); } }; @@ -312,9 +349,10 @@ function getPlatformWWW(req) { function injectConsoleLogScript(html) { try{ - var headTag = html.match(//gi)[0]; + var findTags = html.match(/])(.*?)>||/gi); + var insertAfter = findTags[ findTags.length - 1 ]; - return html.replace(headTag, headTag + '\n\ + return html.replace(insertAfter, insertAfter + '\n\ + + + + + + + +
+
+

iPhone 6

+ +
+
+
+
+

Android

+ +
+
+
+ + + diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 6beb5b9e7b..0d0095c5a9 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -54,6 +54,7 @@ IonicTask.prototype.loadSettings = function(cb) { this.liveReloadPort = this.liveReloadPort || argv.livereloadport || argv['livereload-port'] || argv.i || DEFAULT_LIVE_RELOAD_PORT; this.launchBrowser = !argv.nobrowser && !argv.b; + this.launchLab = this.launchBrowser && argv.lab; this.runLivereload = !argv.nolivereload && !argv.r; this.useProxy = !argv.noproxy && !argv.x; this.proxies = project.get('proxies') || []; @@ -164,7 +165,10 @@ IonicTask.prototype.start = function(ionic) { } else { console.log('Running live reload server:'.green.bold, self.liveReloadServer ); console.log('Watching :'.green.bold, self.watchPatterns); - if(self.launchBrowser) { + if(self.launchLab) { + var open = require('open'); + open( self.host(self.port) + '/lab' ); + } else if(self.launchBrowser) { var open = require('open'); open( self.host(self.port) ); } @@ -230,6 +234,17 @@ IonicTask.prototype.start = function(ionic) { return; } + if(req.url === '/lab') { + fs.readFile(path.resolve(path.join(__dirname, 'assets/preview.html')), function(err, buf) { + if(err) { + res.end('404'); + } + res.setHeader('Content-Type', 'text/html'); + res.end(buf); + }); + return; + } + if(req.url.split('?')[0] === '/') { fs.readFile( path.resolve(self.contentSrc), 'utf8', function (err, buf) { res.setHeader('Content-Type', 'text/html'); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 242cf60f8e..ceae9c9547 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -5,81 +5,98 @@ "archiver": { "version": "0.5.1", "from": "archiver@0.5.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.5.1.tgz", "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@~1.1.9", + "from": "readable-stream@1.1.13", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "zip-stream": { "version": "0.1.4", - "from": "zip-stream@~0.1.0", + "from": "zip-stream@0.1.4", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.1.4.tgz", "dependencies": { "readable-stream": { "version": "1.0.33-1", - "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "lodash.defaults": { "version": "2.4.1", - "from": "lodash.defaults@~2.4.1", + "from": "lodash.defaults@2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash.keys": { "version": "2.4.1", - "from": "lodash.keys@~2.4.1", + "from": "lodash.keys@2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "lodash._isnative@~2.4.1" + "from": "lodash._isnative@2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "lodash.isobject@~2.4.1" + "from": "lodash.isobject@2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" }, "lodash._shimkeys": { "version": "2.4.1", - "from": "lodash._shimkeys@~2.4.1" + "from": "lodash._shimkeys@2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz" } } }, "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@~2.4.1" + "from": "lodash._objecttypes@2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } } @@ -87,28 +104,33 @@ }, "lazystream": { "version": "0.1.0", - "from": "lazystream@~0.1.0", + "from": "lazystream@0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", "dependencies": { "readable-stream": { "version": "1.0.33-1", - "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } } @@ -116,39 +138,48 @@ }, "file-utils": { "version": "0.1.5", - "from": "file-utils@~0.1.5", + "from": "file-utils@0.1.5", + "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", "dependencies": { "lodash": { "version": "2.1.0", - "from": "lodash@~2.1.0" + "from": "lodash@2.1.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz" }, "iconv-lite": { "version": "0.2.11", - "from": "iconv-lite@~0.2.11" + "from": "iconv-lite@0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" }, "rimraf": { "version": "2.2.8", - "from": "rimraf@~2.2.2" + "from": "rimraf@2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "glob": { "version": "3.2.11", - "from": "glob@~3.2.6", + "from": "glob@3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@0.3", + "from": "minimatch@0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2" + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0" + "from": "sigmund@1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } } @@ -156,58 +187,65 @@ }, "minimatch": { "version": "0.2.14", - "from": "minimatch@~0.2.12", + "from": "minimatch@0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2" + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0" + "from": "sigmund@1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "findup-sync": { "version": "0.1.3", - "from": "findup-sync@~0.1.2", + "from": "findup-sync@0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "lodash": { "version": "2.4.1", - "from": "lodash@~2.4.1" + "from": "lodash@2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "isbinaryfile": { "version": "0.1.9", - "from": "isbinaryfile@~0.1.9" + "from": "isbinaryfile@0.1.9", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz" } } }, "lodash": { "version": "2.4.1", - "from": "lodash@~2.4.1" + "from": "lodash@2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "colors": { "version": "0.6.2", - "from": "colors@0.6.2", + "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "connect": { "version": "3.1.1", - "from": "connect@3.1.1", + "from": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", "resolved": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", "dependencies": { "debug": { "version": "1.0.4", - "from": "debug@1.0.4", + "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -215,127 +253,626 @@ "finalhandler": { "version": "0.1.0", "from": "finalhandler@0.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.1.0.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1" + "from": "escape-html@1.0.1", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "parseurl": { "version": "1.3.0", - "from": "parseurl@~1.3.0" + "from": "parseurl@1.3.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "connect-livereload": { "version": "0.4.0", - "from": "connect-livereload@0.4.0" + "from": "connect-livereload@0.4.0", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.4.0.tgz" }, "cross-spawn": { "version": "0.2.3", - "from": "cross-spawn@0.2.3", + "from": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@^2.5.0" + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" } } }, "event-stream": { "version": "3.0.20", - "from": "event-stream@3.0.x", + "from": "event-stream@3.0.20", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "dependencies": { "through": { "version": "2.3.6", - "from": "through@~2.3.1" + "from": "through@2.3.6", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" }, "duplexer": { "version": "0.1.1", - "from": "duplexer@~0.1.1" + "from": "duplexer@0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" }, "from": { "version": "0.1.3", - "from": "from@~0" + "from": "from@0.1.3", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz" }, "map-stream": { "version": "0.0.4", - "from": "map-stream@~0.0.3" + "from": "map-stream@0.0.4", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz" }, "pause-stream": { "version": "0.0.11", - "from": "pause-stream@0.0.11" + "from": "pause-stream@0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz" }, "split": { "version": "0.2.10", - "from": "split@0.2" + "from": "split@0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz" }, "stream-combiner": { "version": "0.0.4", - "from": "stream-combiner@~0.0.3" + "from": "stream-combiner@0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" } } }, "finalhandler": { "version": "0.2.0", - "from": "finalhandler@0.2.0", + "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "dependencies": { "debug": { "version": "2.0.0", - "from": "debug@~2.0.0", + "from": "debug@2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } }, "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1" + "from": "escape-html@1.0.1", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" } } }, "form-data": { "version": "0.1.4", - "from": "form-data@0.1.4", + "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { "version": "0.0.5", - "from": "combined-stream@~0.0.4", + "from": "combined-stream@0.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.5.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", - "from": "delayed-stream@0.0.5" + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" } } }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.9" + "from": "mime@1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "async": { "version": "0.9.0", - "from": "async@~0.9.0" + "from": "async@0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "gulp": { + "version": "3.8.10", + "from": "gulp@", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.8.10.tgz", + "dependencies": { + "archy": { + "version": "1.0.0", + "from": "archy@^1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" + }, + "chalk": { + "version": "0.5.1", + "from": "chalk@^0.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "dependencies": { + "ansi-styles": { + "version": "1.1.0", + "from": "ansi-styles@^1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" + }, + "escape-string-regexp": { + "version": "1.0.2", + "from": "escape-string-regexp@^1.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" + }, + "has-ansi": { + "version": "0.1.0", + "from": "has-ansi@^0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "from": "ansi-regex@^0.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + } + } + }, + "strip-ansi": { + "version": "0.3.0", + "from": "strip-ansi@^0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "from": "ansi-regex@^0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" + } + } + }, + "supports-color": { + "version": "0.2.0", + "from": "supports-color@^0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" + } + } + }, + "deprecated": { + "version": "0.0.1", + "from": "deprecated@^0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz" + }, + "gulp-util": { + "version": "3.0.1", + "from": "gulp-util@^3.0.0", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.1.tgz", + "dependencies": { + "dateformat": { + "version": "1.0.11", + "from": "dateformat@^1.0.7-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", + "dependencies": { + "get-stdin": { + "version": "3.0.2", + "from": "get-stdin@*", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-3.0.2.tgz" + }, + "meow": { + "version": "2.0.0", + "from": "meow@*", + "resolved": "https://registry.npmjs.org/meow/-/meow-2.0.0.tgz", + "dependencies": { + "camelcase-keys": { + "version": "1.0.0", + "from": "camelcase-keys@^1.0.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", + "dependencies": { + "camelcase": { + "version": "1.0.2", + "from": "camelcase@^1.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" + }, + "map-obj": { + "version": "1.0.0", + "from": "map-obj@^1.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" + } + } + }, + "indent-string": { + "version": "1.2.0", + "from": "indent-string@^1.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.0.tgz", + "dependencies": { + "repeating": { + "version": "1.1.0", + "from": "repeating@^1.1.0", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.0.tgz", + "dependencies": { + "is-finite": { + "version": "1.0.0", + "from": "is-finite@^1.0.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" + }, + "meow": { + "version": "1.0.0", + "from": "meow@^1.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-1.0.0.tgz" + } + } + } + } + }, + "object-assign": { + "version": "1.0.0", + "from": "object-assign@^1.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" + } + } + } + } + }, + "lodash": { + "version": "2.4.1", + "from": "lodash@^2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "from": "lodash._reinterpolate@^2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz" + }, + "lodash.template": { + "version": "2.4.1", + "from": "lodash.template@^2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "dependencies": { + "lodash.defaults": { + "version": "2.4.1", + "from": "lodash.defaults@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "dependencies": { + "lodash._objecttypes": { + "version": "2.4.1", + "from": "lodash._objecttypes@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" + } + } + }, + "lodash.escape": { + "version": "2.4.1", + "from": "lodash.escape@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "dependencies": { + "lodash._escapehtmlchar": { + "version": "2.4.1", + "from": "lodash._escapehtmlchar@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "dependencies": { + "lodash._htmlescapes": { + "version": "2.4.1", + "from": "lodash._htmlescapes@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" + } + } + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "from": "lodash._reunescapedhtml@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "dependencies": { + "lodash._htmlescapes": { + "version": "2.4.1", + "from": "lodash._htmlescapes@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" + } + } + } + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "from": "lodash._escapestringchar@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz" + }, + "lodash.keys": { + "version": "2.4.1", + "from": "lodash.keys@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "dependencies": { + "lodash._isnative": { + "version": "2.4.1", + "from": "lodash._isnative@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" + }, + "lodash.isobject": { + "version": "2.4.1", + "from": "lodash.isobject@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "dependencies": { + "lodash._objecttypes": { + "version": "2.4.1", + "from": "lodash._objecttypes@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" + } + } + }, + "lodash._shimkeys": { + "version": "2.4.1", + "from": "lodash._shimkeys@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "dependencies": { + "lodash._objecttypes": { + "version": "2.4.1", + "from": "lodash._objecttypes@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" + } + } + } + } + }, + "lodash.templatesettings": { + "version": "2.4.1", + "from": "lodash.templatesettings@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz" + }, + "lodash.values": { + "version": "2.4.1", + "from": "lodash.values@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" + } + } + }, + "multipipe": { + "version": "0.1.2", + "from": "multipipe@^0.1.0", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "from": "duplexer2@0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "dependencies": { + "readable-stream": { + "version": "1.1.13", + "from": "readable-stream@~1.1.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + } + } + }, + "through2": { + "version": "0.6.3", + "from": "through2@^0.6.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "dependencies": { + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "xtend": { + "version": "4.0.0", + "from": "xtend@>=4.0.0 <4.1.0-0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" + } + } + }, + "vinyl": { + "version": "0.4.6", + "from": "vinyl@^0.4.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "dependencies": { + "clone": { + "version": "0.2.0", + "from": "clone@^0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" + }, + "clone-stats": { + "version": "0.0.1", + "from": "clone-stats@^0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + } + } + } + }, + "interpret": { + "version": "0.3.8", + "from": "interpret@^0.3.2", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.3.8.tgz" + }, + "liftoff": { + "version": "0.13.6", + "from": "liftoff@^0.13.2", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-0.13.6.tgz", + "dependencies": { + "findup-sync": { + "version": "0.1.3", + "from": "findup-sync@~0.1.2", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "dependencies": { + "glob": { + "version": "3.2.11", + "from": "glob@~3.2.9", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "dependencies": { + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "minimatch": { + "version": "0.3.0", + "from": "minimatch@0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@~1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + } + } + }, + "lodash": { + "version": "2.4.1", + "from": "lodash@~2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" + } + } + }, + "resolve": { + "version": "1.0.0", + "from": "resolve@~1.0.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.0.0.tgz" + }, + "extend": { + "version": "1.3.0", + "from": "extend@~1.3.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz" + }, + "flagged-respawn": { + "version": "0.3.1", + "from": "flagged-respawn@~0.3.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz" + } + } + }, + "minimist": { + "version": "1.1.0", + "from": "minimist@^1.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" + }, + "orchestrator": { + "version": "0.3.7", + "from": "orchestrator@^0.3.0", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "from": "end-of-stream@~0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "dependencies": { + "once": { + "version": "1.3.1", + "from": "once@~1.3.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@1", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + } + } + }, + "sequencify": { + "version": "0.0.7", + "from": "sequencify@~0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz" + }, + "stream-consume": { + "version": "0.1.0", + "from": "stream-consume@~0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" + } + } + }, + "pretty-hrtime": { + "version": "0.2.2", + "from": "pretty-hrtime@^0.2.0", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz" + }, + "semver": { + "version": "4.1.0", + "from": "semver@^4.1.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.1.0.tgz" + }, + "tildify": { + "version": "1.0.0", + "from": "tildify@^1.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", + "dependencies": { + "user-home": { + "version": "1.1.0", + "from": "user-home@^1.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.0.tgz" + } + } + }, + "v8flags": { + "version": "1.0.5", + "from": "v8flags@^1.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-1.0.5.tgz" } } }, "ncp": { "version": "0.4.2", - "from": "ncp@0.4.2" + "from": "ncp@0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz" }, "npm": { "version": "2.1.3", - "from": "npm@2.1.3", + "from": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", "resolved": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", "dependencies": { "abbrev": { @@ -899,315 +1436,369 @@ }, "open": { "version": "0.0.5", - "from": "open@0.0.5", + "from": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz" }, "optimist": { "version": "0.6.0", - "from": "optimist@0.6.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "wordwrap@~0.0.2" + "from": "wordwrap@0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@~0.0.1" + "from": "minimist@0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } }, "progress": { "version": "1.1.7", - "from": "progress@1.1.7" + "from": "progress@1.1.7", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.7.tgz" }, "prompt": { "version": "0.2.12", - "from": "prompt@0.2.12", + "from": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", "dependencies": { "pkginfo": { "version": "0.3.0", - "from": "pkginfo@0.x.x" + "from": "pkginfo@0.3.0", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "read": { "version": "1.0.5", - "from": "read@1.0.x", + "from": "read@1.0.5", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.5.tgz", "dependencies": { "mute-stream": { "version": "0.0.4", - "from": "mute-stream@~0.0.4" + "from": "mute-stream@0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" } } }, "revalidator": { "version": "0.1.8", - "from": "revalidator@0.1.x" + "from": "revalidator@0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz" }, "utile": { "version": "0.2.1", - "from": "utile@0.2.x", + "from": "utile@0.2.1", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "async@~0.2.9" + "from": "async@0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "deep-equal": { "version": "0.2.1", - "from": "deep-equal@*" + "from": "deep-equal@0.2.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.1.tgz" }, "i": { "version": "0.3.2", - "from": "i@0.3.x" + "from": "i@0.3.2", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.2.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.x.x", + "from": "mkdirp@0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@2.x.x" + "from": "rimraf@2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "winston": { "version": "0.6.2", - "from": "winston@0.6.x", + "from": "winston@0.6.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz", "dependencies": { "async": { "version": "0.1.22", - "from": "async@0.1.x" + "from": "async@0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" }, "cycle": { "version": "1.0.3", - "from": "cycle@1.0.x" + "from": "cycle@1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz" }, "eyes": { "version": "0.1.8", - "from": "eyes@0.1.x" + "from": "eyes@0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" }, "pkginfo": { "version": "0.2.3", - "from": "pkginfo@0.2.x" + "from": "pkginfo@0.2.3", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz" }, "request": { "version": "2.9.203", - "from": "request@2.9.x" + "from": "request@2.9.203", + "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz" }, "stack-trace": { "version": "0.0.9", - "from": "stack-trace@0.0.x" + "from": "stack-trace@0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } } } }, + "proxy-middleware": { + "version": "0.7.0", + "from": "proxy-middleware@0.7.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.7.0.tgz" + }, "q": { "version": "1.0.1", - "from": "q@1.0.1", + "from": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz" }, "request": { "version": "2.27.0", - "from": "request@2.27.0", + "from": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", "resolved": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", "dependencies": { "qs": { "version": "0.6.6", - "from": "qs@~0.6.0" + "from": "qs@0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@~5.0.0" + "from": "json-stringify-safe@5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@~0.5.0" + "from": "forever-agent@0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "tunnel-agent": { "version": "0.3.0", - "from": "tunnel-agent@~0.3.0" + "from": "tunnel-agent@0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" }, "http-signature": { "version": "0.10.0", - "from": "http-signature@~0.10.0", + "from": "http-signature@0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", "dependencies": { "assert-plus": { "version": "0.1.2", - "from": "assert-plus@0.1.2", + "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" }, "asn1": { "version": "0.1.11", - "from": "asn1@0.1.11", + "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.2", - "from": "ctype@0.5.2" + "from": "ctype@0.5.2", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz" } } }, "hawk": { "version": "1.0.0", - "from": "hawk@~1.0.0", + "from": "hawk@1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "hoek@0.9.x" + "from": "hoek@0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "boom@0.4.x" + "from": "boom@0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@0.2.x" + "from": "cryptiles@0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@0.2.x" + "from": "sntp@0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign": { "version": "0.3.0", - "from": "aws-sign@~0.3.0" + "from": "aws-sign@0.3.0", + "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz" }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@~0.3.0" + "from": "oauth-sign@0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "cookie-jar": { "version": "0.3.0", - "from": "cookie-jar@~0.3.0" + "from": "cookie-jar@0.3.0", + "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz" }, "node-uuid": { "version": "1.4.1", - "from": "node-uuid@~1.4.0" + "from": "node-uuid@1.4.1", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@1.2.11" + "from": "mime@1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } }, "serve-static": { "version": "1.6.1", - "from": "serve-static@1.6.1", + "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.1.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.1.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1" + "from": "escape-html@1.0.1", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "parseurl": { "version": "1.3.0", - "from": "parseurl@~1.3.0" + "from": "parseurl@1.3.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "send": { "version": "0.9.1", - "from": "send@0.9.1", + "from": "https://registry.npmjs.org/send/-/send-0.9.1.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.9.1.tgz", "dependencies": { "debug": { "version": "2.0.0", - "from": "debug@~2.0.0" + "from": "debug@2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz" }, "depd": { "version": "0.4.4", - "from": "depd@0.4.4" + "from": "depd@0.4.4", + "resolved": "https://registry.npmjs.org/depd/-/depd-0.4.4.tgz" }, "destroy": { "version": "1.0.3", - "from": "destroy@1.0.3" + "from": "destroy@1.0.3", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "etag": { "version": "1.3.1", - "from": "etag@~1.3.0", + "from": "https://registry.npmjs.org/etag/-/etag-1.3.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.3.1.tgz", "dependencies": { "crc": { "version": "3.0.0", - "from": "crc@3.0.0", + "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" } } }, "fresh": { "version": "0.2.4", - "from": "fresh@0.2.4", + "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@1.2.11" + "from": "mime@1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" }, "on-finished": { "version": "2.1.0", "from": "on-finished@2.1.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", "dependencies": { "ee-first": { "version": "1.0.5", - "from": "ee-first@1.0.5" + "from": "ee-first@1.0.5", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" } } }, "range-parser": { "version": "1.0.2", - "from": "range-parser@~1.0.0", + "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "shelljs": { "version": "0.2.6", - "from": "shelljs@0.2.6", + "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz" }, "tiny-lr-fork": { "version": "0.0.5", - "from": "tiny-lr-fork@0.0.5", + "from": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", "resolved": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", "dependencies": { "qs": { "version": "0.5.6", - "from": "qs@~0.5.2" + "from": "qs@0.5.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" }, "faye-websocket": { "version": "0.4.4", - "from": "faye-websocket@~0.4.3" + "from": "faye-websocket@0.4.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz" }, "noptify": { "version": "0.0.3", - "from": "noptify@~0.0.3", + "from": "noptify@0.0.3", + "resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz", "dependencies": { "nopt": { "version": "2.0.0", - "from": "nopt@~2.0.0", + "from": "nopt@2.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz", "dependencies": { "abbrev": { "version": "1.0.5", - "from": "abbrev@1" + "from": "abbrev@1.0.5", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" } } } @@ -1215,115 +1806,132 @@ }, "debug": { "version": "0.7.4", - "from": "debug@~0.7.0" + "from": "debug@0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" } } }, "unzip": { "version": "0.1.9", - "from": "unzip@0.1.9", + "from": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", "dependencies": { "fstream": { "version": "0.1.31", - "from": "fstream@~0.1.21", + "from": "fstream@0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "dependencies": { "graceful-fs": { "version": "3.0.4", - "from": "graceful-fs@~3.0.2", + "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.0" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.5", + "from": "mkdirp@0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@2" + "from": "rimraf@2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "pullstream": { "version": "0.4.1", - "from": "pullstream@~0.4.0", + "from": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "dependencies": { "over": { "version": "0.0.5", - "from": "over@>= 0.0.5 < 1" + "from": "over@0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz" }, "slice-stream": { "version": "1.0.0", - "from": "slice-stream@>= 1.0.0 < 2", + "from": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" } } }, "binary": { "version": "0.3.0", - "from": "binary@~0.3.0", + "from": "binary@0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "dependencies": { "chainsaw": { "version": "0.1.0", - "from": "chainsaw@~0.1.0", + "from": "chainsaw@0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "dependencies": { "traverse": { "version": "0.3.9", - "from": "traverse@>=0.3.0 <0.4" + "from": "traverse@0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } } }, "buffers": { "version": "0.1.1", - "from": "buffers@~0.1.1" + "from": "buffers@0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } }, "readable-stream": { "version": "1.0.33-1", - "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "setimmediate": { "version": "1.0.2", - "from": "setimmediate@~1.0.1" + "from": "setimmediate@1.0.2", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.2.tgz" }, "match-stream": { "version": "0.0.2", - "from": "match-stream@~0.0.2", + "from": "match-stream@0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "dependencies": { "buffers": { "version": "0.1.1", - "from": "buffers@~0.1.1" + "from": "buffers@0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } } @@ -1331,28 +1939,33 @@ }, "vinyl-fs": { "version": "0.3.7", - "from": "vinyl-fs@0.3.7", + "from": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", "dependencies": { "glob-stream": { "version": "3.1.15", - "from": "glob-stream@^3.1.5", + "from": "glob-stream@3.1.15", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.15.tgz", "dependencies": { "glob": { "version": "4.0.6", - "from": "glob@^4.0.0", + "from": "glob@4.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "once": { "version": "1.3.1", - "from": "once@^1.3.0", + "from": "once@1.3.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@1" + "from": "wrappy@1.0.1", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } } @@ -1360,73 +1973,89 @@ }, "minimatch": { "version": "1.0.0", - "from": "minimatch@^1.0.0", + "from": "minimatch@1.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2" + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0" + "from": "sigmund@1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "ordered-read-streams": { "version": "0.0.8", - "from": "ordered-read-streams@0.0.8" + "from": "ordered-read-streams@0.0.8", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.0.8.tgz" }, "glob2base": { "version": "0.0.11", - "from": "glob2base@^0.0.11" + "from": "glob2base@0.0.11", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.11.tgz" }, "unique-stream": { "version": "1.0.0", - "from": "unique-stream@^1.0.0" + "from": "unique-stream@1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" } } }, "glob-watcher": { "version": "0.0.6", - "from": "glob-watcher@^0.0.6", + "from": "glob-watcher@0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "dependencies": { "gaze": { "version": "0.5.1", - "from": "gaze@^0.5.1", + "from": "gaze@0.5.1", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz", "dependencies": { "globule": { "version": "0.1.0", - "from": "globule@~0.1.0", + "from": "globule@0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "dependencies": { "lodash": { "version": "1.0.1", - "from": "lodash@~1.0.1" + "from": "lodash@1.0.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.1.tgz" }, "glob": { "version": "3.1.21", - "from": "glob@~3.1.21", + "from": "glob@3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "dependencies": { "graceful-fs": { "version": "1.2.3", - "from": "graceful-fs@~1.2.0" + "from": "graceful-fs@1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, "inherits": { "version": "1.0.0", - "from": "inherits@1" + "from": "inherits@1.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz" } } }, "minimatch": { "version": "0.2.14", - "from": "minimatch@~0.2.11", + "from": "minimatch@0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2" + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0" + "from": "sigmund@1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } } @@ -1438,79 +2067,91 @@ }, "graceful-fs": { "version": "3.0.4", - "from": "graceful-fs@^3.0.0", + "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" }, "lodash": { "version": "2.4.1", - "from": "lodash@~2.4.1" + "from": "lodash@2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.x.x", + "from": "mkdirp@0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "strip-bom": { "version": "1.0.0", - "from": "strip-bom@^1.0.0", + "from": "strip-bom@1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "dependencies": { "first-chunk-stream": { "version": "1.0.0", - "from": "first-chunk-stream@^1.0.0" + "from": "first-chunk-stream@1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" }, "is-utf8": { "version": "0.2.0", - "from": "is-utf8@^0.2.0" + "from": "is-utf8@0.2.0", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz" } } }, "through2": { "version": "0.6.3", - "from": "through2@^0.6.1", + "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { "version": "1.0.33-1", - "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0" + "from": "core-util-is@1.0.1", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x" + "from": "string_decoder@0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "xtend@>=4.0.0 <4.1.0-0" + "from": "xtend@4.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { "version": "0.4.3", - "from": "vinyl@^0.4.0", + "from": "vinyl@0.4.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.3.tgz", "dependencies": { "clone-stats": { "version": "0.0.1", - "from": "clone-stats@^0.0.1" + "from": "clone-stats@0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } } @@ -1519,19 +2160,22 @@ "xml2js": { "version": "0.4.4", "from": "xml2js@0.4.4", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", "dependencies": { "sax": { "version": "0.6.1", - "from": "sax@0.6.x", + "from": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz" }, "xmlbuilder": { "version": "2.4.4", - "from": "xmlbuilder@>=1.0.0", + "from": "xmlbuilder@2.4.4", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.4.tgz", "dependencies": { "lodash-node": { "version": "2.4.1", - "from": "lodash-node@~2.4.1" + "from": "lodash-node@2.4.1", + "resolved": "https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz" } } } From 3d077f76860f009eb467df0c34c47b5b0b52bad4 Mon Sep 17 00:00:00 2001 From: jbavari Date: Mon, 8 Dec 2014 16:53:49 -0700 Subject: [PATCH 301/850] Making the document easier to understand for proxying. Updated the options to be proxyUrl, as well as updating that value in serve.js --- README.md | 33 +++++++++++++++++++++++++++------ lib/ionic/serve.js | 4 ++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7108381aff..403ed5a361 100644 --- a/README.md +++ b/README.md @@ -61,11 +61,12 @@ $ ionic serve [options] __Proxies:__ -The `serve` command can add some proxies to the http server. This proxies are useful if your are developing in the browser and you need to make calls to an external API. With this feature you can proxy request to the external api through the ionic http server preventing the `No 'Access-Control-Allow-Origin' header is present on the requested resource` error. +The `serve` command can add some proxies to the http server. These proxies are useful if you are developing in the browser and you need to make calls to an external API. With this feature you can proxy request to the external api through the ionic http server preventing the `No 'Access-Control-Allow-Origin' header is present on the requested resource` error. In the `ionic.project` file you can add a property with an array of proxies you want to add. The proxies are object with two properties: -Say you want to intercept all calls to your server `http://localhost:8100/api` to go instead to `http://my.server.com/api` - use the following configuration: +* `path`: string that will be matched against the beginning of the incoming request URL. +* `proxyUrl`: a string with the url of where the proxied request should go. ```json { @@ -74,17 +75,37 @@ Say you want to intercept all calls to your server `http://localhost:8100/api` t "app_id": "", "proxies": [ { - "path": "/api", - "options": "http://my.server.com/api" + "path": "/v1", + "proxyUrl": "https://api.instagram.com/v1" } ] } ``` -* `path`: string that will be matched against after the host in the request URL (for example, the `/api` in `http://localhost:8100/api`) -* `options`: a string of the address to proxy to. Allows any options that are permitted on the [http](http://nodejs.org/api/http.html#http_http_request_options_callback) request options. +Using the above configuration, you can now make requests to your local server at `http://localhost:8100/v1` to have it proxy out requests to `https://api.instagram.com/v1` +For example: + +```js +angular.module('starter.controllers', []) +.constant('InstagramApiUrl', '') +// .contant('InstagramApiUrl','https://api.instagram.com') +//In production, make this the real URL + +.controller('FeedCtrl', function($scope, $http, InstagramApiUrl) { + + $scope.feed = null; + + $http.get(InstagramApiUrl + '/v1/media/search?client_id=1&lat=48&lng=2.294351').then(function(data) { + console.log('data ' , data) + $scope.feed = data; + }) + +}) +``` + +See also [this gist](https://gist.github.com/jbavari/d9c1c94058c4fdd4e935) for more help. __Command-line flags/options:__ diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 0d0095c5a9..73edccef4a 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -186,8 +186,8 @@ IonicTask.prototype.start = function(ionic) { for(var x=0; x " + url.format(proxy.options)); + app.use(proxy.path, proxyMiddleware(url.parse(proxy.proxyUrl))); + console.log('Proxy added:'.green.bold, proxy.path + " => " + url.format(proxy.proxyUrl)); } } From 03855c011a8a57d1caa4685cdc30a280a0a5742c Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 8 Dec 2014 18:09:40 -0600 Subject: [PATCH 302/850] Fallback platform override --- lib/ionic/serve.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 0d0095c5a9..d64824bf6b 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -12,7 +12,7 @@ var fs = require('fs'), IonicProject = require('./project'), Task = require('./task').Task, proxyMiddleware = require('proxy-middleware'), - url = require('url'); + url = require('url'), IonicStats = require('./stats').IonicStats; var DEFAULT_HTTP_PORT = 8100; @@ -201,6 +201,9 @@ IonicTask.prototype.start = function(ionic) { var server = http.createServer(function(req, res){ var done = finalhandler(req, res); + var urlParsed = url.parse(req.url, true); + var platformOverride = urlParsed.query.ionicplatform; + var platformUrl = getPlatformUrl(req); if(platformUrl) { var platformWWW = getPlatformWWW(req); @@ -260,6 +263,10 @@ IonicTask.prototype.start = function(ionic) { html = injectConsoleLogScript(html); } + if(platformOverride) { + html = injectPlatformScript( html, platformOverride ); + } + res.end(html); } }); @@ -494,6 +501,24 @@ function injectGoToScript(html) { return html; } +/** + * Inject the platform override for choosing Android or iOS during + * development. + */ +function injectPlatformScript(html, platformOverride) { + try { + var findTags = html.toLowerCase().indexOf(''); + if(findTags < 0) { return html; } + + return html.slice(0, findTags) + '\n' + + '\n' + + html.slice(findTags); + } catch(e) {} + + return html; +} IonicTask.prototype._changed = function(filePath) { // Cleanup the path a bit From ce1565d216950cb28bcff780a063934c6edcc126 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 8 Dec 2014 18:15:36 -0600 Subject: [PATCH 303/850] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 403ed5a361..f8d807c0ca 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Use `ionic serve` to start a local development server for app dev and testing. T $ ionic serve [options] ``` -__Proxies:__ +__Service Proxies:__ The `serve` command can add some proxies to the http server. These proxies are useful if you are developing in the browser and you need to make calls to an external API. With this feature you can proxy request to the external api through the ionic http server preventing the `No 'Access-Control-Allow-Origin' header is present on the requested resource` error. From 4c94afcc4aa3f49bf69591ac0d43704bf66b0399 Mon Sep 17 00:00:00 2001 From: jbavari Date: Mon, 8 Dec 2014 17:37:24 -0700 Subject: [PATCH 304/850] Bumping version to 1.2.9, adding myself as maintainer --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 36033a77cf..5dfa933b4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.8", + "version": "1.2.9", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", @@ -35,6 +35,11 @@ { "name": "Adam Bradley", "web": "https://twitter.com/adamdbradley" + }, + { + "name": "Josh Bavari", + "web": "https://twitter.com/jbavari", + "email": "josh@drifty.com" } ], "license": "MIT", From 674df4906a091305edcfcdc545e37030ebcd43fa Mon Sep 17 00:00:00 2001 From: jbavari Date: Mon, 8 Dec 2014 17:39:45 -0700 Subject: [PATCH 305/850] Shrinkwrapped --- npm-shrinkwrap.json | 663 +++++++++++++++++++++++--------------------- 1 file changed, 347 insertions(+), 316 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index ceae9c9547..f36e3667be 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.8", + "version": "1.2.9", "dependencies": { "archiver": { "version": "0.5.1", @@ -9,12 +9,12 @@ "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@1.1.13", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -24,29 +24,29 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "zip-stream": { "version": "0.1.4", - "from": "zip-stream@0.1.4", + "from": "zip-stream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.1.4.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33-1", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "version": "1.0.33", + "from": "readable-stream@>=1.0.24 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -56,46 +56,46 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "lodash.defaults": { "version": "2.4.1", - "from": "lodash.defaults@2.4.1", + "from": "lodash.defaults@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash.keys": { "version": "2.4.1", - "from": "lodash.keys@2.4.1", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "lodash._isnative@2.4.1", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "lodash.isobject@2.4.1", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" }, "lodash._shimkeys": { "version": "2.4.1", - "from": "lodash._shimkeys@2.4.1", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz" } } }, "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@2.4.1", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -104,17 +104,17 @@ }, "lazystream": { "version": "0.1.0", - "from": "lazystream@0.1.0", + "from": "lazystream@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33-1", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "version": "1.0.33", + "from": "readable-stream@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -124,12 +124,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -138,47 +138,47 @@ }, "file-utils": { "version": "0.1.5", - "from": "file-utils@0.1.5", + "from": "file-utils@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", "dependencies": { "lodash": { "version": "2.1.0", - "from": "lodash@2.1.0", + "from": "lodash@>=2.1.0 <2.2.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz" }, "iconv-lite": { "version": "0.2.11", - "from": "iconv-lite@0.2.11", + "from": "iconv-lite@>=0.2.11 <0.3.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" }, "rimraf": { "version": "2.2.8", - "from": "rimraf@2.2.8", + "from": "rimraf@>=2.2.2 <2.3.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "glob": { "version": "3.2.11", - "from": "glob@3.2.11", + "from": "glob@>=3.2.6 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@0.3.0", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2.5.0", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -187,65 +187,65 @@ }, "minimatch": { "version": "0.2.14", - "from": "minimatch@0.2.14", + "from": "minimatch@>=0.2.12 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2.5.0", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "findup-sync": { "version": "0.1.3", - "from": "findup-sync@0.1.3", + "from": "findup-sync@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "lodash": { "version": "2.4.1", - "from": "lodash@2.4.1", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "isbinaryfile": { "version": "0.1.9", - "from": "isbinaryfile@0.1.9", + "from": "isbinaryfile@>=0.1.9 <0.2.0", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz" } } }, "lodash": { "version": "2.4.1", - "from": "lodash@2.4.1", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "colors": { "version": "0.6.2", - "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "from": "colors@0.6.2", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "connect": { "version": "3.1.1", - "from": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", + "from": "connect@3.1.1", "resolved": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", "dependencies": { "debug": { "version": "1.0.4", - "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", + "from": "debug@1.0.4", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -264,12 +264,12 @@ }, "parseurl": { "version": "1.3.0", - "from": "parseurl@1.3.0", + "from": "parseurl@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } @@ -281,40 +281,40 @@ }, "cross-spawn": { "version": "0.2.3", - "from": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", + "from": "cross-spawn@0.2.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2.5.0", + "from": "lru-cache@>=2.5.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" } } }, "event-stream": { "version": "3.0.20", - "from": "event-stream@3.0.20", + "from": "event-stream@>=3.0.0 <3.1.0", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "dependencies": { "through": { "version": "2.3.6", - "from": "through@2.3.6", + "from": "through@>=2.3.1 <2.4.0", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" }, "duplexer": { "version": "0.1.1", - "from": "duplexer@0.1.1", + "from": "duplexer@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" }, "from": { "version": "0.1.3", - "from": "from@0.1.3", + "from": "from@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz" }, "map-stream": { - "version": "0.0.4", - "from": "map-stream@0.0.4", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz" + "version": "0.0.5", + "from": "map-stream@>=0.0.3 <0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.5.tgz" }, "pause-stream": { "version": "0.0.11", @@ -323,29 +323,29 @@ }, "split": { "version": "0.2.10", - "from": "split@0.2.10", + "from": "split@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz" }, "stream-combiner": { "version": "0.0.4", - "from": "stream-combiner@0.0.4", + "from": "stream-combiner@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" } } }, "finalhandler": { "version": "0.2.0", - "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", + "from": "finalhandler@0.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "dependencies": { "debug": { "version": "2.0.0", - "from": "debug@2.0.0", + "from": "debug@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -359,13 +359,13 @@ }, "form-data": { "version": "0.1.4", - "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "from": "form-data@0.1.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { - "version": "0.0.5", - "from": "combined-stream@0.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.5.tgz", + "version": "0.0.7", + "from": "combined-stream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", @@ -376,85 +376,85 @@ }, "mime": { "version": "1.2.11", - "from": "mime@1.2.11", + "from": "mime@>=1.2.11 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "async": { "version": "0.9.0", - "from": "async@0.9.0", + "from": "async@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "gulp": { "version": "3.8.10", - "from": "gulp@", + "from": "gulp@>=3.8.8 <3.9.0", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.8.10.tgz", "dependencies": { "archy": { "version": "1.0.0", - "from": "archy@^1.0.0", + "from": "archy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" }, "chalk": { "version": "0.5.1", - "from": "chalk@^0.5.0", + "from": "chalk@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "ansi-styles@^1.1.0", + "from": "ansi-styles@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { "version": "1.0.2", - "from": "escape-string-regexp@^1.0.0", + "from": "escape-string-regexp@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "has-ansi@^0.1.0", + "from": "has-ansi@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@^0.2.0", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "strip-ansi@^0.3.0", + "from": "strip-ansi@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@^0.2.1", + "from": "ansi-regex@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "supports-color@^0.2.0", + "from": "supports-color@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "deprecated": { "version": "0.0.1", - "from": "deprecated@^0.0.1", + "from": "deprecated@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz" }, "gulp-util": { "version": "3.0.1", - "from": "gulp-util@^3.0.0", + "from": "gulp-util@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.1.tgz", "dependencies": { "dateformat": { "version": "1.0.11", - "from": "dateformat@^1.0.7-1.2.3", + "from": "dateformat@>=1.0.7-1.2.3 <2.0.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", "dependencies": { "get-stdin": { @@ -469,39 +469,39 @@ "dependencies": { "camelcase-keys": { "version": "1.0.0", - "from": "camelcase-keys@^1.0.0", + "from": "camelcase-keys@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", "dependencies": { "camelcase": { "version": "1.0.2", - "from": "camelcase@^1.0.1", + "from": "camelcase@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { "version": "1.0.0", - "from": "map-obj@^1.0.0", + "from": "map-obj@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" } } }, "indent-string": { "version": "1.2.0", - "from": "indent-string@^1.1.0", + "from": "indent-string@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.0.tgz", "dependencies": { "repeating": { "version": "1.1.0", - "from": "repeating@^1.1.0", + "from": "repeating@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.0.tgz", "dependencies": { "is-finite": { "version": "1.0.0", - "from": "is-finite@^1.0.0", + "from": "is-finite@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" }, "meow": { "version": "1.0.0", - "from": "meow@^1.0.0", + "from": "meow@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-1.0.0.tgz" } } @@ -510,7 +510,7 @@ }, "object-assign": { "version": "1.0.0", - "from": "object-assign@^1.0.0", + "from": "object-assign@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" } } @@ -519,56 +519,56 @@ }, "lodash": { "version": "2.4.1", - "from": "lodash@^2.4.1", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "lodash._reinterpolate": { "version": "2.4.1", - "from": "lodash._reinterpolate@^2.4.1", + "from": "lodash._reinterpolate@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz" }, "lodash.template": { "version": "2.4.1", - "from": "lodash.template@^2.4.1", + "from": "lodash.template@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "dependencies": { "lodash.defaults": { "version": "2.4.1", - "from": "lodash.defaults@~2.4.1", + "from": "lodash.defaults@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@~2.4.1", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.escape": { "version": "2.4.1", - "from": "lodash.escape@~2.4.1", + "from": "lodash.escape@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "dependencies": { "lodash._escapehtmlchar": { "version": "2.4.1", - "from": "lodash._escapehtmlchar@~2.4.1", + "from": "lodash._escapehtmlchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "lodash._htmlescapes@~2.4.1", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } }, "lodash._reunescapedhtml": { "version": "2.4.1", - "from": "lodash._reunescapedhtml@~2.4.1", + "from": "lodash._reunescapedhtml@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "lodash._htmlescapes@~2.4.1", + "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } @@ -577,39 +577,39 @@ }, "lodash._escapestringchar": { "version": "2.4.1", - "from": "lodash._escapestringchar@~2.4.1", + "from": "lodash._escapestringchar@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz" }, "lodash.keys": { "version": "2.4.1", - "from": "lodash.keys@~2.4.1", + "from": "lodash.keys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "lodash._isnative@~2.4.1", + "from": "lodash._isnative@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "lodash.isobject@~2.4.1", + "from": "lodash.isobject@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@~2.4.1", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._shimkeys": { "version": "2.4.1", - "from": "lodash._shimkeys@~2.4.1", + "from": "lodash._shimkeys@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@~2.4.1", + "from": "lodash._objecttypes@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -618,19 +618,19 @@ }, "lodash.templatesettings": { "version": "2.4.1", - "from": "lodash.templatesettings@~2.4.1", + "from": "lodash.templatesettings@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz" }, "lodash.values": { "version": "2.4.1", - "from": "lodash.values@~2.4.1", + "from": "lodash.values@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" } } }, "multipipe": { "version": "0.1.2", - "from": "multipipe@^0.1.0", + "from": "multipipe@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "dependencies": { "duplexer2": { @@ -640,12 +640,12 @@ "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@~1.1.9", + "from": "readable-stream@>=1.1.9 <1.2.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -655,12 +655,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -671,7 +671,7 @@ }, "through2": { "version": "0.6.3", - "from": "through2@^0.6.1", + "from": "through2@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { @@ -681,7 +681,7 @@ "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@~1.0.0", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -691,12 +691,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@~0.10.x", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -710,17 +710,17 @@ }, "vinyl": { "version": "0.4.6", - "from": "vinyl@^0.4.0", + "from": "vinyl@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { "clone": { "version": "0.2.0", - "from": "clone@^0.2.0", + "from": "clone@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" }, "clone-stats": { "version": "0.0.1", - "from": "clone-stats@^0.0.1", + "from": "clone-stats@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -729,42 +729,42 @@ }, "interpret": { "version": "0.3.8", - "from": "interpret@^0.3.2", + "from": "interpret@>=0.3.2 <0.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.3.8.tgz" }, "liftoff": { "version": "0.13.6", - "from": "liftoff@^0.13.2", + "from": "liftoff@>=0.13.2 <0.14.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-0.13.6.tgz", "dependencies": { "findup-sync": { "version": "0.1.3", - "from": "findup-sync@~0.1.2", + "from": "findup-sync@>=0.1.2 <0.2.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "glob@~3.2.9", + "from": "glob@>=3.2.9 <3.3.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@2", + "from": "inherits@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@0.3", + "from": "minimatch@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@~1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -773,51 +773,51 @@ }, "lodash": { "version": "2.4.1", - "from": "lodash@~2.4.1", + "from": "lodash@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "resolve": { "version": "1.0.0", - "from": "resolve@~1.0.0", + "from": "resolve@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.0.0.tgz" }, "extend": { "version": "1.3.0", - "from": "extend@~1.3.0", + "from": "extend@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz" }, "flagged-respawn": { "version": "0.3.1", - "from": "flagged-respawn@~0.3.0", + "from": "flagged-respawn@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz" } } }, "minimist": { "version": "1.1.0", - "from": "minimist@^1.1.0", + "from": "minimist@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" }, "orchestrator": { "version": "0.3.7", - "from": "orchestrator@^0.3.0", + "from": "orchestrator@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", "dependencies": { "end-of-stream": { "version": "0.1.5", - "from": "end-of-stream@~0.1.5", + "from": "end-of-stream@>=0.1.5 <0.2.0", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "once@~1.3.0", + "from": "once@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@1", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -826,41 +826,41 @@ }, "sequencify": { "version": "0.0.7", - "from": "sequencify@~0.0.7", + "from": "sequencify@>=0.0.7 <0.1.0", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz" }, "stream-consume": { "version": "0.1.0", - "from": "stream-consume@~0.1.0", + "from": "stream-consume@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" } } }, "pretty-hrtime": { "version": "0.2.2", - "from": "pretty-hrtime@^0.2.0", + "from": "pretty-hrtime@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz" }, "semver": { "version": "4.1.0", - "from": "semver@^4.1.0", + "from": "semver@>=4.1.0 <5.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-4.1.0.tgz" }, "tildify": { "version": "1.0.0", - "from": "tildify@^1.0.0", + "from": "tildify@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", "dependencies": { "user-home": { "version": "1.1.0", - "from": "user-home@^1.0.0", + "from": "user-home@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.0.tgz" } } }, "v8flags": { "version": "1.0.5", - "from": "v8flags@^1.0.1", + "from": "v8flags@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-1.0.5.tgz" } } @@ -872,7 +872,7 @@ }, "npm": { "version": "2.1.3", - "from": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", + "from": "npm@2.1.3", "resolved": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", "dependencies": { "abbrev": { @@ -1436,22 +1436,22 @@ }, "open": { "version": "0.0.5", - "from": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "from": "open@0.0.5", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz" }, "optimist": { "version": "0.6.0", - "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", + "from": "optimist@0.6.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "wordwrap@0.0.2", + "from": "wordwrap@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@0.0.10", + "from": "minimist@>=0.0.1 <0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -1463,103 +1463,103 @@ }, "prompt": { "version": "0.2.12", - "from": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", + "from": "prompt@0.2.12", "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", "dependencies": { "pkginfo": { "version": "0.3.0", - "from": "pkginfo@0.3.0", + "from": "pkginfo@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "read": { "version": "1.0.5", - "from": "read@1.0.5", + "from": "read@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/read/-/read-1.0.5.tgz", "dependencies": { "mute-stream": { "version": "0.0.4", - "from": "mute-stream@0.0.4", + "from": "mute-stream@>=0.0.4 <0.1.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" } } }, "revalidator": { "version": "0.1.8", - "from": "revalidator@0.1.8", + "from": "revalidator@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz" }, "utile": { "version": "0.2.1", - "from": "utile@0.2.1", + "from": "utile@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "async@0.2.10", + "from": "async@>=0.2.9 <0.3.0", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "deep-equal": { "version": "0.2.1", - "from": "deep-equal@0.2.1", + "from": "deep-equal@*", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.1.tgz" }, "i": { "version": "0.3.2", - "from": "i@0.3.2", + "from": "i@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/i/-/i-0.3.2.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.5.0", + "from": "mkdirp@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@2.2.8", + "from": "rimraf@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "winston": { "version": "0.6.2", - "from": "winston@0.6.2", + "from": "winston@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz", "dependencies": { "async": { "version": "0.1.22", - "from": "async@0.1.22", + "from": "async@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" }, "cycle": { "version": "1.0.3", - "from": "cycle@1.0.3", + "from": "cycle@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz" }, "eyes": { "version": "0.1.8", - "from": "eyes@0.1.8", + "from": "eyes@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" }, "pkginfo": { "version": "0.2.3", - "from": "pkginfo@0.2.3", + "from": "pkginfo@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz" }, "request": { "version": "2.9.203", - "from": "request@2.9.203", + "from": "request@>=2.9.0 <2.10.0", "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz" }, "stack-trace": { "version": "0.0.9", - "from": "stack-trace@0.0.9", + "from": "stack-trace@>=0.0.0 <0.1.0", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } @@ -1568,52 +1568,52 @@ }, "proxy-middleware": { "version": "0.7.0", - "from": "proxy-middleware@0.7.0", + "from": "proxy-middleware@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.7.0.tgz" }, "q": { "version": "1.0.1", - "from": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", + "from": "q@1.0.1", "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz" }, "request": { "version": "2.27.0", - "from": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", + "from": "request@2.27.0", "resolved": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", "dependencies": { "qs": { "version": "0.6.6", - "from": "qs@0.6.6", + "from": "qs@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@5.0.0", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@0.5.2", + "from": "forever-agent@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "tunnel-agent": { "version": "0.3.0", - "from": "tunnel-agent@0.3.0", + "from": "tunnel-agent@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" }, "http-signature": { "version": "0.10.0", - "from": "http-signature@0.10.0", + "from": "http-signature@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", "dependencies": { "assert-plus": { "version": "0.1.2", - "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz", + "from": "assert-plus@0.1.2", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" }, "asn1": { "version": "0.1.11", - "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "from": "asn1@0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { @@ -1625,62 +1625,62 @@ }, "hawk": { "version": "1.0.0", - "from": "hawk@1.0.0", + "from": "hawk@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "hoek@0.9.1", + "from": "hoek@>=0.9.0 <0.10.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "boom@0.4.2", + "from": "boom@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@0.2.2", + "from": "cryptiles@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@0.2.4", + "from": "sntp@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign": { "version": "0.3.0", - "from": "aws-sign@0.3.0", + "from": "aws-sign@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz" }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@0.3.0", + "from": "oauth-sign@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "cookie-jar": { "version": "0.3.0", - "from": "cookie-jar@0.3.0", + "from": "cookie-jar@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz" }, "node-uuid": { - "version": "1.4.1", - "from": "node-uuid@1.4.1", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" + "version": "1.4.2", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@1.2.11", + "from": "mime@>=1.2.9 <1.3.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } }, "serve-static": { - "version": "1.6.1", - "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.1.tgz", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.6.1.tgz", + "version": "1.7.1", + "from": "serve-static@1.7.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.7.1.tgz", "dependencies": { "escape-html": { "version": "1.0.1", @@ -1689,23 +1689,23 @@ }, "parseurl": { "version": "1.3.0", - "from": "parseurl@1.3.0", + "from": "parseurl@>=1.3.0 <1.4.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "send": { - "version": "0.9.1", - "from": "https://registry.npmjs.org/send/-/send-0.9.1.tgz", - "resolved": "https://registry.npmjs.org/send/-/send-0.9.1.tgz", + "version": "0.10.1", + "from": "send@0.10.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.10.1.tgz", "dependencies": { "debug": { - "version": "2.0.0", - "from": "debug@2.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz" + "version": "2.1.0", + "from": "debug@>=2.1.0 <2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz" }, "depd": { - "version": "0.4.4", - "from": "depd@0.4.4", - "resolved": "https://registry.npmjs.org/depd/-/depd-0.4.4.tgz" + "version": "1.0.0", + "from": "depd@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz" }, "destroy": { "version": "1.0.3", @@ -1713,20 +1713,20 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "etag": { - "version": "1.3.1", - "from": "https://registry.npmjs.org/etag/-/etag-1.3.1.tgz", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.3.1.tgz", + "version": "1.5.1", + "from": "etag@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "dependencies": { "crc": { - "version": "3.0.0", - "from": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.0.0.tgz" + "version": "3.2.1", + "from": "crc@3.2.1", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz" } } }, "fresh": { "version": "0.2.4", - "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", + "from": "fresh@0.2.4", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, "mime": { @@ -1736,68 +1736,68 @@ }, "ms": { "version": "0.6.2", - "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "from": "ms@0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" }, "on-finished": { - "version": "2.1.0", - "from": "on-finished@2.1.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", + "version": "2.1.1", + "from": "on-finished@>=2.1.1 <2.2.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.1.tgz", "dependencies": { "ee-first": { - "version": "1.0.5", - "from": "ee-first@1.0.5", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz" + "version": "1.1.0", + "from": "ee-first@1.1.0", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz" } } }, "range-parser": { "version": "1.0.2", - "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", + "from": "range-parser@>=1.0.2 <1.1.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "shelljs": { "version": "0.2.6", - "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", + "from": "shelljs@0.2.6", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz" }, "tiny-lr-fork": { "version": "0.0.5", - "from": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", + "from": "tiny-lr-fork@0.0.5", "resolved": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", "dependencies": { "qs": { "version": "0.5.6", - "from": "qs@0.5.6", + "from": "qs@>=0.5.2 <0.6.0", "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" }, "faye-websocket": { "version": "0.4.4", - "from": "faye-websocket@0.4.4", + "from": "faye-websocket@>=0.4.3 <0.5.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz" }, "noptify": { "version": "0.0.3", - "from": "noptify@0.0.3", + "from": "noptify@>=0.0.3 <0.1.0", "resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz", "dependencies": { "nopt": { "version": "2.0.0", - "from": "nopt@2.0.0", + "from": "nopt@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz", "dependencies": { "abbrev": { "version": "1.0.5", - "from": "abbrev@1.0.5", + "from": "abbrev@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" } } @@ -1806,99 +1806,99 @@ }, "debug": { "version": "0.7.4", - "from": "debug@0.7.4", + "from": "debug@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" } } }, "unzip": { "version": "0.1.9", - "from": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", + "from": "unzip@0.1.9", "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", "dependencies": { "fstream": { "version": "0.1.31", - "from": "fstream@0.1.31", + "from": "fstream@>=0.1.21 <0.2.0", "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "dependencies": { "graceful-fs": { - "version": "3.0.4", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" + "version": "3.0.5", + "from": "graceful-fs@>=3.0.2 <3.1.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.0 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.5.0", + "from": "mkdirp@>=0.0.0 <1.0.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@2.2.8", + "from": "rimraf@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "pullstream": { "version": "0.4.1", - "from": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "from": "pullstream@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "dependencies": { "over": { "version": "0.0.5", - "from": "over@0.0.5", + "from": "over@>=0.0.5 <1.0.0", "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz" }, "slice-stream": { "version": "1.0.0", - "from": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "from": "slice-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" } } }, "binary": { "version": "0.3.0", - "from": "binary@0.3.0", + "from": "binary@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "dependencies": { "chainsaw": { "version": "0.1.0", - "from": "chainsaw@0.1.0", + "from": "chainsaw@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "dependencies": { "traverse": { "version": "0.3.9", - "from": "traverse@0.3.9", + "from": "traverse@>=0.3.0 <0.4.0", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } } }, "buffers": { "version": "0.1.1", - "from": "buffers@0.1.1", + "from": "buffers@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } }, "readable-stream": { - "version": "1.0.33-1", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "version": "1.0.33", + "from": "readable-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -1908,29 +1908,29 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "setimmediate": { "version": "1.0.2", - "from": "setimmediate@1.0.2", + "from": "setimmediate@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.2.tgz" }, "match-stream": { "version": "0.0.2", - "from": "match-stream@0.0.2", + "from": "match-stream@>=0.0.2 <0.1.0", "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "dependencies": { "buffers": { "version": "0.1.1", - "from": "buffers@0.1.1", + "from": "buffers@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } @@ -1939,32 +1939,44 @@ }, "vinyl-fs": { "version": "0.3.7", - "from": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", + "from": "vinyl-fs@0.3.7", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", "dependencies": { "glob-stream": { - "version": "3.1.15", - "from": "glob-stream@3.1.15", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.15.tgz", + "version": "3.1.18", + "from": "glob-stream@>=3.1.5 <4.0.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "dependencies": { "glob": { - "version": "4.0.6", - "from": "glob@4.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "version": "4.3.1", + "from": "glob@>=4.3.1 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.1.tgz", "dependencies": { + "inflight": { + "version": "1.0.4", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + } + } + }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "once": { "version": "1.3.1", - "from": "once@1.3.1", + "from": "once@>=1.3.0 <2.0.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@1.0.1", + "from": "wrappy@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -1972,89 +1984,103 @@ } }, "minimatch": { - "version": "1.0.0", - "from": "minimatch@1.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "version": "2.0.1", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", "dependencies": { - "lru-cache": { - "version": "2.5.0", - "from": "lru-cache@2.5.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" - }, - "sigmund": { - "version": "1.0.0", - "from": "sigmund@1.0.0", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + "brace-expansion": { + "version": "1.0.1", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.0.1.tgz", + "dependencies": { + "balanced-match": { + "version": "0.2.0", + "from": "balanced-match@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" + }, + "concat-map": { + "version": "0.0.0", + "from": "concat-map@0.0.0", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.0.tgz" + } + } } } }, "ordered-read-streams": { - "version": "0.0.8", - "from": "ordered-read-streams@0.0.8", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.0.8.tgz" + "version": "0.1.0", + "from": "ordered-read-streams@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz" }, "glob2base": { - "version": "0.0.11", - "from": "glob2base@0.0.11", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.11.tgz" + "version": "0.0.12", + "from": "glob2base@>=0.0.12 <0.0.13", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "dependencies": { + "find-index": { + "version": "0.1.1", + "from": "find-index@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" + } + } }, "unique-stream": { "version": "1.0.0", - "from": "unique-stream@1.0.0", + "from": "unique-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" } } }, "glob-watcher": { "version": "0.0.6", - "from": "glob-watcher@0.0.6", + "from": "glob-watcher@>=0.0.6 <0.0.7", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "dependencies": { "gaze": { "version": "0.5.1", - "from": "gaze@0.5.1", + "from": "gaze@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz", "dependencies": { "globule": { "version": "0.1.0", - "from": "globule@0.1.0", + "from": "globule@>=0.1.0 <0.2.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "dependencies": { "lodash": { "version": "1.0.1", - "from": "lodash@1.0.1", + "from": "lodash@>=1.0.1 <1.1.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.1.tgz" }, "glob": { "version": "3.1.21", - "from": "glob@3.1.21", + "from": "glob@>=3.1.21 <3.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "dependencies": { "graceful-fs": { "version": "1.2.3", - "from": "graceful-fs@1.2.3", + "from": "graceful-fs@>=1.2.0 <1.3.0", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, "inherits": { "version": "1.0.0", - "from": "inherits@1.0.0", + "from": "inherits@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz" } } }, "minimatch": { "version": "0.2.14", - "from": "minimatch@0.2.14", + "from": "minimatch@>=0.2.11 <0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@2.5.0", + "from": "lru-cache@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@1.0.0", + "from": "sigmund@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -2066,57 +2092,57 @@ } }, "graceful-fs": { - "version": "3.0.4", - "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" + "version": "3.0.5", + "from": "graceful-fs@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" }, "lodash": { "version": "2.4.1", - "from": "lodash@2.4.1", + "from": "lodash@>=2.4.1 <3.0.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@0.5.0", + "from": "mkdirp@>=0.5.0 <0.6.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "strip-bom": { "version": "1.0.0", - "from": "strip-bom@1.0.0", + "from": "strip-bom@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "dependencies": { "first-chunk-stream": { "version": "1.0.0", - "from": "first-chunk-stream@1.0.0", + "from": "first-chunk-stream@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" }, "is-utf8": { "version": "0.2.0", - "from": "is-utf8@0.2.0", + "from": "is-utf8@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz" } } }, "through2": { "version": "0.6.3", - "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", + "from": "through2@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33-1", - "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "version": "1.0.33", + "from": "readable-stream@>=1.0.33-1 <1.1.0-0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@1.0.1", + "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -2126,31 +2152,36 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "xtend@4.0.0", + "from": "xtend@>=4.0.0 <4.1.0-0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { - "version": "0.4.3", - "from": "vinyl@0.4.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.3.tgz", + "version": "0.4.6", + "from": "vinyl@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { + "clone": { + "version": "0.2.0", + "from": "clone@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" + }, "clone-stats": { "version": "0.0.1", - "from": "clone-stats@0.0.1", + "from": "clone-stats@>=0.0.1 <0.0.2", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -2164,17 +2195,17 @@ "dependencies": { "sax": { "version": "0.6.1", - "from": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", + "from": "sax@>=0.6.0 <0.7.0", "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz" }, "xmlbuilder": { - "version": "2.4.4", - "from": "xmlbuilder@2.4.4", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.4.tgz", + "version": "2.4.5", + "from": "xmlbuilder@>=1.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.4.5.tgz", "dependencies": { "lodash-node": { "version": "2.4.1", - "from": "lodash-node@2.4.1", + "from": "lodash-node@>=2.4.1 <2.5.0", "resolved": "https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz" } } From c805f00c32117fb4c1541a060e7d1d5ba6a85c77 Mon Sep 17 00:00:00 2001 From: jbavari Date: Mon, 8 Dec 2014 19:21:42 -0700 Subject: [PATCH 306/850] Adding in the service/remove/add commands to assist in maintaining bower components --- lib/ionic.js | 39 ++++++++ lib/ionic/add.js | 91 +++++++++++++++++++ lib/ionic/bower.js | 29 ++++-- lib/ionic/service.js | 207 +++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- 5 files changed, 361 insertions(+), 8 deletions(-) create mode 100644 lib/ionic/add.js create mode 100644 lib/ionic/service.js diff --git a/lib/ionic.js b/lib/ionic.js index f0d8c21d70..d34d78d506 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -236,6 +236,45 @@ var TASKS = [ // '--uuid|-u': 'Mark an already uploaded version as deployed' // }, module: './ionic/app' + }, + { + title: 'service add', + name: 'service', + summary: 'Add an Ionic service package and install any required plugins', + args: { + '[options]': '', + '': 'Can be a service name or a git url' + }, + module: './ionic/service' + }, + { + title: 'add', + name: 'add', + summary: 'Add a bower component to the project', + args: { + 'component name': '' + }, + module: './ionic/add' + }, + { + title: 'remove', + name: 'remove', + summary: 'Remove a bower component from the project', + args: { + 'component name': '' + }, + module: './ionic/add', + alt: ['rm'] + }, + { + title: 'list', + name: 'list', + summary: 'List bower components from the project', + args: { + 'component name': '' + }, + module: './ionic/add', + alt: ['ls'] } ]; diff --git a/lib/ionic/add.js b/lib/ionic/add.js new file mode 100644 index 0000000000..c18a919c74 --- /dev/null +++ b/lib/ionic/add.js @@ -0,0 +1,91 @@ +require('shelljs/global') + +var Task = require('./task').Task, + IonicCordova = require('./cordova').IonicTask, + IonicStats = require('./stats').IonicStats, + argv = require('optimist').argv, + fs = require('fs'), + path = require('path'), + bower = require('./bower'); + +var IonicTask = function() {}; + +IonicTask.prototype = new Task(); + +IonicTask.prototype.installBowerComponent = function installBowerComponent(componentName) { + var bowerInstallCommand = 'bower install --save-dev ' + componentName; + + var result = exec(bowerInstallCommand); + + if (result.code != 0) { + //Error happened, report it. + var errorMessage = 'Failed to find the bower component "'.error.bold + componentName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'add'); + } else { + var message = 'Bower component installed - ' + componentName; + console.log(message.green) + } +} + +IonicTask.prototype.uninstallBowerComponent = function uninstallBowerComponent(componentName) { + var bowerUninstallCommand = 'bower uninstall --save-dev ' + componentName; + + var result = exec(bowerUninstallCommand); + + if (result.code != 0) { + var errorMessage = 'Failed to find the bower component "'.error.bold + componentName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'add') + } else { + var message = 'Bower component removed - ' + componentName; + console.log(message.red); + } +} + +IonicTask.prototype.listComponents = function listComponents() { + var bowerJson = require(path.join(process.cwd(), 'bower.json')); + console.log('Components installed: '.info) + for (var bowerCompIndex in bowerJson.devDependencies) { + console.log(bowerCompIndex.green); + } +} + +// Need to look at bower.json of package just installed and look for any cordova plugins required +// Check the directory in the projects `.bowerrc` file +// Then go to /path/to/bower/components//ionic-plugins.json - 'plugins' +// For each plugins - call 'ionic add plugin ' +IonicTask.prototype.run = function(ionic, callback) { + // console.log('running ', argv._) + this.ionic = ionic; + + IonicStats.t(); + + if (!bower.IonicBower.checkForBower()) { + this.ionic.fail(bower.IonicBower.installMessage, 'add'); + return; + } + + var action = argv._[0] + var componentName = argv._[1]; + + try { + switch (action) { + case 'add': + this.installBowerComponent(componentName); + break; + case 'remove': + case 'rm': + this.uninstallBowerComponent(componentName); + break; + case 'list': + case 'ls': + case '': + this.listComponents(); + break; + } + } catch (error) { + var errorMessage = error.message ? error.message : error; + this.ionic.fail(errorMessage, 'service') + } +} + +exports.IonicTask = IonicTask; diff --git a/lib/ionic/bower.js b/lib/ionic/bower.js index daf765bc6b..3c6657c23d 100644 --- a/lib/ionic/bower.js +++ b/lib/ionic/bower.js @@ -1,3 +1,5 @@ +require('shelljs/global') + var fs = require('fs'), path = require('path'), colors = require('colors'); @@ -6,7 +8,7 @@ exports.IonicBower = { setIonicVersion: function(newVersion) { var bowerData = this.getData(); - if(!bowerData.devDependencies) bowerData.devDependencies = {}; + if (!bowerData.devDependencies) bowerData.devDependencies = {}; bowerData.devDependencies.ionic = 'driftyco/ionic-bower#' + newVersion; this.saveData(bowerData); }, @@ -21,10 +23,10 @@ exports.IonicBower = { var bowerFilePath = path.resolve('bower.json'); try { - if( fs.existsSync(bowerFilePath) ) { + if (fs.existsSync(bowerFilePath)) { return require(bowerFilePath); } - } catch(e){} + } catch (e) {} return { "name": "HelloIonic", @@ -35,10 +37,23 @@ exports.IonicBower = { saveData: function(bowerData) { try { var bowerFilePath = path.resolve('bower.json'); - fs.writeFileSync( bowerFilePath, JSON.stringify(bowerData, null, 2) ); - } catch(e) { - console.log( ('Error saving ' + bowerFilePath + ': ' + e).error.bold ); + fs.writeFileSync(bowerFilePath, JSON.stringify(bowerData, null, 2)); + } catch (e) { + console.log(('Error saving ' + bowerFilePath + ': ' + e).error.bold); } - } + }, + + checkForBower: function checkForBower() { + var installed = false; + try { + var result = exec('bower -v', {silent: true}); + if (result.output.indexOf('command not found') == -1 && result.output.indexOf('not recognized') == -1) { + installed = true; + } + } catch (ex) { } + return installed; + }, + + installMessage: 'You must have bower installed to continue. \nType `npm install -g bower`' }; diff --git a/lib/ionic/service.js b/lib/ionic/service.js new file mode 100644 index 0000000000..47e95d82f1 --- /dev/null +++ b/lib/ionic/service.js @@ -0,0 +1,207 @@ +require('shelljs/global') + +var Task = require('./task').Task, + IonicCordova = require('./cordova').IonicTask, + IonicStats = require('./stats').IonicStats, + argv = require('optimist').argv, + fs = require('fs'), + path = require('path') + _ = require('underscore'), + bower = require('./bower'); + +var IonicTask = function() {}; + +IonicTask.prototype = new Task(); + +IonicTask.prototype.readIonicProjectJson = function readIonicProjectJson() { + var ionicProjectFile = path.join(process.cwd(), 'ionic.project'); + var ionicProjectJson = null; + try { + var content = fs.readFileSync(ionicProjectFile, 'utf8'); + ionicProjectJson = JSON.parse(content); + } catch (ex) { } + + return ionicProjectJson; +} + +IonicTask.prototype.addServiceToIonicJson = function addServiceToIonicJson(serviceName) { + var ionicProjectFile = path.join(process.cwd(), 'ionic.project'); + + try { + var ionicProjectJson = this.readIonicProjectJson() || {}; + + if (!ionicProjectJson.services) { + ionicProjectJson.services = []; + } + + var existingProject = _.findWhere(ionicProjectJson.services, {name: serviceName}); + if (typeof existingProject != 'undefined') { + return; + } + + ionicProjectJson.services.push({name: serviceName}); + fs.writeFileSync(ionicProjectFile, JSON.stringify(ionicProjectJson, null, 2), 'utf8'); + + } catch (ex) { + this.ionic.fail('Failed to update the ionic.project settings for the service', 'service'); + } +} + +IonicTask.prototype.installBowerComponent = function installBowerComponent(serviceName) { + // console.log('We are here now.'); + var bowerInstallCommand = 'bower link ionic-service-' + serviceName; + // var bowerInstallCommand = 'bower install ionic-service-' + serviceName; + + var result = exec(bowerInstallCommand); + + if (result.code != 0) { + //Error happened, report it. + var errorMessage = 'Failed to find the service "'.error.bold + serviceName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } else { + this.addServiceToIonicJson(serviceName); + } +} + +IonicTask.prototype.uninstallBowerComponent = function uninstallBowerComponent(serviceName) { + var bowerUninstallCommand = 'bower unlink ionic-service-' + serviceName; + + var result = exec(bowerUninstallCommand); + + if (result.code != 0) { + var errorMessage = 'Failed to find the service "'.error.bold + serviceName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'service') + } else { + // console.log('Uninstalled Ionic service', serviceName); + } +} + +IonicTask.prototype.getBowerComponentsLocation = function getBowerComponentsLocation() { + var bowerRcFileLocation = path.join(process.cwd(), '.bowerrc'); + // console.log('location bowerrc: ' , bowerRcFileLocation) + var bowerRc = null; + + try { + var content = fs.readFileSync(bowerRcFileLocation, 'utf8'); + bowerRc = JSON.parse(content); + // console.log('bowerRc contents: ', bowerRc) + } catch (ex) { } + + var directory = 'www/lib'; //Default directory + + if (bowerRc && bowerRc.directory) { + directory = bowerRc.directory; + } + + return directory; +} + +IonicTask.prototype.getBowerJson = function getBowerJson(directory, serviceName) { + var bowerJsonLocation = path.join(process.cwd(), directory, 'ionic-service-' + serviceName, 'ionic-plugins.json'); + var packageBowerJson = require(bowerJsonLocation); + return packageBowerJson; +} + +IonicTask.prototype.installBowerPlugins = function installBowerPlugins(directory, serviceName) { + // var bowerJsonLocation = process.cwd() + '/' + directory + '/ionic-service-' + serviceName + '/bower.json'; + // var packageBowerJson = require(bowerJsonLocation); + var packageBowerJson = this.getBowerJson(directory, serviceName); + + // console.log('bowerjson = ', packageBowerJson.plugins); + // console.log('ionic - ', IonicCordova); + _.each(packageBowerJson.plugins, function(plugin) { + // var ic = new IonicCordova(); + // ic.run('ionic plugin add ' + plugin); + console.log('Installing cordova plugin - ' + plugin.name + ' (' + plugin.id + ')'); + var installPluginCmd = 'ionic plugin add ' + plugin.uri; + console.log(installPluginCmd); + var pluginInstallResult = exec(installPluginCmd); + + if (pluginInstallResult.code != 0) { + var errorMessage = 'Failed to find the plugin "'.error.bold + plugin.name.verbose + '"'.error.bold + '.'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } + // console.log(pluginInstallResult); + }) +} + +IonicTask.prototype.uninstallBowerPlugins = function uninstallBowerPlugins(bowerJson) { + _.each(bowerJson.plugins, function(plugin) { + console.log('Uninstalling cordova plugin - ' + plugin.name); + var uninstallPluginCmd = 'ionic plugin rm ' + plugin.id; + console.log(uninstallPluginCmd); + var pluginRemoveResult = exec(uninstallPluginCmd) + + if (pluginRemoveResult.code != 0) { + var errorMessage = 'Failed to find the plugin to remove "'.error.bold + plugin.name.verbose + '"'.error.bold + '.'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } + }) +} + +IonicTask.prototype.addService = function addService(serviceName) { + this.installBowerComponent(serviceName); + + var directory = this.getBowerComponentsLocation(); + // console.log('Directory we are searching for bower.json - ', directory); + + console.log('Checking for any plugins required by service package'); + + this.installBowerPlugins(directory, serviceName); + console.log('ionic service add completed'); +} + +IonicTask.prototype.removeService = function removeService(serviceName) { + var directory = this.getBowerComponentsLocation(); + var packageBowerJson = this.getBowerJson(directory, serviceName); + + this.uninstallBowerComponent(serviceName); + + this.uninstallBowerPlugins(packageBowerJson); + +} + +IonicTask.prototype.listServices = function listServices() { + // var directory = this.getBowerComponentsLocation(); + var bowerJson = require(process.cwd() + '/bower.json'); + // console.log(bowerJson); + +} + +// Need to look at bower.json of package just installed and look for any cordova plugins required +// Check the directory in the projects `.bowerrc` file +// Then go to /path/to/bower/components//ionic-plugins.json - 'plugins' +// For each plugins - call 'ionic add plugin ' +IonicTask.prototype.run = function run(ionic, callback) { + this.ionic = ionic; + + IonicStats.t(); + + + if (!bower.IonicBower.checkForBower()) { + this.ionic.fail(bower.IonicBower.installMessage, 'service'); + return; + } + + var action = argv._[1] + var serviceName = argv._[2]; + + try { + switch (action) { + case 'add': + this.addService(serviceName); + break; + case 'remove': + this.removeService(serviceName); + break; + case 'list': + this.listServices(); + break; + } + } catch (error) { + var errorMessage = error.message ? error.message : error; + this.ionic.fail(errorMessage, 'service') + } +} + +exports.IonicTask = IonicTask; diff --git a/package.json b/package.json index 5dfa933b4c..685ae01890 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "tiny-lr-fork": "0.0.5", "unzip": "0.1.9", "vinyl-fs": "0.3.7", - "xml2js": "0.4.4" + "xml2js": "0.4.4", + "underscore": "~1.7.0" } } From 562f71a080eed2bc1629a40fd14f9c14884d5a4e Mon Sep 17 00:00:00 2001 From: jbavari Date: Mon, 8 Dec 2014 19:21:42 -0700 Subject: [PATCH 307/850] Adding in the service/remove/add commands to assist in maintaining bower components --- lib/ionic.js | 39 ++++++++ lib/ionic/add.js | 91 +++++++++++++++++++ lib/ionic/bower.js | 29 ++++-- lib/ionic/service.js | 207 +++++++++++++++++++++++++++++++++++++++++++ npm-shrinkwrap.json | 5 ++ package.json | 3 +- 6 files changed, 366 insertions(+), 8 deletions(-) create mode 100644 lib/ionic/add.js create mode 100644 lib/ionic/service.js diff --git a/lib/ionic.js b/lib/ionic.js index f0d8c21d70..d34d78d506 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -236,6 +236,45 @@ var TASKS = [ // '--uuid|-u': 'Mark an already uploaded version as deployed' // }, module: './ionic/app' + }, + { + title: 'service add', + name: 'service', + summary: 'Add an Ionic service package and install any required plugins', + args: { + '[options]': '', + '': 'Can be a service name or a git url' + }, + module: './ionic/service' + }, + { + title: 'add', + name: 'add', + summary: 'Add a bower component to the project', + args: { + 'component name': '' + }, + module: './ionic/add' + }, + { + title: 'remove', + name: 'remove', + summary: 'Remove a bower component from the project', + args: { + 'component name': '' + }, + module: './ionic/add', + alt: ['rm'] + }, + { + title: 'list', + name: 'list', + summary: 'List bower components from the project', + args: { + 'component name': '' + }, + module: './ionic/add', + alt: ['ls'] } ]; diff --git a/lib/ionic/add.js b/lib/ionic/add.js new file mode 100644 index 0000000000..c18a919c74 --- /dev/null +++ b/lib/ionic/add.js @@ -0,0 +1,91 @@ +require('shelljs/global') + +var Task = require('./task').Task, + IonicCordova = require('./cordova').IonicTask, + IonicStats = require('./stats').IonicStats, + argv = require('optimist').argv, + fs = require('fs'), + path = require('path'), + bower = require('./bower'); + +var IonicTask = function() {}; + +IonicTask.prototype = new Task(); + +IonicTask.prototype.installBowerComponent = function installBowerComponent(componentName) { + var bowerInstallCommand = 'bower install --save-dev ' + componentName; + + var result = exec(bowerInstallCommand); + + if (result.code != 0) { + //Error happened, report it. + var errorMessage = 'Failed to find the bower component "'.error.bold + componentName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'add'); + } else { + var message = 'Bower component installed - ' + componentName; + console.log(message.green) + } +} + +IonicTask.prototype.uninstallBowerComponent = function uninstallBowerComponent(componentName) { + var bowerUninstallCommand = 'bower uninstall --save-dev ' + componentName; + + var result = exec(bowerUninstallCommand); + + if (result.code != 0) { + var errorMessage = 'Failed to find the bower component "'.error.bold + componentName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'add') + } else { + var message = 'Bower component removed - ' + componentName; + console.log(message.red); + } +} + +IonicTask.prototype.listComponents = function listComponents() { + var bowerJson = require(path.join(process.cwd(), 'bower.json')); + console.log('Components installed: '.info) + for (var bowerCompIndex in bowerJson.devDependencies) { + console.log(bowerCompIndex.green); + } +} + +// Need to look at bower.json of package just installed and look for any cordova plugins required +// Check the directory in the projects `.bowerrc` file +// Then go to /path/to/bower/components//ionic-plugins.json - 'plugins' +// For each plugins - call 'ionic add plugin ' +IonicTask.prototype.run = function(ionic, callback) { + // console.log('running ', argv._) + this.ionic = ionic; + + IonicStats.t(); + + if (!bower.IonicBower.checkForBower()) { + this.ionic.fail(bower.IonicBower.installMessage, 'add'); + return; + } + + var action = argv._[0] + var componentName = argv._[1]; + + try { + switch (action) { + case 'add': + this.installBowerComponent(componentName); + break; + case 'remove': + case 'rm': + this.uninstallBowerComponent(componentName); + break; + case 'list': + case 'ls': + case '': + this.listComponents(); + break; + } + } catch (error) { + var errorMessage = error.message ? error.message : error; + this.ionic.fail(errorMessage, 'service') + } +} + +exports.IonicTask = IonicTask; diff --git a/lib/ionic/bower.js b/lib/ionic/bower.js index daf765bc6b..3c6657c23d 100644 --- a/lib/ionic/bower.js +++ b/lib/ionic/bower.js @@ -1,3 +1,5 @@ +require('shelljs/global') + var fs = require('fs'), path = require('path'), colors = require('colors'); @@ -6,7 +8,7 @@ exports.IonicBower = { setIonicVersion: function(newVersion) { var bowerData = this.getData(); - if(!bowerData.devDependencies) bowerData.devDependencies = {}; + if (!bowerData.devDependencies) bowerData.devDependencies = {}; bowerData.devDependencies.ionic = 'driftyco/ionic-bower#' + newVersion; this.saveData(bowerData); }, @@ -21,10 +23,10 @@ exports.IonicBower = { var bowerFilePath = path.resolve('bower.json'); try { - if( fs.existsSync(bowerFilePath) ) { + if (fs.existsSync(bowerFilePath)) { return require(bowerFilePath); } - } catch(e){} + } catch (e) {} return { "name": "HelloIonic", @@ -35,10 +37,23 @@ exports.IonicBower = { saveData: function(bowerData) { try { var bowerFilePath = path.resolve('bower.json'); - fs.writeFileSync( bowerFilePath, JSON.stringify(bowerData, null, 2) ); - } catch(e) { - console.log( ('Error saving ' + bowerFilePath + ': ' + e).error.bold ); + fs.writeFileSync(bowerFilePath, JSON.stringify(bowerData, null, 2)); + } catch (e) { + console.log(('Error saving ' + bowerFilePath + ': ' + e).error.bold); } - } + }, + + checkForBower: function checkForBower() { + var installed = false; + try { + var result = exec('bower -v', {silent: true}); + if (result.output.indexOf('command not found') == -1 && result.output.indexOf('not recognized') == -1) { + installed = true; + } + } catch (ex) { } + return installed; + }, + + installMessage: 'You must have bower installed to continue. \nType `npm install -g bower`' }; diff --git a/lib/ionic/service.js b/lib/ionic/service.js new file mode 100644 index 0000000000..47e95d82f1 --- /dev/null +++ b/lib/ionic/service.js @@ -0,0 +1,207 @@ +require('shelljs/global') + +var Task = require('./task').Task, + IonicCordova = require('./cordova').IonicTask, + IonicStats = require('./stats').IonicStats, + argv = require('optimist').argv, + fs = require('fs'), + path = require('path') + _ = require('underscore'), + bower = require('./bower'); + +var IonicTask = function() {}; + +IonicTask.prototype = new Task(); + +IonicTask.prototype.readIonicProjectJson = function readIonicProjectJson() { + var ionicProjectFile = path.join(process.cwd(), 'ionic.project'); + var ionicProjectJson = null; + try { + var content = fs.readFileSync(ionicProjectFile, 'utf8'); + ionicProjectJson = JSON.parse(content); + } catch (ex) { } + + return ionicProjectJson; +} + +IonicTask.prototype.addServiceToIonicJson = function addServiceToIonicJson(serviceName) { + var ionicProjectFile = path.join(process.cwd(), 'ionic.project'); + + try { + var ionicProjectJson = this.readIonicProjectJson() || {}; + + if (!ionicProjectJson.services) { + ionicProjectJson.services = []; + } + + var existingProject = _.findWhere(ionicProjectJson.services, {name: serviceName}); + if (typeof existingProject != 'undefined') { + return; + } + + ionicProjectJson.services.push({name: serviceName}); + fs.writeFileSync(ionicProjectFile, JSON.stringify(ionicProjectJson, null, 2), 'utf8'); + + } catch (ex) { + this.ionic.fail('Failed to update the ionic.project settings for the service', 'service'); + } +} + +IonicTask.prototype.installBowerComponent = function installBowerComponent(serviceName) { + // console.log('We are here now.'); + var bowerInstallCommand = 'bower link ionic-service-' + serviceName; + // var bowerInstallCommand = 'bower install ionic-service-' + serviceName; + + var result = exec(bowerInstallCommand); + + if (result.code != 0) { + //Error happened, report it. + var errorMessage = 'Failed to find the service "'.error.bold + serviceName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } else { + this.addServiceToIonicJson(serviceName); + } +} + +IonicTask.prototype.uninstallBowerComponent = function uninstallBowerComponent(serviceName) { + var bowerUninstallCommand = 'bower unlink ionic-service-' + serviceName; + + var result = exec(bowerUninstallCommand); + + if (result.code != 0) { + var errorMessage = 'Failed to find the service "'.error.bold + serviceName.verbose + '"'.error.bold + '.\nAre you sure it exists?'.error.bold; + this.ionic.fail(errorMessage, 'service') + } else { + // console.log('Uninstalled Ionic service', serviceName); + } +} + +IonicTask.prototype.getBowerComponentsLocation = function getBowerComponentsLocation() { + var bowerRcFileLocation = path.join(process.cwd(), '.bowerrc'); + // console.log('location bowerrc: ' , bowerRcFileLocation) + var bowerRc = null; + + try { + var content = fs.readFileSync(bowerRcFileLocation, 'utf8'); + bowerRc = JSON.parse(content); + // console.log('bowerRc contents: ', bowerRc) + } catch (ex) { } + + var directory = 'www/lib'; //Default directory + + if (bowerRc && bowerRc.directory) { + directory = bowerRc.directory; + } + + return directory; +} + +IonicTask.prototype.getBowerJson = function getBowerJson(directory, serviceName) { + var bowerJsonLocation = path.join(process.cwd(), directory, 'ionic-service-' + serviceName, 'ionic-plugins.json'); + var packageBowerJson = require(bowerJsonLocation); + return packageBowerJson; +} + +IonicTask.prototype.installBowerPlugins = function installBowerPlugins(directory, serviceName) { + // var bowerJsonLocation = process.cwd() + '/' + directory + '/ionic-service-' + serviceName + '/bower.json'; + // var packageBowerJson = require(bowerJsonLocation); + var packageBowerJson = this.getBowerJson(directory, serviceName); + + // console.log('bowerjson = ', packageBowerJson.plugins); + // console.log('ionic - ', IonicCordova); + _.each(packageBowerJson.plugins, function(plugin) { + // var ic = new IonicCordova(); + // ic.run('ionic plugin add ' + plugin); + console.log('Installing cordova plugin - ' + plugin.name + ' (' + plugin.id + ')'); + var installPluginCmd = 'ionic plugin add ' + plugin.uri; + console.log(installPluginCmd); + var pluginInstallResult = exec(installPluginCmd); + + if (pluginInstallResult.code != 0) { + var errorMessage = 'Failed to find the plugin "'.error.bold + plugin.name.verbose + '"'.error.bold + '.'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } + // console.log(pluginInstallResult); + }) +} + +IonicTask.prototype.uninstallBowerPlugins = function uninstallBowerPlugins(bowerJson) { + _.each(bowerJson.plugins, function(plugin) { + console.log('Uninstalling cordova plugin - ' + plugin.name); + var uninstallPluginCmd = 'ionic plugin rm ' + plugin.id; + console.log(uninstallPluginCmd); + var pluginRemoveResult = exec(uninstallPluginCmd) + + if (pluginRemoveResult.code != 0) { + var errorMessage = 'Failed to find the plugin to remove "'.error.bold + plugin.name.verbose + '"'.error.bold + '.'.error.bold; + this.ionic.fail(errorMessage, 'service'); + } + }) +} + +IonicTask.prototype.addService = function addService(serviceName) { + this.installBowerComponent(serviceName); + + var directory = this.getBowerComponentsLocation(); + // console.log('Directory we are searching for bower.json - ', directory); + + console.log('Checking for any plugins required by service package'); + + this.installBowerPlugins(directory, serviceName); + console.log('ionic service add completed'); +} + +IonicTask.prototype.removeService = function removeService(serviceName) { + var directory = this.getBowerComponentsLocation(); + var packageBowerJson = this.getBowerJson(directory, serviceName); + + this.uninstallBowerComponent(serviceName); + + this.uninstallBowerPlugins(packageBowerJson); + +} + +IonicTask.prototype.listServices = function listServices() { + // var directory = this.getBowerComponentsLocation(); + var bowerJson = require(process.cwd() + '/bower.json'); + // console.log(bowerJson); + +} + +// Need to look at bower.json of package just installed and look for any cordova plugins required +// Check the directory in the projects `.bowerrc` file +// Then go to /path/to/bower/components//ionic-plugins.json - 'plugins' +// For each plugins - call 'ionic add plugin ' +IonicTask.prototype.run = function run(ionic, callback) { + this.ionic = ionic; + + IonicStats.t(); + + + if (!bower.IonicBower.checkForBower()) { + this.ionic.fail(bower.IonicBower.installMessage, 'service'); + return; + } + + var action = argv._[1] + var serviceName = argv._[2]; + + try { + switch (action) { + case 'add': + this.addService(serviceName); + break; + case 'remove': + this.removeService(serviceName); + break; + case 'list': + this.listServices(); + break; + } + } catch (error) { + var errorMessage = error.message ? error.message : error; + this.ionic.fail(errorMessage, 'service') + } +} + +exports.IonicTask = IonicTask; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index f36e3667be..1100c36b64 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1811,6 +1811,11 @@ } } }, + "underscore": { + "version": "1.7.0", + "from": "underscore@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + }, "unzip": { "version": "0.1.9", "from": "unzip@0.1.9", diff --git a/package.json b/package.json index 5dfa933b4c..685ae01890 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "tiny-lr-fork": "0.0.5", "unzip": "0.1.9", "vinyl-fs": "0.3.7", - "xml2js": "0.4.4" + "xml2js": "0.4.4", + "underscore": "~1.7.0" } } From bb2f5ba9f076a2e4c6222015d88ee5b522962b89 Mon Sep 17 00:00:00 2001 From: Mehdy Dara Date: Tue, 9 Dec 2014 17:06:47 +0100 Subject: [PATCH 308/850] spawn use option "stdio" inheritance * http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options * Less code * Color enabled --- lib/ionic/serve.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 55a74e9687..0c18d946a7 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -133,21 +133,10 @@ IonicTask.prototype.start = function(ionic) { // gulpStartupTasks should be an array of tasks set in the project config // watchSass is for backwards compatible sass: true project config if((this.gulpStartupTasks && this.gulpStartupTasks.length) || this.watchSass) { - var spawn = require('cross-spawn').spawn; var tasks = this.gulpStartupTasks || ['sass','watch']; console.log('Gulp startup tasks:'.green.bold, tasks); - var childProcess = spawn('gulp', tasks); - - childProcess.stdout.on('data', function (data) { - process.stdout.write(data); - }); - - childProcess.stderr.on('data', function (data) { - if(data) { - process.stderr.write(data.toString().yellow); - } - }); + require('cross-spawn').spawn('gulp', tasks, { stdio: 'inherit' }); } if(this.runLivereload) { From f9712b3be0abbb02a6585ad1f5b1cf4f201ae814 Mon Sep 17 00:00:00 2001 From: jbavari Date: Tue, 9 Dec 2014 11:12:07 -0700 Subject: [PATCH 309/850] Adding in the environment variable http_proxy for npm defaults, along with the PROXY env variable we suggested --- lib/ionic.js | 2 +- lib/ionic/lib.js | 2 +- lib/ionic/login.js | 2 +- lib/ionic/package.js | 2 +- lib/ionic/start.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ionic.js b/lib/ionic.js index d34d78d506..0bd4be6f11 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -540,7 +540,7 @@ Ionic = { return; } - var proxy = process.env.PROXY || null; + var proxy = process.env.PROXY || process.env.http_proxy || null; var request = require('request'); request({ url: 'http://registry.npmjs.org/ionic/latest', proxy: proxy }, function(err, res, body) { try { diff --git a/lib/ionic/lib.js b/lib/ionic/lib.js index 460b657ede..e64ff7c9bf 100644 --- a/lib/ionic/lib.js +++ b/lib/ionic/lib.js @@ -80,7 +80,7 @@ IonicTask.prototype.getVersionData = function(version) { url += '/' + version + '/version.json'; } - var proxy = process.env.PROXY || null; + var proxy = process.env.PROXY || process.env.http_proxy || null; request({ url: url, proxy: proxy }, function(err, res, body) { try { if(err || !res || !body) { diff --git a/lib/ionic/login.js b/lib/ionic/login.js index 9b29a04371..7710f39fa6 100644 --- a/lib/ionic/login.js +++ b/lib/ionic/login.js @@ -104,7 +104,7 @@ IonicTask.prototype.requestLogIn = function(ionic, callback, saveCookies) { username: self.email.toString().toLowerCase(), password: self.password }, - proxy: process.env.PROXY || null + proxy: process.env.PROXY || process.env.http_proxy || null }, function (err, response, body) { if(err) { diff --git a/lib/ionic/package.js b/lib/ionic/package.js index 55ae310364..1234dc80b7 100644 --- a/lib/ionic/package.js +++ b/lib/ionic/package.js @@ -169,7 +169,7 @@ IonicTask.prototype.loadAppSigning = function(callback) { }).join("; "), cck: cck }, - proxy: process.env.PROXY || null + proxy: process.env.PROXY || process.env.http_proxy || null }; request(options, function(err, response, body) { diff --git a/lib/ionic/start.js b/lib/ionic/start.js index 0b3b787e24..3e43ea68ac 100644 --- a/lib/ionic/start.js +++ b/lib/ionic/start.js @@ -247,7 +247,7 @@ IonicTask.prototype.fetchCodepen = function() { var qCSS = Q.defer(); var qJS = Q.defer(); - var proxy = process.env.PROXY || null; + var proxy = process.env.PROXY || process.env.http_proxy || null; request({ url: codepenUrl + '.html', proxy: proxy }, function(err, res, html) { if(!err && res && res.statusCode === 200) { From 0835f23c99b9ae562d604208a863173bbed18a34 Mon Sep 17 00:00:00 2001 From: jbavari Date: Tue, 9 Dec 2014 12:11:07 -0700 Subject: [PATCH 310/850] Adding documenation to README about working around proxies, as well as adding in the additional http_proxy in lib/ionic.js --- README.md | 17 +++++++++++++++++ lib/ionic.js | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f8d807c0ca..17bdcb1962 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,23 @@ Ionic uses Cordova underneath, so you can also substitute Cordova commands to pr *Note: we occasionally send anonymous usage statistics to the Ionic team to make the tool better.* +## Working around proxies + +If you have a proxy you need to get around, you can pass that proxy with the default `http_proxy` [node environment variable](https://www.npmjs.org/doc/misc/npm-config.html#proxy) or an environment variable `proxy`. + +A few ways to set up and use the environment variable: + +```bash +export http_proxy=internal.proxy.com +# Or +export PROXY=internal.proxy.com + +ionic start my_app + +# Additionally, pass in line +PROXY=internal.proxy.com ionic start my_app +``` + ## Using Sass diff --git a/lib/ionic.js b/lib/ionic.js index 0bd4be6f11..ccc80aeae2 100644 --- a/lib/ionic.js +++ b/lib/ionic.js @@ -648,7 +648,7 @@ Ionic = { readStream.pipe(writeStream); }; - var proxy = process.env.PROXY || null; + var proxy = process.env.PROXY || process.env.http_proxy || null; var request = require('request'); request({ url: archiveUrl, rejectUnauthorized: false, encoding: null, proxy: proxy }, function(err, res, body) { if(err) { From 78e4117ae1c145ed3d8aecef56f147417d0926d7 Mon Sep 17 00:00:00 2001 From: jbavari Date: Tue, 9 Dec 2014 20:35:20 -0700 Subject: [PATCH 311/850] Refactoring changes to use the Ionic.fetchArchive instead of using the git clone and curl commands --- lib/ionic/CrosswalkNotes.md | 12 ++ lib/ionic/browser.js | 218 ++++++++++++++++++++++-------------- 2 files changed, 149 insertions(+), 81 deletions(-) diff --git a/lib/ionic/CrosswalkNotes.md b/lib/ionic/CrosswalkNotes.md index 089b730a1a..83af78b830 100644 --- a/lib/ionic/CrosswalkNotes.md +++ b/lib/ionic/CrosswalkNotes.md @@ -16,3 +16,15 @@ A problem occurred evaluating script. > No installed build tools found. Please install the Android build tools version 19.1.0 or higher. Had to bump the minversionnumber in platform/android/AndroidManifest.xml to 14 from 10. + + + + +## Roadmap for Crosswalk integration + +Cordova release in Jan 2015 is pushing for pluggable web views + +In the meantime, do we go ahead and release now as a beta? + +When they do release, how do we integrate with those changes? + diff --git a/lib/ionic/browser.js b/lib/ionic/browser.js index 510d8b57e8..46d65fe2b8 100644 --- a/lib/ionic/browser.js +++ b/lib/ionic/browser.js @@ -18,22 +18,29 @@ //Install the crosswalk latest files // cordova platform remove android // cordova platform add android@3.5 -var path = require('path'), - shelljs = require('shelljs'); + +var fs = require('fs'), + path = require('path'), + argv = require('optimist').argv, + request = require('request'), + Q = require('q'), + shelljs = require('shelljs'), + Task = require('./task').Task, + proxyMiddleware = require('proxy-middleware'), + unzip = require('unzip'), + Ionic = require('../ionic').Ionic, + IonicStats = require('./stats').IonicStats; + +var IonicTask = function() {}; + +IonicTask.prototype = new Task(); + + var XWALK_LIBRARY_PATH = path.join(process.cwd(), 'tmp', 'xwalk'); var ARM_DOWNLOAD_URL = "https://download.01.org/crosswalk/releases/crosswalk/android/canary/8.37.189.0/arm/crosswalk-webview-8.37.189.0-arm.zip"; var X86_DOWNLOAD_URL = "https://download.01.org/crosswalk/releases/crosswalk/android/canary/8.37.189.0/x86/crosswalk-webview-8.37.189.0-x86.zip"; -function downloadFiles() { - var tempDir = '../../tmp/crosswalk-engine'; - //Download ARM - //unzip ARM - //rm zip - var libCrossWalk = path.join(process.cwd(), 'libs', 'xwalk_core_library'); - -} - function updateCrosswalkProject() { // prepare xwalk_core_library if(fs.existsSync(XWALK_LIBRARY_PATH)) { @@ -44,34 +51,35 @@ function updateCrosswalkProject() { } } -var fs = require('fs'), - path = require('path'), - argv = require('optimist').argv, - shelljs = require('shelljs'), - Task = require('./task').Task, - proxyMiddleware = require('proxy-middleware'), - IonicStats = require('./stats').IonicStats; +IonicTask.prototype.getCordovaCrosswalkEngine = function getCordovaCrosswalkEngine() { + var q = Q.defer(); -var IonicTask = function() {}; - -IonicTask.prototype = new Task(); - -IonicTask.prototype.getCrosswalkEngine = function getCrosswalkEngine() { if(!fs.existsSync(path.join(process.cwd(), 'engine'))) { shelljs.mkdir(path.join(process.cwd(), 'engine')); } if(fs.existsSync(path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine'))) { - return; //It exists, nothing to do here. + q.resolve(); + return q.promise; } - shelljs.cd(path.join(process.cwd(), 'engine')); - var downloadResult = shelljs.exec('git clone --depth=1 git@github.com:MobileChromeApps/cordova-crosswalk-engine.git'); - shelljs.cd('..') + // shelljs.cd(path.join(process.cwd(), 'engine')); + // var downloadResult = shelljs.exec('git clone --depth=1 git@github.com:MobileChromeApps/cordova-crosswalk-engine.git'); + var downloadUrl = 'https://github.com/driftyco/cordova-crosswalk-engine/archive/v0.8.zip'; - if(downloadResult.code == 1) { - //LOG ERROR - } + var tempZipFilePath = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine.zip'); + var zipOutPath = path.join(process.cwd(), 'engine'); + + Ionic.fetchArchive(zipOutPath, downloadUrl) + .then(function(data) { + console.log('downloaded') + q.resolve(); + }, function(error) { + console.log('failed to download engine - ', error); + q.reject(); + }) + + return q.promise; } IonicTask.prototype.getAndroidRuntimes = function getAndroidRuntimes() { @@ -83,78 +91,114 @@ IonicTask.prototype.getAndroidRuntimes = function getAndroidRuntimes() { } } -// download() { -// TMPDIR=cordova-crosswalk-engine-$$ -// pushd $TMPDIR > /dev/null -// echo "Fetching $1..." -// curl -# $1 -o library.zip -// unzip -q library.zip -// rm library.zip -// PACKAGENAME=$(ls|head -n 1) -// echo "Installing $PACKAGENAME into xwalk_core_library..." -// cp -a $PACKAGENAME/* ../libs/xwalk_core_library -// popd > /dev/null -// rm -r $TMPDIR -// } - -// download $ARM_DOWNLOAD -// download $X86_DOWNLOAD - -function downloadCrosswalkEngine(architecture, version) { - var command = 'curl -# https://download.01.org/crosswalk/releases/crosswalk/android/stable/' + - version + '/' + architecture + '/crosswalk-webview-' + version + '-' + architecture + '.zip -o library.zip'; +function downloadCrosswalkWebview(architecture, version) { + // var command = 'curl -# https://download.01.org/crosswalk/releases/crosswalk/android/stable/' + + // version + '/' + architecture + '/crosswalk-webview-' + version + '-' + architecture + '.zip -o library.zip'; + var q = Q.defer(); + + var downloadUrl = 'https://download.01.org/crosswalk/releases/crosswalk/android/stable/' + + version + '/' + architecture + '/crosswalk-webview-' + version + '-' + architecture + '.zip'; + + var tempZipFilePath = path.join(process.cwd(), 'engine', 'xwalk-webviews', architecture); //Ensure xwalk-webviews folder exists if (!fs.existsSync(path.join(process.cwd(), 'engine', 'xwalk-webviews'))) { shelljs.mkdir(path.join(process.cwd(), 'engine', 'xwalk-webviews')); } - shelljs.cd(path.join(process.cwd(), 'engine', 'xwalk-webviews')); + Ionic.fetchArchive(tempZipFilePath, downloadUrl) + .then(function(data) { + console.log('xwalk download good - ', data); + + //Need to go copy to android directory. + var fileName = fs.readdirSync(tempZipFilePath); + console.log('fileName for dirs ', fileName) + + var copySource = path.join(tempZipFilePath, fileName[0], '*'); + console.log('copy source - ', copySource) + + var copyDestination = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine-0.8', 'libs', 'xwalk_core_library', '/') + console.log('copyDestination - ', copyDestination); - console.log('Downloading the crosswalk webview for ' + architecture + ', version ' + version); - var resultCurl = shelljs.exec(command); - //TODO: Check for resultCurl + var cpXwalkLibsCmd = 'cp -r ' + copySource + ' ' + copyDestination; + var cpResult = shelljs.exec(cpXwalkLibsCmd) - console.log('Unzipping webview binaries') - var unzipCommand = 'unzip -q library.zip -d unzipped'; - var resultUnzip = shelljs.exec(unzipCommand); - var fileName = fs.readdirSync('unzipped')[0]; + console.log('Result from cp - ' , cpResult) + // var archDirectory = fs.readdirSync(path.join(fileName[0])); + // console.log('archDirectory - ', archDirectory); - console.log('file name: ', fileName); + q.resolve(data); + }, function(error) { + console.log('xwalk download failed - ', error) + q.reject(error); + }) - shelljs.cd('../../'); //Back at process.cwd() in ionic project root + // shelljs.cd(path.join(process.cwd(), 'engine', 'xwalk-webviews')); - var copySource = path.join(process.cwd(), 'engine', 'xwalk-webviews', 'unzipped', fileName, '*'); - console.log('copy source ', copySource) - var copyDestination = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine', 'libs', 'xwalk_core_library', '/'); - var cpArmLibsCommand = 'cp -r ' + copySource + ' ' + copyDestination; - console.log('command: ', cpArmLibsCommand); - shelljs.exec(cpArmLibsCommand); + // console.log('Downloading the crosswalk webview for ' + architecture + ', version ' + version); + // var resultCurl = shelljs.exec(command); - shelljs.rm('-rf', path.join(process.cwd(), 'engine', 'xwalk-webviews', 'unzipped')); + // console.log('Unzipping webview binaries') + // var unzipCommand = 'unzip -q library.zip -d unzipped'; + // var resultUnzip = shelljs.exec(unzipCommand); + // var fileName = fs.readdirSync('unzipped')[0]; + // console.log('file name: ', fileName); + + // shelljs.cd('../../'); //Back at process.cwd() in ionic project root + + // var copySource = path.join(process.cwd(), 'engine', 'xwalk-webviews', 'unzipped', fileName, '*'); + // console.log('copy source ', copySource) + // var copyDestination = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine', 'libs', 'xwalk_core_library', '/'); + // var cpArmLibsCommand = 'cp -r ' + copySource + ' ' + copyDestination; + // console.log('command: ', cpArmLibsCommand); + // shelljs.exec(cpArmLibsCommand); + + // shelljs.rm('-rf', path.join(process.cwd(), 'engine', 'xwalk-webviews', 'unzipped')); + return q.promise; } IonicTask.prototype.getCrosswalkWebviews = function getCrosswalkWebviews() { // var command = 'curl -# https://download.01.org/crosswalk/releases/crosswalk/android/stable/8.37.189.14/arm/crosswalk-webview-8.37.189.14-arm.zip -o arm.zip'; var version = '8.37.189.14'; - downloadCrosswalkEngine('arm', version); - downloadCrosswalkEngine('x86', version); + var armPromise = downloadCrosswalkWebview('arm', version); + var x86Promise = downloadCrosswalkWebview('x86', version); + // downloadCrosswalkWebview('x86', version); + + return Q.all[armPromise, x86Promise]; } IonicTask.prototype.getCordovaAndroid40x = function getCordovaAndroid40x() { + var q = Q.defer(); + if (fs.existsSync(path.join(process.cwd(), 'engine', 'cordova-android'))) { - return; + q.resolve(); + return q.promise; } - var command = 'git clone --depth=1 -b 4.0.x git@github.com:apache/cordova-android.git'; + // var command = 'git clone --depth=1 -b 4.0.x git@github.com:apache/cordova-android.git'; + var downloadUrl = 'https://github.com/driftyco/cordova-android/archive/v4.0.x.zip'; - shelljs.cd(path.join(process.cwd(), 'engine')); + var tempZipFilePath = path.join(process.cwd(), 'engine'); - var result = shelljs.exec(command); - shelljs.cd('..'); + Ionic.fetchArchive(tempZipFilePath, downloadUrl) + .then(function(data) { + console.log('downloaded - ', data); + q.resolve(); + }, function(error) { + console.log('download fail - ', error); + q.reject(); + }) + + // shelljs.cd(path.join(process.cwd(), 'engine')); + + // var result = shelljs.exec(command); + + // shelljs.cd('..'); + + return q.promise; } IonicTask.prototype.removeAndroidProject = function removeAndroidProject() { @@ -163,17 +207,17 @@ IonicTask.prototype.removeAndroidProject = function removeAndroidProject() { } IonicTask.prototype.addCordova40xProject = function addCordova40xProject() { - var command = 'cordova platform add ./engine/cordova-android/'; + var command = 'cordova platform add ./engine/cordova-android-4.0.x/'; var result = shelljs.exec(command); } IonicTask.prototype.addCrosswalkPlugin = function addCrosswalkPlugin() { - var command = 'cordova plugin add ./engine/cordova-crosswalk-engine'; + var command = 'cordova plugin add ./engine/cordova-crosswalk-engine-0.8'; var result = shelljs.exec(command); } IonicTask.prototype.updateAndroidProject = function updateAndroidProject() { - var xwalkLibraryPath = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine', 'libs', 'xwalk_core_library'); + var xwalkLibraryPath = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine-0.8', 'libs', 'xwalk_core_library'); shelljs.cd(path.join(process.cwd(), 'platforms', 'android')); @@ -187,13 +231,25 @@ IonicTask.prototype.run = function(ionic) { this.ionic = ionic; - this.getCrosswalkEngine(); + // this.getCordovaCrosswalkEngine() + // .then(function(data) { + // console.log('we completed the download') + // return self.getCordovaAndroid40x(); + // }, function(error) { + // console.log('Error - ', error) + // }) + // .then(function(data) { + // console.log('downloaded Android runtimes'); + + // self.getCrosswalkWebviews(); - this.getAndroidRuntimes(); + // }, function(error) { + // console.log('failed to download android runtime'); + // }) - this.getCrosswalkWebviews(); + // this.getAndroidRuntimes(); - this.getCordovaAndroid40x(); + // this.getCordovaAndroid40x(); this.removeAndroidProject(); From b684e4ab301e34f30bdaa110f0427601c4ed3cc4 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 10 Dec 2014 11:37:56 -0600 Subject: [PATCH 312/850] New serve --- lib/ionic/assets/preview.html | 60 +++- lib/ionic/serve.js | 45 ++- npm-shrinkwrap.json | 631 ++++++++++++++++------------------ package.json | 2 +- 4 files changed, 379 insertions(+), 359 deletions(-) diff --git a/lib/ionic/assets/preview.html b/lib/ionic/assets/preview.html index 25e11303b9..61c4b7e0ed 100644 --- a/lib/ionic/assets/preview.html +++ b/lib/ionic/assets/preview.html @@ -1,17 +1,18 @@ - + + + + + + + - + +
-

iPhone 6

+

iOS

-

Android

+

Android

@@ -140,5 +155,16 @@

Android

--> + diff --git a/lib/ionic/serve.js b/lib/ionic/serve.js index 55a74e9687..a722beab5f 100644 --- a/lib/ionic/serve.js +++ b/lib/ionic/serve.js @@ -13,10 +13,12 @@ var fs = require('fs'), Task = require('./task').Task, proxyMiddleware = require('proxy-middleware'), url = require('url'), + xml2js = require('xml2js'), IonicStats = require('./stats').IonicStats; var DEFAULT_HTTP_PORT = 8100; var DEFAULT_LIVE_RELOAD_PORT = 35729; +var IONIC_LAB_URL = '/ionic-lab'; var IonicTask = function() {}; @@ -167,7 +169,7 @@ IonicTask.prototype.start = function(ionic) { console.log('Watching :'.green.bold, self.watchPatterns); if(self.launchLab) { var open = require('open'); - open( self.host(self.port) + '/lab' ); + open( self.host(self.port) + IONIC_LAB_URL ); } else if(self.launchBrowser) { var open = require('open'); open( self.host(self.port) ); @@ -202,7 +204,7 @@ IonicTask.prototype.start = function(ionic) { var done = finalhandler(req, res); var urlParsed = url.parse(req.url, true); - var platformOverride = urlParsed.query.ionicplatform; + var platformOverride = urlParsed.query && urlParsed.query.ionicplatform; var platformUrl = getPlatformUrl(req); if(platformUrl) { @@ -237,14 +239,37 @@ IonicTask.prototype.start = function(ionic) { return; } - if(req.url === '/lab') { - fs.readFile(path.resolve(path.join(__dirname, 'assets/preview.html')), function(err, buf) { - if(err) { - res.end('404'); - } - res.setHeader('Content-Type', 'text/html'); - res.end(buf); - }); + if(req.url === IONIC_LAB_URL) { + // Serve the lab page with the given object with template data + var labServeFn = function(context) { + fs.readFile(path.resolve(path.join(__dirname, 'assets/preview.html')), function(err, buf) { + var html; + if(err) { + res.end('404'); + } else { + html = buf.toString('utf8'); + html = html.replace('//INSERT_JSON_HERE', 'var BOOTSTRAP = ' + JSON.stringify(context || {})); + } + res.setHeader('Content-Type', 'text/html'); + res.end(html); + }); + }; + + // If the config.xml file exists, let's parse it for some nice features like + // showing the name of the app in the title + if(fs.existsSync('config.xml')) { + fs.readFile(path.resolve('config.xml'), function(err, buf) { + var xml = buf.toString('utf8'); + xml2js.parseString(xml, function (err, result) { + labServeFn({ + appName: result.widget.name[0] + }); + }); + }); + } else { + labServeFn(); + } + return; } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1100c36b64..d623d0718d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,12 +9,12 @@ "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@>=1.1.9 <1.2.0", + "from": "readable-stream@1.1.13", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@1.0.1", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -24,29 +24,29 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "zip-stream": { "version": "0.1.4", - "from": "zip-stream@>=0.1.0 <0.2.0", + "from": "zip-stream@0.1.4", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.1.4.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33", - "from": "readable-stream@>=1.0.24 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "version": "1.0.33-1", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@1.0.1", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -56,46 +56,46 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "lodash.defaults": { "version": "2.4.1", - "from": "lodash.defaults@>=2.4.1 <2.5.0", + "from": "lodash.defaults@2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash.keys": { "version": "2.4.1", - "from": "lodash.keys@>=2.4.1 <2.5.0", + "from": "lodash.keys@2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "lodash._isnative@>=2.4.1 <2.5.0", + "from": "lodash._isnative@2.4.1", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "lodash.isobject@>=2.4.1 <2.5.0", + "from": "lodash.isobject@2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz" }, "lodash._shimkeys": { "version": "2.4.1", - "from": "lodash._shimkeys@>=2.4.1 <2.5.0", + "from": "lodash._shimkeys@2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz" } } }, "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@>=2.4.1 <2.5.0", + "from": "lodash._objecttypes@2.4.1", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -104,17 +104,17 @@ }, "lazystream": { "version": "0.1.0", - "from": "lazystream@>=0.1.0 <0.2.0", + "from": "lazystream@0.1.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33", - "from": "readable-stream@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "version": "1.0.33-1", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@1.0.1", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -124,12 +124,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -138,47 +138,47 @@ }, "file-utils": { "version": "0.1.5", - "from": "file-utils@>=0.1.5 <0.2.0", + "from": "file-utils@0.1.5", "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", "dependencies": { "lodash": { "version": "2.1.0", - "from": "lodash@>=2.1.0 <2.2.0", + "from": "lodash@2.1.0", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz" }, "iconv-lite": { "version": "0.2.11", - "from": "iconv-lite@>=0.2.11 <0.3.0", + "from": "iconv-lite@0.2.11", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz" }, "rimraf": { "version": "2.2.8", - "from": "rimraf@>=2.2.2 <2.3.0", + "from": "rimraf@2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" }, "glob": { "version": "3.2.11", - "from": "glob@>=3.2.6 <3.3.0", + "from": "glob@3.2.11", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@>=0.3.0 <0.4.0", + "from": "minimatch@0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@>=2.0.0 <3.0.0", + "from": "lru-cache@2.5.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@>=1.0.0 <1.1.0", + "from": "sigmund@1.0.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -187,65 +187,65 @@ }, "minimatch": { "version": "0.2.14", - "from": "minimatch@>=0.2.12 <0.3.0", + "from": "minimatch@0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@>=2.0.0 <3.0.0", + "from": "lru-cache@2.5.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@>=1.0.0 <1.1.0", + "from": "sigmund@1.0.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "findup-sync": { "version": "0.1.3", - "from": "findup-sync@>=0.1.2 <0.2.0", + "from": "findup-sync@0.1.3", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "lodash": { "version": "2.4.1", - "from": "lodash@>=2.4.1 <2.5.0", + "from": "lodash@2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "isbinaryfile": { "version": "0.1.9", - "from": "isbinaryfile@>=0.1.9 <0.2.0", + "from": "isbinaryfile@0.1.9", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz" } } }, "lodash": { "version": "2.4.1", - "from": "lodash@>=2.4.1 <2.5.0", + "from": "lodash@2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "colors": { "version": "0.6.2", - "from": "colors@0.6.2", + "from": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz" }, "connect": { "version": "3.1.1", - "from": "connect@3.1.1", + "from": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", "resolved": "https://registry.npmjs.org/connect/-/connect-3.1.1.tgz", "dependencies": { "debug": { "version": "1.0.4", - "from": "debug@1.0.4", + "from": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -264,12 +264,12 @@ }, "parseurl": { "version": "1.3.0", - "from": "parseurl@>=1.3.0 <1.4.0", + "from": "parseurl@1.3.0", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } @@ -281,40 +281,40 @@ }, "cross-spawn": { "version": "0.2.3", - "from": "cross-spawn@0.2.3", + "from": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.3.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@>=2.5.0 <3.0.0", + "from": "lru-cache@2.5.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" } } }, "event-stream": { "version": "3.0.20", - "from": "event-stream@>=3.0.0 <3.1.0", + "from": "event-stream@3.0.20", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.0.20.tgz", "dependencies": { "through": { "version": "2.3.6", - "from": "through@>=2.3.1 <2.4.0", + "from": "through@2.3.6", "resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz" }, "duplexer": { "version": "0.1.1", - "from": "duplexer@>=0.1.1 <0.2.0", + "from": "duplexer@0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" }, "from": { "version": "0.1.3", - "from": "from@>=0.0.0 <1.0.0", + "from": "from@0.1.3", "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz" }, "map-stream": { - "version": "0.0.5", - "from": "map-stream@>=0.0.3 <0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.5.tgz" + "version": "0.0.4", + "from": "map-stream@0.0.4", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.4.tgz" }, "pause-stream": { "version": "0.0.11", @@ -323,29 +323,29 @@ }, "split": { "version": "0.2.10", - "from": "split@>=0.2.0 <0.3.0", + "from": "split@0.2.10", "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz" }, "stream-combiner": { "version": "0.0.4", - "from": "stream-combiner@>=0.0.3 <0.1.0", + "from": "stream-combiner@0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" } } }, "finalhandler": { "version": "0.2.0", - "from": "finalhandler@0.2.0", + "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.2.0.tgz", "dependencies": { "debug": { "version": "2.0.0", - "from": "debug@>=2.0.0 <2.1.0", + "from": "debug@2.0.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", "dependencies": { "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" } } @@ -359,13 +359,13 @@ }, "form-data": { "version": "0.1.4", - "from": "form-data@0.1.4", + "from": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", "dependencies": { "combined-stream": { - "version": "0.0.7", - "from": "combined-stream@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "version": "0.0.5", + "from": "combined-stream@0.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.5.tgz", "dependencies": { "delayed-stream": { "version": "0.0.5", @@ -376,85 +376,85 @@ }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.11 <1.3.0", + "from": "mime@1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "async": { "version": "0.9.0", - "from": "async@>=0.9.0 <0.10.0", + "from": "async@0.9.0", "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" } } }, "gulp": { "version": "3.8.10", - "from": "gulp@>=3.8.8 <3.9.0", + "from": "gulp@", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.8.10.tgz", "dependencies": { "archy": { "version": "1.0.0", - "from": "archy@>=1.0.0 <2.0.0", + "from": "archy@^1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" }, "chalk": { "version": "0.5.1", - "from": "chalk@>=0.5.0 <0.6.0", + "from": "chalk@^0.5.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "dependencies": { "ansi-styles": { "version": "1.1.0", - "from": "ansi-styles@>=1.1.0 <2.0.0", + "from": "ansi-styles@^1.1.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz" }, "escape-string-regexp": { "version": "1.0.2", - "from": "escape-string-regexp@>=1.0.0 <2.0.0", + "from": "escape-string-regexp@^1.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz" }, "has-ansi": { "version": "0.1.0", - "from": "has-ansi@>=0.1.0 <0.2.0", + "from": "has-ansi@^0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@>=0.2.1 <0.3.0", + "from": "ansi-regex@^0.2.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "strip-ansi": { "version": "0.3.0", - "from": "strip-ansi@>=0.3.0 <0.4.0", + "from": "strip-ansi@^0.3.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "dependencies": { "ansi-regex": { "version": "0.2.1", - "from": "ansi-regex@>=0.2.1 <0.3.0", + "from": "ansi-regex@^0.2.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz" } } }, "supports-color": { "version": "0.2.0", - "from": "supports-color@>=0.2.0 <0.3.0", + "from": "supports-color@^0.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz" } } }, "deprecated": { "version": "0.0.1", - "from": "deprecated@>=0.0.1 <0.0.2", + "from": "deprecated@^0.0.1", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz" }, "gulp-util": { "version": "3.0.1", - "from": "gulp-util@>=3.0.0 <4.0.0", + "from": "gulp-util@^3.0.0", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.1.tgz", "dependencies": { "dateformat": { "version": "1.0.11", - "from": "dateformat@>=1.0.7-1.2.3 <2.0.0", + "from": "dateformat@^1.0.7-1.2.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.11.tgz", "dependencies": { "get-stdin": { @@ -469,39 +469,39 @@ "dependencies": { "camelcase-keys": { "version": "1.0.0", - "from": "camelcase-keys@>=1.0.0 <2.0.0", + "from": "camelcase-keys@^1.0.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", "dependencies": { "camelcase": { "version": "1.0.2", - "from": "camelcase@>=1.0.1 <2.0.0", + "from": "camelcase@^1.0.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { "version": "1.0.0", - "from": "map-obj@>=1.0.0 <2.0.0", + "from": "map-obj@^1.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" } } }, "indent-string": { "version": "1.2.0", - "from": "indent-string@>=1.1.0 <2.0.0", + "from": "indent-string@^1.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.0.tgz", "dependencies": { "repeating": { "version": "1.1.0", - "from": "repeating@>=1.1.0 <2.0.0", + "from": "repeating@^1.1.0", "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.0.tgz", "dependencies": { "is-finite": { "version": "1.0.0", - "from": "is-finite@>=1.0.0 <2.0.0", + "from": "is-finite@^1.0.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.0.tgz" }, "meow": { "version": "1.0.0", - "from": "meow@>=1.0.0 <2.0.0", + "from": "meow@^1.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-1.0.0.tgz" } } @@ -510,7 +510,7 @@ }, "object-assign": { "version": "1.0.0", - "from": "object-assign@>=1.0.0 <2.0.0", + "from": "object-assign@^1.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" } } @@ -519,56 +519,56 @@ }, "lodash": { "version": "2.4.1", - "from": "lodash@>=2.4.1 <2.5.0", + "from": "lodash@^2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "lodash._reinterpolate": { "version": "2.4.1", - "from": "lodash._reinterpolate@>=2.4.1 <3.0.0", + "from": "lodash._reinterpolate@^2.4.1", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz" }, "lodash.template": { "version": "2.4.1", - "from": "lodash.template@>=2.4.1 <3.0.0", + "from": "lodash.template@^2.4.1", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", "dependencies": { "lodash.defaults": { "version": "2.4.1", - "from": "lodash.defaults@>=2.4.1 <2.5.0", + "from": "lodash.defaults@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@>=2.4.1 <2.5.0", + "from": "lodash._objecttypes@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash.escape": { "version": "2.4.1", - "from": "lodash.escape@>=2.4.1 <2.5.0", + "from": "lodash.escape@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", "dependencies": { "lodash._escapehtmlchar": { "version": "2.4.1", - "from": "lodash._escapehtmlchar@>=2.4.1 <2.5.0", + "from": "lodash._escapehtmlchar@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", + "from": "lodash._htmlescapes@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } }, "lodash._reunescapedhtml": { "version": "2.4.1", - "from": "lodash._reunescapedhtml@>=2.4.1 <2.5.0", + "from": "lodash._reunescapedhtml@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", "dependencies": { "lodash._htmlescapes": { "version": "2.4.1", - "from": "lodash._htmlescapes@>=2.4.1 <2.5.0", + "from": "lodash._htmlescapes@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz" } } @@ -577,39 +577,39 @@ }, "lodash._escapestringchar": { "version": "2.4.1", - "from": "lodash._escapestringchar@>=2.4.1 <2.5.0", + "from": "lodash._escapestringchar@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz" }, "lodash.keys": { "version": "2.4.1", - "from": "lodash.keys@>=2.4.1 <2.5.0", + "from": "lodash.keys@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", "dependencies": { "lodash._isnative": { "version": "2.4.1", - "from": "lodash._isnative@>=2.4.1 <2.5.0", + "from": "lodash._isnative@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz" }, "lodash.isobject": { "version": "2.4.1", - "from": "lodash.isobject@>=2.4.1 <2.5.0", + "from": "lodash.isobject@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@>=2.4.1 <2.5.0", + "from": "lodash._objecttypes@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } }, "lodash._shimkeys": { "version": "2.4.1", - "from": "lodash._shimkeys@>=2.4.1 <2.5.0", + "from": "lodash._shimkeys@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", "dependencies": { "lodash._objecttypes": { "version": "2.4.1", - "from": "lodash._objecttypes@>=2.4.1 <2.5.0", + "from": "lodash._objecttypes@~2.4.1", "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz" } } @@ -618,19 +618,19 @@ }, "lodash.templatesettings": { "version": "2.4.1", - "from": "lodash.templatesettings@>=2.4.1 <2.5.0", + "from": "lodash.templatesettings@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz" }, "lodash.values": { "version": "2.4.1", - "from": "lodash.values@>=2.4.1 <2.5.0", + "from": "lodash.values@~2.4.1", "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz" } } }, "multipipe": { "version": "0.1.2", - "from": "multipipe@>=0.1.0 <0.2.0", + "from": "multipipe@^0.1.0", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "dependencies": { "duplexer2": { @@ -640,12 +640,12 @@ "dependencies": { "readable-stream": { "version": "1.1.13", - "from": "readable-stream@>=1.1.9 <1.2.0", + "from": "readable-stream@~1.1.9", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@~1.0.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -655,12 +655,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@~0.10.x", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@~2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -671,7 +671,7 @@ }, "through2": { "version": "0.6.3", - "from": "through2@>=0.6.1 <0.7.0", + "from": "through2@^0.6.1", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { @@ -681,7 +681,7 @@ "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@~1.0.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -691,12 +691,12 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@~0.10.x", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@~2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -710,17 +710,17 @@ }, "vinyl": { "version": "0.4.6", - "from": "vinyl@>=0.4.0 <0.5.0", + "from": "vinyl@^0.4.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "dependencies": { "clone": { "version": "0.2.0", - "from": "clone@>=0.2.0 <0.3.0", + "from": "clone@^0.2.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" }, "clone-stats": { "version": "0.0.1", - "from": "clone-stats@>=0.0.1 <0.0.2", + "from": "clone-stats@^0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -729,42 +729,42 @@ }, "interpret": { "version": "0.3.8", - "from": "interpret@>=0.3.2 <0.4.0", + "from": "interpret@^0.3.2", "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.3.8.tgz" }, "liftoff": { "version": "0.13.6", - "from": "liftoff@>=0.13.2 <0.14.0", + "from": "liftoff@^0.13.2", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-0.13.6.tgz", "dependencies": { "findup-sync": { "version": "0.1.3", - "from": "findup-sync@>=0.1.2 <0.2.0", + "from": "findup-sync@~0.1.2", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", "dependencies": { "glob": { "version": "3.2.11", - "from": "glob@>=3.2.9 <3.3.0", + "from": "glob@~3.2.9", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <3.0.0", + "from": "inherits@2", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "minimatch": { "version": "0.3.0", - "from": "minimatch@>=0.3.0 <0.4.0", + "from": "minimatch@0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@>=2.0.0 <3.0.0", + "from": "lru-cache@2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@>=1.0.0 <1.1.0", + "from": "sigmund@~1.0.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -773,51 +773,51 @@ }, "lodash": { "version": "2.4.1", - "from": "lodash@>=2.4.1 <2.5.0", + "from": "lodash@~2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" } } }, "resolve": { "version": "1.0.0", - "from": "resolve@>=1.0.0 <1.1.0", + "from": "resolve@~1.0.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.0.0.tgz" }, "extend": { "version": "1.3.0", - "from": "extend@>=1.3.0 <1.4.0", + "from": "extend@~1.3.0", "resolved": "https://registry.npmjs.org/extend/-/extend-1.3.0.tgz" }, "flagged-respawn": { "version": "0.3.1", - "from": "flagged-respawn@>=0.3.0 <0.4.0", + "from": "flagged-respawn@~0.3.0", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.1.tgz" } } }, "minimist": { "version": "1.1.0", - "from": "minimist@>=1.1.0 <2.0.0", + "from": "minimist@^1.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.0.tgz" }, "orchestrator": { "version": "0.3.7", - "from": "orchestrator@>=0.3.0 <0.4.0", + "from": "orchestrator@^0.3.0", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", "dependencies": { "end-of-stream": { "version": "0.1.5", - "from": "end-of-stream@>=0.1.5 <0.2.0", + "from": "end-of-stream@~0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "dependencies": { "once": { "version": "1.3.1", - "from": "once@>=1.3.0 <1.4.0", + "from": "once@~1.3.0", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@>=1.0.0 <2.0.0", + "from": "wrappy@1", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -826,41 +826,41 @@ }, "sequencify": { "version": "0.0.7", - "from": "sequencify@>=0.0.7 <0.1.0", + "from": "sequencify@~0.0.7", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz" }, "stream-consume": { "version": "0.1.0", - "from": "stream-consume@>=0.1.0 <0.2.0", + "from": "stream-consume@~0.1.0", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" } } }, "pretty-hrtime": { "version": "0.2.2", - "from": "pretty-hrtime@>=0.2.0 <0.3.0", + "from": "pretty-hrtime@^0.2.0", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz" }, "semver": { "version": "4.1.0", - "from": "semver@>=4.1.0 <5.0.0", + "from": "semver@^4.1.0", "resolved": "https://registry.npmjs.org/semver/-/semver-4.1.0.tgz" }, "tildify": { "version": "1.0.0", - "from": "tildify@>=1.0.0 <2.0.0", + "from": "tildify@^1.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", "dependencies": { "user-home": { "version": "1.1.0", - "from": "user-home@>=1.0.0 <2.0.0", + "from": "user-home@^1.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.0.tgz" } } }, "v8flags": { "version": "1.0.5", - "from": "v8flags@>=1.0.1 <2.0.0", + "from": "v8flags@^1.0.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-1.0.5.tgz" } } @@ -872,7 +872,7 @@ }, "npm": { "version": "2.1.3", - "from": "npm@2.1.3", + "from": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", "resolved": "https://registry.npmjs.org/npm/-/npm-2.1.3.tgz", "dependencies": { "abbrev": { @@ -1436,22 +1436,22 @@ }, "open": { "version": "0.0.5", - "from": "open@0.0.5", + "from": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz" }, "optimist": { "version": "0.6.0", - "from": "optimist@0.6.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.0.tgz", "dependencies": { "wordwrap": { "version": "0.0.2", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "wordwrap@0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "minimist@0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -1463,103 +1463,103 @@ }, "prompt": { "version": "0.2.12", - "from": "prompt@0.2.12", + "from": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.12.tgz", "dependencies": { "pkginfo": { "version": "0.3.0", - "from": "pkginfo@>=0.0.0 <1.0.0", + "from": "pkginfo@0.3.0", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.0.tgz" }, "read": { "version": "1.0.5", - "from": "read@>=1.0.0 <1.1.0", + "from": "read@1.0.5", "resolved": "https://registry.npmjs.org/read/-/read-1.0.5.tgz", "dependencies": { "mute-stream": { "version": "0.0.4", - "from": "mute-stream@>=0.0.4 <0.1.0", + "from": "mute-stream@0.0.4", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz" } } }, "revalidator": { "version": "0.1.8", - "from": "revalidator@>=0.1.0 <0.2.0", + "from": "revalidator@0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz" }, "utile": { "version": "0.2.1", - "from": "utile@>=0.2.0 <0.3.0", + "from": "utile@0.2.1", "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.9 <0.3.0", + "from": "async@0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "deep-equal": { "version": "0.2.1", - "from": "deep-equal@*", + "from": "deep-equal@0.2.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.1.tgz" }, "i": { "version": "0.3.2", - "from": "i@>=0.3.0 <0.4.0", + "from": "i@0.3.2", "resolved": "https://registry.npmjs.org/i/-/i-0.3.2.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@>=0.0.0 <1.0.0", + "from": "mkdirp@0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@>=2.0.0 <3.0.0", + "from": "rimraf@2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "winston": { "version": "0.6.2", - "from": "winston@>=0.6.0 <0.7.0", + "from": "winston@0.6.2", "resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz", "dependencies": { "async": { "version": "0.1.22", - "from": "async@>=0.1.0 <0.2.0", + "from": "async@0.1.22", "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz" }, "cycle": { "version": "1.0.3", - "from": "cycle@>=1.0.0 <1.1.0", + "from": "cycle@1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz" }, "eyes": { "version": "0.1.8", - "from": "eyes@>=0.1.0 <0.2.0", + "from": "eyes@0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" }, "pkginfo": { "version": "0.2.3", - "from": "pkginfo@>=0.2.0 <0.3.0", + "from": "pkginfo@0.2.3", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz" }, "request": { "version": "2.9.203", - "from": "request@>=2.9.0 <2.10.0", + "from": "request@2.9.203", "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz" }, "stack-trace": { "version": "0.0.9", - "from": "stack-trace@>=0.0.0 <0.1.0", + "from": "stack-trace@0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz" } } @@ -1568,52 +1568,52 @@ }, "proxy-middleware": { "version": "0.7.0", - "from": "proxy-middleware@>=0.7.0 <0.8.0", + "from": "proxy-middleware@0.7.0", "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.7.0.tgz" }, "q": { "version": "1.0.1", - "from": "q@1.0.1", + "from": "https://registry.npmjs.org/q/-/q-1.0.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz" }, "request": { "version": "2.27.0", - "from": "request@2.27.0", + "from": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", "resolved": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", "dependencies": { "qs": { "version": "0.6.6", - "from": "qs@>=0.6.0 <0.7.0", + "from": "qs@0.6.6", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" }, "json-stringify-safe": { "version": "5.0.0", - "from": "json-stringify-safe@>=5.0.0 <5.1.0", + "from": "json-stringify-safe@5.0.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" }, "forever-agent": { "version": "0.5.2", - "from": "forever-agent@>=0.5.0 <0.6.0", + "from": "forever-agent@0.5.2", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" }, "tunnel-agent": { "version": "0.3.0", - "from": "tunnel-agent@>=0.3.0 <0.4.0", + "from": "tunnel-agent@0.3.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" }, "http-signature": { "version": "0.10.0", - "from": "http-signature@>=0.10.0 <0.11.0", + "from": "http-signature@0.10.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", "dependencies": { "assert-plus": { "version": "0.1.2", - "from": "assert-plus@0.1.2", + "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" }, "asn1": { "version": "0.1.11", - "from": "asn1@0.1.11", + "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { @@ -1625,179 +1625,179 @@ }, "hawk": { "version": "1.0.0", - "from": "hawk@>=1.0.0 <1.1.0", + "from": "hawk@1.0.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", "dependencies": { "hoek": { "version": "0.9.1", - "from": "hoek@>=0.9.0 <0.10.0", + "from": "hoek@0.9.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" }, "boom": { "version": "0.4.2", - "from": "boom@>=0.4.0 <0.5.0", + "from": "boom@0.4.2", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@>=0.2.0 <0.3.0", + "from": "cryptiles@0.2.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" }, "sntp": { "version": "0.2.4", - "from": "sntp@>=0.2.0 <0.3.0", + "from": "sntp@0.2.4", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" } } }, "aws-sign": { "version": "0.3.0", - "from": "aws-sign@>=0.3.0 <0.4.0", + "from": "aws-sign@0.3.0", "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz" }, "oauth-sign": { "version": "0.3.0", - "from": "oauth-sign@>=0.3.0 <0.4.0", + "from": "oauth-sign@0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" }, "cookie-jar": { "version": "0.3.0", - "from": "cookie-jar@>=0.3.0 <0.4.0", + "from": "cookie-jar@0.3.0", "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz" }, "node-uuid": { - "version": "1.4.2", - "from": "node-uuid@>=1.4.0 <1.5.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "version": "1.4.1", + "from": "node-uuid@1.4.1", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.9 <1.3.0", + "from": "mime@1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } }, "serve-static": { "version": "1.7.1", - "from": "serve-static@1.7.1", + "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.7.1.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.7.1.tgz", "dependencies": { "escape-html": { "version": "1.0.1", - "from": "escape-html@1.0.1", + "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz" }, "parseurl": { "version": "1.3.0", - "from": "parseurl@>=1.3.0 <1.4.0", + "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz" }, "send": { "version": "0.10.1", - "from": "send@0.10.1", + "from": "https://registry.npmjs.org/send/-/send-0.10.1.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.10.1.tgz", "dependencies": { "debug": { "version": "2.1.0", - "from": "debug@>=2.1.0 <2.2.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.0.tgz" }, "depd": { "version": "1.0.0", - "from": "depd@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.0.tgz" }, "destroy": { "version": "1.0.3", - "from": "destroy@1.0.3", + "from": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz" }, "etag": { "version": "1.5.1", - "from": "etag@>=1.5.0 <1.6.0", + "from": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.5.1.tgz", "dependencies": { "crc": { "version": "3.2.1", - "from": "crc@3.2.1", + "from": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz", "resolved": "https://registry.npmjs.org/crc/-/crc-3.2.1.tgz" } } }, "fresh": { "version": "0.2.4", - "from": "fresh@0.2.4", + "from": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.4.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@1.2.11", + "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "ms": { "version": "0.6.2", - "from": "ms@0.6.2", + "from": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz" }, "on-finished": { "version": "2.1.1", - "from": "on-finished@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.1.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.1.tgz", "dependencies": { "ee-first": { "version": "1.1.0", - "from": "ee-first@1.1.0", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz" } } }, "range-parser": { "version": "1.0.2", - "from": "range-parser@>=1.0.2 <1.1.0", + "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz" } } }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" } } }, "shelljs": { "version": "0.2.6", - "from": "shelljs@0.2.6", + "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz" }, "tiny-lr-fork": { "version": "0.0.5", - "from": "tiny-lr-fork@0.0.5", + "from": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", "resolved": "https://registry.npmjs.org/tiny-lr-fork/-/tiny-lr-fork-0.0.5.tgz", "dependencies": { "qs": { "version": "0.5.6", - "from": "qs@>=0.5.2 <0.6.0", + "from": "qs@0.5.6", "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" }, "faye-websocket": { "version": "0.4.4", - "from": "faye-websocket@>=0.4.3 <0.5.0", + "from": "faye-websocket@0.4.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz" }, "noptify": { "version": "0.0.3", - "from": "noptify@>=0.0.3 <0.1.0", + "from": "noptify@0.0.3", "resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz", "dependencies": { "nopt": { "version": "2.0.0", - "from": "nopt@>=2.0.0 <2.1.0", + "from": "nopt@2.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz", "dependencies": { "abbrev": { "version": "1.0.5", - "from": "abbrev@>=1.0.0 <2.0.0", + "from": "abbrev@1.0.5", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" } } @@ -1806,7 +1806,7 @@ }, "debug": { "version": "0.7.4", - "from": "debug@>=0.7.0 <0.8.0", + "from": "debug@0.7.4", "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" } } @@ -1818,92 +1818,92 @@ }, "unzip": { "version": "0.1.9", - "from": "unzip@0.1.9", + "from": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.9.tgz", "dependencies": { "fstream": { "version": "0.1.31", - "from": "fstream@>=0.1.21 <0.2.0", + "from": "fstream@0.1.31", "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", "dependencies": { "graceful-fs": { - "version": "3.0.5", - "from": "graceful-fs@>=3.0.2 <3.1.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.4", + "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.0 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@>=0.0.0 <1.0.0", + "from": "mkdirp@0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "rimraf": { "version": "2.2.8", - "from": "rimraf@>=2.0.0 <3.0.0", + "from": "rimraf@2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" } } }, "pullstream": { "version": "0.4.1", - "from": "pullstream@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", "dependencies": { "over": { "version": "0.0.5", - "from": "over@>=0.0.5 <1.0.0", + "from": "over@0.0.5", "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz" }, "slice-stream": { "version": "1.0.0", - "from": "slice-stream@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz" } } }, "binary": { "version": "0.3.0", - "from": "binary@>=0.3.0 <0.4.0", + "from": "binary@0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "dependencies": { "chainsaw": { "version": "0.1.0", - "from": "chainsaw@>=0.1.0 <0.2.0", + "from": "chainsaw@0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "dependencies": { "traverse": { "version": "0.3.9", - "from": "traverse@>=0.3.0 <0.4.0", + "from": "traverse@0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" } } }, "buffers": { "version": "0.1.1", - "from": "buffers@>=0.1.1 <0.2.0", + "from": "buffers@0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } }, "readable-stream": { - "version": "1.0.33", - "from": "readable-stream@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "version": "1.0.33-1", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@1.0.1", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -1913,29 +1913,29 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "setimmediate": { "version": "1.0.2", - "from": "setimmediate@>=1.0.1 <1.1.0", + "from": "setimmediate@1.0.2", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.2.tgz" }, "match-stream": { "version": "0.0.2", - "from": "match-stream@>=0.0.2 <0.1.0", + "from": "match-stream@0.0.2", "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", "dependencies": { "buffers": { "version": "0.1.1", - "from": "buffers@>=0.1.1 <0.2.0", + "from": "buffers@0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" } } @@ -1944,44 +1944,32 @@ }, "vinyl-fs": { "version": "0.3.7", - "from": "vinyl-fs@0.3.7", + "from": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.7.tgz", "dependencies": { "glob-stream": { - "version": "3.1.18", - "from": "glob-stream@>=3.1.5 <4.0.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "version": "3.1.15", + "from": "glob-stream@3.1.15", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.15.tgz", "dependencies": { "glob": { - "version": "4.3.1", - "from": "glob@>=4.3.1 <5.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.1.tgz", + "version": "4.0.6", + "from": "glob@4.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", "dependencies": { - "inflight": { - "version": "1.0.4", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", - "dependencies": { - "wrappy": { - "version": "1.0.1", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" - } - } - }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "once": { "version": "1.3.1", - "from": "once@>=1.3.0 <2.0.0", + "from": "once@1.3.1", "resolved": "https://registry.npmjs.org/once/-/once-1.3.1.tgz", "dependencies": { "wrappy": { "version": "1.0.1", - "from": "wrappy@>=1.0.0 <2.0.0", + "from": "wrappy@1.0.1", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" } } @@ -1989,103 +1977,89 @@ } }, "minimatch": { - "version": "2.0.1", - "from": "minimatch@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.1.tgz", + "version": "1.0.0", + "from": "minimatch@1.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", "dependencies": { - "brace-expansion": { - "version": "1.0.1", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.0.1.tgz", - "dependencies": { - "balanced-match": { - "version": "0.2.0", - "from": "balanced-match@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.0.tgz" - }, - "concat-map": { - "version": "0.0.0", - "from": "concat-map@0.0.0", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.0.tgz" - } - } + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2.5.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } }, "ordered-read-streams": { - "version": "0.1.0", - "from": "ordered-read-streams@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz" + "version": "0.0.8", + "from": "ordered-read-streams@0.0.8", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.0.8.tgz" }, "glob2base": { - "version": "0.0.12", - "from": "glob2base@>=0.0.12 <0.0.13", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "dependencies": { - "find-index": { - "version": "0.1.1", - "from": "find-index@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" - } - } + "version": "0.0.11", + "from": "glob2base@0.0.11", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.11.tgz" }, "unique-stream": { "version": "1.0.0", - "from": "unique-stream@>=1.0.0 <2.0.0", + "from": "unique-stream@1.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" } } }, "glob-watcher": { "version": "0.0.6", - "from": "glob-watcher@>=0.0.6 <0.0.7", + "from": "glob-watcher@0.0.6", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "dependencies": { "gaze": { "version": "0.5.1", - "from": "gaze@>=0.5.1 <0.6.0", + "from": "gaze@0.5.1", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.1.tgz", "dependencies": { "globule": { "version": "0.1.0", - "from": "globule@>=0.1.0 <0.2.0", + "from": "globule@0.1.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "dependencies": { "lodash": { "version": "1.0.1", - "from": "lodash@>=1.0.1 <1.1.0", + "from": "lodash@1.0.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.1.tgz" }, "glob": { "version": "3.1.21", - "from": "glob@>=3.1.21 <3.2.0", + "from": "glob@3.1.21", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "dependencies": { "graceful-fs": { "version": "1.2.3", - "from": "graceful-fs@>=1.2.0 <1.3.0", + "from": "graceful-fs@1.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" }, "inherits": { "version": "1.0.0", - "from": "inherits@>=1.0.0 <2.0.0", + "from": "inherits@1.0.0", "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz" } } }, "minimatch": { "version": "0.2.14", - "from": "minimatch@>=0.2.11 <0.3.0", + "from": "minimatch@0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "dependencies": { "lru-cache": { "version": "2.5.0", - "from": "lru-cache@>=2.0.0 <3.0.0", + "from": "lru-cache@2.5.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" }, "sigmund": { "version": "1.0.0", - "from": "sigmund@>=1.0.0 <1.1.0", + "from": "sigmund@1.0.0", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" } } @@ -2097,57 +2071,57 @@ } }, "graceful-fs": { - "version": "3.0.5", - "from": "graceful-fs@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + "version": "3.0.4", + "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" }, "lodash": { "version": "2.4.1", - "from": "lodash@>=2.4.1 <3.0.0", + "from": "lodash@2.4.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "mkdirp": { "version": "0.5.0", - "from": "mkdirp@>=0.5.0 <0.6.0", + "from": "mkdirp@0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "strip-bom": { "version": "1.0.0", - "from": "strip-bom@>=1.0.0 <2.0.0", + "from": "strip-bom@1.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "dependencies": { "first-chunk-stream": { "version": "1.0.0", - "from": "first-chunk-stream@>=1.0.0 <2.0.0", + "from": "first-chunk-stream@1.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" }, "is-utf8": { "version": "0.2.0", - "from": "is-utf8@>=0.2.0 <0.3.0", + "from": "is-utf8@0.2.0", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.0.tgz" } } }, "through2": { "version": "0.6.3", - "from": "through2@>=0.6.1 <0.7.0", + "from": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.3.tgz", "dependencies": { "readable-stream": { - "version": "1.0.33", - "from": "readable-stream@>=1.0.33-1 <1.1.0-0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "version": "1.0.33-1", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", "dependencies": { "core-util-is": { "version": "1.0.1", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "core-util-is@1.0.1", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" }, "isarray": { @@ -2157,36 +2131,31 @@ }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "string_decoder@0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "inherits@2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "xtend": { "version": "4.0.0", - "from": "xtend@>=4.0.0 <4.1.0-0", + "from": "xtend@4.0.0", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.0.tgz" } } }, "vinyl": { - "version": "0.4.6", - "from": "vinyl@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "version": "0.4.3", + "from": "vinyl@0.4.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.3.tgz", "dependencies": { - "clone": { - "version": "0.2.0", - "from": "clone@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" - }, "clone-stats": { "version": "0.0.1", - "from": "clone-stats@>=0.0.1 <0.0.2", + "from": "clone-stats@0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" } } @@ -2195,12 +2164,12 @@ }, "xml2js": { "version": "0.4.4", - "from": "xml2js@0.4.4", + "from": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", "dependencies": { "sax": { "version": "0.6.1", - "from": "sax@>=0.6.0 <0.7.0", + "from": "sax@0.6.x", "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz" }, "xmlbuilder": { @@ -2210,7 +2179,7 @@ "dependencies": { "lodash-node": { "version": "2.4.1", - "from": "lodash-node@>=2.4.1 <2.5.0", + "from": "lodash-node@~2.4.1", "resolved": "https://registry.npmjs.org/lodash-node/-/lodash-node-2.4.1.tgz" } } diff --git a/package.json b/package.json index 685ae01890..38968a4557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.9", + "version": "1.2.10", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 12117df3e0e15a2abef8960a658b5487accb159f Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 10 Dec 2014 11:50:18 -0600 Subject: [PATCH 313/850] Nicer lab styles --- lib/ionic/assets/preview.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ionic/assets/preview.html b/lib/ionic/assets/preview.html index 61c4b7e0ed..48ae25928f 100644 --- a/lib/ionic/assets/preview.html +++ b/lib/ionic/assets/preview.html @@ -45,7 +45,8 @@ opacity: 1; } h2 a { - color: #222; + font-size: 18px; + color: #6F7582; text-decoration: none; } .phone { @@ -53,8 +54,9 @@ margin: 20px; } .frame { - border: 6px solid #121316; + border: 1px solid transparent; border-radius: 3px; + box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.2); } #iphone-frame { top: 109px; From 8bab19c2fd5a60d67b0be7a677ca6d0c71cb0180 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 10 Dec 2014 11:50:29 -0600 Subject: [PATCH 314/850] vbump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38968a4557..ef64155837 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ionic", - "version": "1.2.10", + "version": "1.2.11", "preferGlobal": true, "description": "A tool for creating and developing Ionic Framework mobile apps.", "homepage": "http://ionicframework.com/", From 0796c9039d930b41127f4779f9f7c85512e46c96 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 10 Dec 2014 12:19:58 -0600 Subject: [PATCH 315/850] Better lab --- lib/ionic/assets/preview.html | 42 +++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/ionic/assets/preview.html b/lib/ionic/assets/preview.html index 48ae25928f..aad119a41f 100644 --- a/lib/ionic/assets/preview.html +++ b/lib/ionic/assets/preview.html @@ -1,18 +1,19 @@ - +