{ "id": "127606", "key": "TIMOB-16620", "fields": { "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "15939", "description": "2014 Sprint 07", "name": "2014 Sprint 07", "archived": true, "released": true, "releaseDate": "2014-04-11" }, { "id": "15942", "description": "2014 Sprint 07 Tooling", "name": "2014 Sprint 07 Tooling", "archived": true, "released": true, "releaseDate": "2014-04-11" }, { "id": "16098", "description": "2014 Sprint 09 Tooling", "name": "2014 Sprint 09 Tooling", "archived": true, "released": true, "releaseDate": "2014-05-08" }, { "id": "15422", "description": "Release 3.3.0", "name": "Release 3.3.0", "archived": false, "released": true, "releaseDate": "2014-07-16" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2014-05-09T17:48:39.000+0000", "created": "2014-03-12T23:42:29.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "qe-testadded" ], "versions": [], "issuelinks": [], "assignee": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "updated": "2014-05-30T18:09:51.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "13103", "name": "CLI", "description": "Node-based command line interface" } ], "description": "Currently custom templates can be built and placed in the templates folder in the root of each installed SDK.\r\n\r\nWould like to have an entry called *paths.templates* added to the *config.json* that could be searched for custom templates (and possibly overwrite/overrule those located in the {sdk}/templates folder) when creating a new project.\r\n\r\nThis would allow large enterprise orgs to:\r\n\r\n# share common project templates across development environments\r\n# reduce the time to adopt a new sdk (currently requires moving custom templates to the new sdk on all systems)\r\n# reduce required storage space caused by duplication\r\n", "attachment": [ { "id": "47013", "filename": "foo.zip", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2014-04-01T21:03:08.000+0000", "size": 3135604, "mimeType": "application/zip" } ], "flagged": false, "summary": "CLI: Add configurable source for new project templates", "creator": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "subtasks": [], "reporter": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "environment": "All supported development platforms", "comment": { "comments": [ { "id": "298989", "author": { "name": "ralcocer", "key": "ralcocer", "displayName": "Ricardo Alcocer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "@Praveen Innamuri should know about this and see if there's a way for Studio to use these CLI functions (TISTUD-6260)", "updateAuthor": { "name": "ralcocer", "key": "ralcocer", "displayName": "Ricardo Alcocer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-03-27T16:48:33.000+0000", "updated": "2014-03-27T16:50:38.000+0000" }, { "id": "299554", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "Titanium CLI master pull request: https://github.com/appcelerator/titanium/pull/125\n\nTitanium Mobile master pull request: https://github.com/appcelerator/titanium_mobile/pull/5569", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2014-04-01T21:02:46.000+0000", "updated": "2014-04-01T21:02:46.000+0000" }, { "id": "299558", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "There are a number of new ways to specify templates!\r\n\r\nh4. Default template\r\n\r\nThis will use the default template that comes with Titanium Mobile. It basically looks in the SDK's \"templates/app\" folder.\r\n\r\n{code}\r\nti create\r\n\r\n# -or-\r\n\r\nti create --template default\r\n{code}\r\n\r\nh4. Global template directory\r\n\r\nNow \"ti create\" will also scan all Titanium install locations for a \"templates\" directory containing the template you specified:\r\n\r\n{code}\r\n/Users/chris/Library/Application Support/Titanium/templates/mytemplate\r\n{code}\r\n\r\n{code}\r\nti create --template mytemplate\r\n{code}\r\n\r\nh4. Custom template paths\r\n\r\nYou can add more search paths via the {{paths.templates}} config option. You set this value to the path containing the templates.\r\n\r\nIn this example, {{/path/to/mytemplates}} contains a template called \"foo\".\r\n\r\n{code}\r\nti config paths.templates /path/to/mytemplates\r\n{code}\r\n\r\n{code}\r\nti create --template foo\r\n{code}\r\n\r\nh4. Local directory\r\n\r\n{code}\r\nti create --template /path/to/mytemplates/foo\r\n{code}\r\n\r\nh4. Local zip file\r\n\r\n{code}\r\nti create --template /path/to/myfootemplate.zip\r\n{code}\r\n\r\nh4. Remote zip file\r\n\r\n{code}\r\nti create --template http://www.chrisrocks.com/myfootemplate.zip\r\n{code}\r\n\r\nh4. New Template Structure\r\n\r\nTemplates now have a different file structure. You should have a \"templates\" directory containing all the files that will be automatically copied. You may have a \"hooks\" folder as well containing a Titanium CLI hook that allows you to tie into one of the several available hooks. Any other directory is ignored, so you could drop a package.json, readme, node_modules, whatever in the template directory.\r\n\r\n{code}\r\n├─┬ hooks (optional)\r\n│ └── mytemplatehook.js (optional)\r\n└─┬ template (should exist)\r\n ├── Resources (should exists, automatically created if it doesn't)\r\n └── tiapp.xml (should exist, automatically created if it doesn't)\r\n{code}\r\n\r\nh4. Template Hooks\r\n\r\nHooks give you the ability to do custom things when creating a project.\r\n\r\n{code}\r\nexports.init = function (logger, config, cli, appc) {\r\n\tlogger.log('HI FROM FOO HOOK!');\r\n\t\r\n\tcli.on('create.copyFiles', {\r\n\t\tpre: function (data) {\r\n\t\t\tlogger.log('COPYING FILES FROM ' + data.args[0] + ' TO ' + data.args[1]);\r\n\t\t}\r\n\t});\r\n\r\n\tcli.on('create.populateTiappXml', {\r\n\t\tpre: function (data) {\r\n\t\t\tlogger.log('POPULATING TIAPP.XML');\r\n\t\t\tdump(data.args[1]);\r\n\t\t\tdata.args[1].foo = \"bar\";\r\n\t\t}\r\n\t});\r\n\r\n\tcli.on('create.pre.platform.android', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.android [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.android', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.android [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\t// note: current the platform is called \"iphone\", so this hook won't fire right now\r\n\tcli.on('create.pre.platform.ios', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.ios [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.ios', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.ios [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.pre.platform.iphone', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.iphone [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.iphone', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.iphone [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.pre.platform.mobileweb', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.mobileweb [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.mobileweb', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.mobileweb [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.pre.platform.blackberry', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.blackberry [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.blackberry', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.blackberry [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.pre.platform.tizen', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.pre.platform.tizen [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\tcli.on('create.post.platform.tizen', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post.platform.tizen [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.post', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.post [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n\r\n\tcli.on('create.finalize', function (creator, next) {\r\n\t\tlogger.log(('[EVENT-HOOK] create.finalize [' + creator.projectType + ']').magenta);\r\n\t\tnext();\r\n\t});\r\n};\r\n{code}\r\n\r\nAvailable FUNCTION hooks:\r\n\r\n* {{create.copyFiles}}\r\n** You can change the source directory being copied\r\n** For example, you may not have a \"template\" directory, instead you could change it to something else\r\n* {{create.populateTiappXml}}\r\n** You can tweak properties, add properties, add modules, do whatever you want!\r\n\r\nAvailable EVENT hooks:\r\n\r\n* {{create.pre.platform.}}\r\n** This will fire for each platform that you are create the project for (i.e. android, iphone, mobileweb, etc)\r\n* {{create.post.platform.}}\r\n** This will fire for each platform that you are create the project for (i.e. android, iphone, mobileweb, etc)\r\n* {{create.post}}\r\n** Fired after all platforms have finished\r\n* {{create.finalize}}\r\n** Fired when the creation has completed or errored", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2014-04-01T21:21:36.000+0000", "updated": "2014-04-07T20:13:26.000+0000" }, { "id": "299559", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "Happy [~sfeather]?", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2014-04-01T21:21:58.000+0000", "updated": "2014-04-01T21:21:58.000+0000" }, { "id": "299566", "author": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "body": "Like the proverbial pig in mud. Thanks man.", "updateAuthor": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "created": "2014-04-01T22:54:34.000+0000", "updated": "2014-04-01T22:54:34.000+0000" }, { "id": "302158", "author": { "name": "dpandey", "key": "dpandey", "displayName": "Deepti Pandey", "active": true, "timeZone": "Asia/Kolkata" }, "body": "Reopening this ticket usig following configurations :\r\n\r\nMac :10.9.2\r\nStudio - 3.3.0.201404211130\r\nSDK - 3.3.0.v20140422163054\r\nacs-1.0.14\r\nalloy-1.4.0-dev\r\nnpm-1.3.2\r\ntitanium-3.3.0-dev\r\ntitanium-code-processor-1.1.1-beta1\r\nXcode :5.1.1\r\n\r\nTest steps followed are :\r\n1. Create a folder named \"templates\" at any location \r\n2. Copy attached example foo.zip (extracted version) \r\n3.On terminal write : ti config paths.templates /path/to/template folder created in first step.\r\n4.ti create --template foo \r\nand provide rest of the project creation details \r\n5.Error occured \r\n\r\n{code}\r\n/Users/deepti.pandey/Library/Application Support/Titanium/mobilesdk/osx/3.3.0.v20140422163054/cli/lib/creators/app.js:166\r\n\t\t\t\tfinalize();\r\n\t\t\t\t^\r\nTypeError: undefined is not a function\r\n at AppCreator. (/Users/deepti.pandey/Library/Application Support/Titanium/mobilesdk/osx/3.3.0.v20140422163054/cli/lib/creators/app.js:166:5)\r\n at /usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:119:25\r\n at AppCreator. (/usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:24:16)\r\n at CLI._fireHookCallback (/usr/local/lib/node_modules/titanium/lib/hook.js:269:12)\r\n at /usr/local/lib/node_modules/titanium/lib/hook.js:248:10\r\n at /usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:232:13\r\n at async.eachSeries (/usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:130:20)\r\n at _asyncMap (/usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:226:9)\r\n at Object.mapSeries (/usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:216:23)\r\n at async.series (/usr/local/lib/node_modules/titanium/node_modules/async/lib/async.js:549:19)\r\n{code}\r\n", "updateAuthor": { "name": "dpandey", "key": "dpandey", "displayName": "Deepti Pandey", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2014-04-23T10:23:35.000+0000", "updated": "2014-04-23T10:23:35.000+0000" }, { "id": "302718", "author": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "body": "[~sfeather] is this working for you? I'm wondering if the reopened report is an edge case.", "updateAuthor": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-04-28T16:04:15.000+0000", "updated": "2014-04-28T16:04:15.000+0000" }, { "id": "302720", "author": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "body": "@ingo Message seen, will be tomorrow or Wednesday before I can get to it to re-test.", "updateAuthor": { "name": "sfeather", "key": "sfeather", "displayName": "Stephen Feather", "active": true, "timeZone": "America/New_York" }, "created": "2014-04-28T16:10:26.000+0000", "updated": "2014-04-28T16:10:26.000+0000" }, { "id": "303583", "author": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "body": "Fixed.\r\n\r\nTitanium SDK master pull request: https://github.com/appcelerator/titanium_mobile/pull/5661", "updateAuthor": { "name": "cbarber", "key": "cbarber", "displayName": "Chris Barber", "active": true, "timeZone": "America/Chicago" }, "created": "2014-05-06T00:41:07.000+0000", "updated": "2014-05-06T00:41:07.000+0000" }, { "id": "307030", "author": { "name": "oromero", "key": "oromero", "displayName": "Olga Romero", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Tested with:\r\nMac osx 10.9.3 Mavericks\r\nAppcelerator Studio, build: 3.3.0.201405271647\r\nTitanium SDK, build: 3.3.0.v20140528144113 \r\nNode.JS Version: v0.10.13 \r\nNPM Version: 1.3.2 \r\nacs@1.0.14 \r\nalloy@1.4.0-beta \r\nnpm@1.3.2 \r\ntitanium@3.3.0-beta \r\ntitanium-code-processor@1.1.1\r\nh5. Actual result\r\n{code}\r\nPOPULATING TIAPP.XML\r\n{ id: 'com.appcelerator.olatest',\r\n name: 'olatest',\r\n url: 'http://',\r\n version: '1.0',\r\n guid: 'e1e932cc-a895-448d-ae6a-8c8cdaa11836',\r\n 'deployment-targets': \r\n { android: true,\r\n blackberry: true,\r\n ipad: true,\r\n iphone: true,\r\n mobileweb: true },\r\n 'sdk-version': '3.3.0.v20140528144113' }\r\n[INFO] Writing tiapp.xml\r\n[INFO] Project created successfully in 103ms\r\n{code}", "updateAuthor": { "name": "oromero", "key": "oromero", "displayName": "Olga Romero", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2014-05-30T17:51:56.000+0000", "updated": "2014-05-30T17:51:56.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }