@maccesar/titools 3.3.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +27 -61
  2. package/lib/cleanup.js +29 -0
  3. package/lib/commands/agents.js +8 -7
  4. package/lib/commands/skills.js +118 -23
  5. package/lib/config.js +13 -15
  6. package/lib/installer.js +5 -3
  7. package/lib/utils.js +36 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +188 -0
  10. package/skills/alloy-guides/references/CLI_TASKS.md +233 -0
  11. package/skills/alloy-guides/references/CONCEPTS.md +171 -0
  12. package/skills/alloy-guides/references/CONTROLLERS.md +279 -0
  13. package/skills/alloy-guides/references/MODELS.md +742 -0
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +482 -0
  15. package/skills/alloy-guides/references/PURGETSS.md +57 -0
  16. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +235 -0
  17. package/skills/alloy-guides/references/VIEWS_STYLES.md +375 -0
  18. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +102 -0
  19. package/skills/alloy-guides/references/VIEWS_XML.md +581 -0
  20. package/skills/alloy-guides/references/WIDGETS.md +160 -0
  21. package/skills/alloy-howtos/SKILL.md +179 -0
  22. package/skills/alloy-howtos/references/best_practices.md +121 -0
  23. package/skills/alloy-howtos/references/cli_reference.md +230 -0
  24. package/skills/alloy-howtos/references/config_files.md +158 -0
  25. package/skills/alloy-howtos/references/custom_tags.md +148 -0
  26. package/skills/alloy-howtos/references/debugging_troubleshooting.md +78 -0
  27. package/skills/alloy-howtos/references/samples.md +156 -0
  28. package/skills/purgetss/SKILL.md +6 -3
  29. package/skills/purgetss/references/EXAMPLES.md +8 -6
  30. package/skills/purgetss/references/app-branding.md +5 -0
  31. package/skills/purgetss/references/apply-directive.md +1 -1
  32. package/skills/purgetss/references/class-categories.md +1 -1
  33. package/skills/purgetss/references/class-index-properties.md +618 -0
  34. package/skills/purgetss/references/class-index.md +4 -610
  35. package/skills/purgetss/references/cli-commands.md +15 -0
  36. package/skills/purgetss/references/custom-fonts.md +39 -36
  37. package/skills/purgetss/references/custom-rules.md +1 -1
  38. package/skills/purgetss/references/customization-deep-dive.md +64 -1
  39. package/skills/purgetss/references/icon-fonts.md +2 -0
  40. package/skills/purgetss/references/migration-guide.md +53 -1
  41. package/skills/purgetss/references/multi-density-images.md +53 -2
  42. package/skills/purgetss/references/svg-pipeline.md +249 -0
  43. package/skills/purgetss/references/tikit-components.md +2 -2
  44. package/skills/purgetss/references/titanium-resets.md +2 -2
  45. package/skills/purgetss/references/ui-ux-design.md +7 -5
  46. package/skills/purgetss/references/version-history.md +12 -0
  47. package/skills/ti-api/SKILL.md +128 -0
  48. package/skills/ti-api/references/api-android.md +675 -0
  49. package/skills/ti-api/references/api-app-platform.md +636 -0
  50. package/skills/ti-api/references/api-core.md +764 -0
  51. package/skills/ti-api/references/api-data-network.md +641 -0
  52. package/skills/ti-api/references/api-media.md +655 -0
  53. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  54. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  55. package/skills/ti-api/references/api-modules-map.md +632 -0
  56. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  57. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  58. package/skills/ti-api/references/api-services.md +700 -0
  59. package/skills/ti-api/references/api-ui-android.md +499 -0
  60. package/skills/ti-api/references/api-ui-extras.md +702 -0
  61. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  62. package/skills/ti-api/references/api-ui-ios.md +756 -0
  63. package/skills/ti-api/references/api-ui-lists.md +581 -0
  64. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  65. package/skills/ti-api/references/api-ui-views.md +572 -0
  66. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  67. package/skills/ti-api/references/api-xml-global.md +743 -0
  68. package/skills/ti-guides/SKILL.md +82 -0
  69. package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
  70. package/skills/ti-guides/references/android-manifest.md +97 -0
  71. package/skills/ti-guides/references/app-distribution.md +373 -0
  72. package/skills/ti-guides/references/application-frameworks.md +366 -0
  73. package/skills/ti-guides/references/cli-reference.md +700 -0
  74. package/skills/ti-guides/references/coding-best-practices.md +150 -0
  75. package/skills/ti-guides/references/commonjs-advanced.md +279 -0
  76. package/skills/ti-guides/references/hello-world.md +99 -0
  77. package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
  78. package/skills/ti-guides/references/javascript-primer.md +402 -0
  79. package/skills/ti-guides/references/reserved-words.md +36 -0
  80. package/skills/ti-guides/references/resources.md +172 -0
  81. package/skills/ti-guides/references/style-and-conventions.md +104 -0
  82. package/skills/ti-guides/references/tiapp-config.md +655 -0
  83. package/skills/ti-howtos/SKILL.md +131 -0
  84. package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
  85. package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
  86. package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
  87. package/skills/ti-howtos/references/cross-platform-development.md +358 -0
  88. package/skills/ti-howtos/references/debugging-profiling.md +473 -0
  89. package/skills/ti-howtos/references/extending-titanium.md +684 -0
  90. package/skills/ti-howtos/references/google-maps-v2.md +172 -0
  91. package/skills/ti-howtos/references/ios-map-kit.md +149 -0
  92. package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
  93. package/skills/ti-howtos/references/local-data-sources.md +310 -0
  94. package/skills/ti-howtos/references/location-and-maps.md +267 -0
  95. package/skills/ti-howtos/references/media-apis.md +268 -0
  96. package/skills/ti-howtos/references/notification-services.md +539 -0
  97. package/skills/ti-howtos/references/remote-data-sources.md +339 -0
  98. package/skills/ti-howtos/references/tutorials.md +552 -0
  99. package/skills/ti-howtos/references/using-modules.md +182 -0
  100. package/skills/ti-howtos/references/web-content-integration.md +288 -0
  101. package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
@@ -0,0 +1,552 @@
1
+ # Titanium SDK tutorials
2
+
3
+ Practical tutorials and guides for building real Titanium applications.
4
+
5
+ ## RESTe - API integration
6
+
7
+ ### Overview
8
+ RESTe by Jason Kneen is a module for consuming web APIs in Titanium.
9
+
10
+ Benefits:
11
+ - Eliminates boilerplate HTTP code
12
+ - Auto-generates JavaScript API from config
13
+ - Supports Backbone.js models and collections in Alloy
14
+ - Works with any API (not just REST)
15
+
16
+ ### Installation
17
+
18
+ ```bash
19
+ npm install reste
20
+ ```
21
+
22
+ ### Basic configuration
23
+
24
+ `alloy.js`:
25
+
26
+ ```javascript
27
+ const reste = require('reste');
28
+ const api = new reste();
29
+
30
+ api.config({
31
+ debug: true, // Console logging
32
+ errorsAsObjects: true, // Return errors as objects (1.4.5+) - breaks apps written for 1.4.4 that handle errors differently
33
+ autoValidateParams: false, // Throw error if params missing
34
+ validatesSecureCertificate: false,
35
+ timeout: 4000,
36
+ url: 'https://api.example.com/', // Base URL
37
+ requestHeaders: {
38
+ 'X-API-Key': 'your-key-here',
39
+ 'Content-Type': 'application/json'
40
+ },
41
+ methods: [
42
+ {
43
+ name: 'getVideos',
44
+ get: 'videos'
45
+ },
46
+ {
47
+ name: 'getVideoById',
48
+ get: 'videos/'
49
+ },
50
+ {
51
+ name: 'createVideo',
52
+ post: 'videos'
53
+ }
54
+ ],
55
+ onError: (e, retry) => {
56
+ const dialog = Ti.UI.createAlertDialog({
57
+ title: 'Connection error',
58
+ message: 'Check your network and retry.',
59
+ buttonNames: ['Retry']
60
+ });
61
+ dialog.addEventListener('click', () => {
62
+ retry();
63
+ });
64
+ dialog.show();
65
+ }
66
+ });
67
+ ```
68
+
69
+ ### Usage
70
+
71
+ Auto-generated methods:
72
+
73
+ ```javascript
74
+ // Fetch single video
75
+ api.getVideoById({
76
+ videoId: 'abc123'
77
+ }, (video) => {
78
+ Ti.API.info(`Got video: ${video.title}`);
79
+ });
80
+
81
+ // Create video
82
+ api.createVideo({
83
+ body: {
84
+ title: 'My Video',
85
+ categoryId: 2
86
+ }
87
+ }, (response) => {
88
+ Ti.API.info(`Created: ${response.id}`);
89
+ });
90
+ ```
91
+
92
+ ### Backbone.js models and collections
93
+
94
+ Configuration:
95
+
96
+ ```javascript
97
+ api.config({
98
+ // ... other config
99
+ models: [{
100
+ name: 'video',
101
+ id: 'objectId', // Primary key field
102
+ read: 'getVideo',
103
+ create: 'createVideo',
104
+ update: 'updateVideo',
105
+ delete: 'deleteVideo',
106
+ collections: [{
107
+ name: 'videos',
108
+ content: 'results', // Array wrapper in response
109
+ read: 'getVideos'
110
+ }]
111
+ }]
112
+ });
113
+ ```
114
+
115
+ In an Alloy controller:
116
+
117
+ ```javascript
118
+ // Fetch collection
119
+ Alloy.Collections.videos.fetch();
120
+
121
+ // Or fetch with parameters
122
+ Alloy.Collections.videos.fetch({
123
+ data: { category: 'sports' }
124
+ });
125
+ ```
126
+
127
+ In an Alloy view:
128
+
129
+ ```xml
130
+ <TableView dataCollection="videos" onClick="selectVideo">
131
+ <TableViewRow model="{objectId}">
132
+ <Label class="title" text="{title}"/>
133
+ <Label class="subtitle" text="{description}"/>
134
+ </TableViewRow>
135
+ </TableView>
136
+ ```
137
+
138
+ ### RESTe advanced features
139
+
140
+ - Caching: built-in response caching
141
+ - Promises: use with `q.js` for Promise-based API calls
142
+ - Mock data: create models and collections on the fly for testing
143
+
144
+ ```javascript
145
+ const mockUser = api.createModel('users', {
146
+ id: 1,
147
+ name: 'Test User'
148
+ });
149
+ ```
150
+
151
+ - Backbone.js binding: use RESTe models directly with Alloy data binding without `<Model>` tags
152
+
153
+ ### Important notes
154
+
155
+ - Do not use `<Model>` or `<Collection>` tags with RESTe
156
+ - RESTe creates models and collections automatically
157
+ - Use data binding like normal Alloy collections
158
+ - Useful for mocking data during UI development
159
+
160
+ ### Mock data (on the fly)
161
+
162
+ ```javascript
163
+ // Create model without API
164
+ const videoModel = api.createModel('video', {
165
+ title: 'Test Video',
166
+ description: 'Mock data'
167
+ });
168
+
169
+ // Create collection
170
+ const videoCollection = api.createCollection('videos', [
171
+ { title: 'Video 1' },
172
+ { title: 'Video 2' }
173
+ ]);
174
+ ```
175
+
176
+ ### Resources
177
+
178
+ - npm: https://www.npmjs.com/package/reste
179
+ - GitHub: https://github.com/jasonkneen/reste
180
+
181
+ ---
182
+
183
+ ## Camera app tutorial
184
+
185
+ ### Camera permissions setup
186
+
187
+ iOS - add to `tiapp.xml` plist:
188
+
189
+ ```xml
190
+ <key>NSCameraUsageDescription</key>
191
+ <string>This app needs camera access to take photos</string>
192
+ <key>NSMicrophoneUsageDescription</key>
193
+ <string>This app needs microphone access for video recording</string>
194
+ ```
195
+
196
+ Android: camera permissions are automatically added by the build system when you use `Ti.Media.showCamera()`.
197
+
198
+ Always check permissions at runtime:
199
+
200
+ ```javascript
201
+ if (!Ti.Media.hasCameraPermissions()) {
202
+ Ti.Media.requestCameraPermissions((e) => {
203
+ if (e.success) openCamera();
204
+ });
205
+ } else {
206
+ openCamera();
207
+ }
208
+ ```
209
+
210
+ ### Basic camera access
211
+
212
+ ```javascript
213
+ // Show camera
214
+ Ti.Media.showCamera({
215
+ success: (event) => {
216
+ const image = event.media;
217
+ if (event.mediaType === Ti.Media.MEDIA_TYPE_PHOTO) {
218
+ // Use the photo
219
+ const imageView = Ti.UI.createImageView({
220
+ image: image,
221
+ width: 300,
222
+ height: 300
223
+ });
224
+ win.add(imageView);
225
+ }
226
+ },
227
+ cancel: () => {
228
+ Ti.API.info('Camera canceled');
229
+ },
230
+ error: (error) => {
231
+ const a = Ti.UI.createAlertDialog({ title: 'Camera Error' });
232
+ if (error.code === Ti.Media.NO_CAMERA) {
233
+ a.setMessage('Device does not have camera');
234
+ } else {
235
+ a.setMessage(`Unexpected error: ${error.code}`);
236
+ }
237
+ a.show();
238
+ },
239
+ saveToPhotoGallery: true,
240
+ allowEditing: true,
241
+ mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO],
242
+ videoQuality: Ti.Media.QUALITY_HIGH
243
+ });
244
+ ```
245
+
246
+ ### Photo gallery
247
+
248
+ ```javascript
249
+ // Open photo gallery
250
+ Ti.Media.openPhotoGallery({
251
+ success: (event) => {
252
+ const image = event.media;
253
+ // Process selected image
254
+ },
255
+ cancel: () => {
256
+ // User canceled
257
+ },
258
+ error: (error) => {
259
+ // Handle error
260
+ },
261
+ mediaTypes: [Ti.Media.MEDIA_TYPE_PHOTO]
262
+ });
263
+ ```
264
+
265
+ ### Saving images
266
+
267
+ ```javascript
268
+ // Save to gallery
269
+ Ti.Media.saveToPhotoGallery({
270
+ media: myImageBlob,
271
+ success: () => {
272
+ alert('Saved!');
273
+ },
274
+ error: (e) => {
275
+ alert(`Error: ${e.error}`);
276
+ }
277
+ });
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Geolocation tutorial
283
+
284
+ ### Geolocation permissions setup
285
+
286
+ iOS - add to `tiapp.xml` plist:
287
+
288
+ ```xml
289
+ <key>NSLocationWhenInUseUsageDescription</key>
290
+ <string>We need your location to show nearby places</string>
291
+ <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
292
+ <string>We need your location for background tracking</string>
293
+ ```
294
+
295
+ Android - add to `tiapp.xml` manifest:
296
+
297
+ ```xml
298
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
299
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
300
+ ```
301
+
302
+ Runtime permission check:
303
+ ```javascript
304
+ if (!Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) {
305
+ Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, (e) => {
306
+ if (e.success) startTracking();
307
+ });
308
+ }
309
+ ```
310
+
311
+ ### Basic location
312
+
313
+ ```javascript
314
+ // One-time location
315
+ if (Ti.Geolocation.locationServicesEnabled) {
316
+ Ti.Geolocation.getCurrentPosition((e) => {
317
+ if (!e.error) {
318
+ Ti.API.info(`Lat: ${e.coords.latitude}`);
319
+ Ti.API.info(`Lon: ${e.coords.longitude}`);
320
+ }
321
+ });
322
+ }
323
+ ```
324
+
325
+ ### Continuous tracking
326
+
327
+ ```javascript
328
+ // Configure accuracy
329
+ Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
330
+ Ti.Geolocation.distanceFilter = 10; // Meters
331
+
332
+ // Track location changes
333
+ Ti.Geolocation.addEventListener('location', (e) => {
334
+ if (!e.error) {
335
+ const lat = e.coords.latitude;
336
+ const lon = e.coords.longitude;
337
+ updateMap(lat, lon);
338
+ }
339
+ });
340
+ ```
341
+
342
+ ### Reverse geocoding
343
+
344
+ ```javascript
345
+ // Coordinates to address
346
+ Ti.Geolocation.reverseGeocoder(37.389569, -122.050212, (e) => {
347
+ if (e.success) {
348
+ e.places.forEach((place) => {
349
+ Ti.API.info(place.address);
350
+ Ti.API.info(place.city);
351
+ Ti.API.info(place.country);
352
+ });
353
+ }
354
+ });
355
+ ```
356
+
357
+ ### Accuracy tuning
358
+
359
+ ```javascript
360
+ // iOS: minimum distance before firing event
361
+ Ti.Geolocation.distanceFilter = 10; // meters
362
+
363
+ // Android: use FusedLocationProvider for better battery (requires ti.playservices module)
364
+ // Automatically enabled with SDK 7.1.0+ when ti.playservices is present
365
+
366
+ // Android: custom location rules
367
+ Ti.Geolocation.Android.addLocationRule(Ti.Geolocation.Android.createLocationRule({
368
+ provider: Ti.Geolocation.Android.PROVIDER_GPS,
369
+ accuracy: 100, // meters
370
+ minAge: 1000 // milliseconds
371
+ }));
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Alloy controller chaining
377
+
378
+ ### Pattern overview
379
+
380
+ Chain controller methods to pass data between Alloy controllers in a clean, maintainable way.
381
+
382
+ ### Basic pattern
383
+
384
+ Parent controller:
385
+ ```javascript
386
+ const childController = Alloy.createController('child', {
387
+ data: someData,
388
+ onAction: (result) => {
389
+ // Handle result from child
390
+ Ti.API.info(`Child returned: ${result}`);
391
+ }
392
+ });
393
+
394
+ childController.on('customEvent', (data) => {
395
+ // Handle child events
396
+ });
397
+
398
+ childController.open();
399
+ ```
400
+
401
+ Child controller:
402
+ ```javascript
403
+ const args = arguments[0] || {};
404
+
405
+ // Access parent data
406
+ const parentData = args.data;
407
+
408
+ // Call parent callback
409
+ function notifyParent(result) {
410
+ if (args.onAction) {
411
+ args.onAction(result);
412
+ }
413
+ }
414
+
415
+ // Trigger parent events
416
+ function triggerEvent(data) {
417
+ $.trigger('customEvent', data);
418
+ }
419
+ ```
420
+
421
+ ### Benefits
422
+
423
+ - Clean separation. Controllers remain independent.
424
+ - Reusable. Child works in different contexts.
425
+ - Testable. You can mock parent callbacks.
426
+ - Maintainable. Clear data flow.
427
+
428
+ ---
429
+
430
+ ## Build automation with Fastlane
431
+
432
+ ### Overview
433
+
434
+ Automate building and deploying Titanium apps with Fastlane.
435
+
436
+ ### Installing Fastlane
437
+
438
+ ```bash
439
+ # Using Homebrew (macOS)
440
+ brew install fastlane
441
+
442
+ # Or using Ruby gems
443
+ sudo gem install fastlane -NV
444
+ ```
445
+
446
+ ### Basic Fastfile
447
+
448
+ `fastlane/Fastfile`:
449
+ ```ruby
450
+ platform :ios do
451
+ desc "Build and deploy to TestFlight"
452
+ lane :beta do
453
+ # Build the app
454
+ sh "ti build -p ios -F"
455
+
456
+ # Upload to TestFlight
457
+ upload_to_testflight(
458
+ skip_waiting_for_build_processing: true
459
+ )
460
+ end
461
+
462
+ desc "Build for development"
463
+ lane :dev do
464
+ sh "ti build -p ios -T developer"
465
+ end
466
+ end
467
+
468
+ platform :android do
469
+ desc "Build Android APK"
470
+ lane :build do
471
+ sh "ti build -p android -A"
472
+ end
473
+
474
+ desc "Deploy to Play Store (Beta)"
475
+ lane :beta do
476
+ # Build
477
+ sh "ti build -p android -F"
478
+
479
+ # Upload to Play Store
480
+ upload_to_play_store(
481
+ track: 'beta',
482
+ apk: 'app/build/android/bin/app.apk'
483
+ )
484
+ end
485
+ end
486
+ ```
487
+
488
+ ### Usage
489
+
490
+ ```bash
491
+ # iOS Beta
492
+ fastlane ios beta
493
+
494
+ # Android Build
495
+ fastlane android build
496
+
497
+ # Android Beta
498
+ fastlane android beta
499
+ ```
500
+
501
+ ### Advanced options
502
+
503
+ Multiple environments:
504
+ ```ruby
505
+ lane :staging do
506
+ sh "ti build -p ios -T dist --config ../staging.js"
507
+ end
508
+
509
+ lane :production do
510
+ sh "ti build -p ios -T dist --config ../production.js"
511
+ end
512
+ ```
513
+
514
+ Environment-specific configs:
515
+ ```javascript
516
+ // staging.js
517
+ module.exports = {
518
+ apiURL: 'https://staging-api.example.com',
519
+ analyticsEnabled: true
520
+ };
521
+
522
+ // production.js
523
+ module.exports = {
524
+ apiURL: 'https://api.example.com',
525
+ analyticsEnabled: true
526
+ };
527
+ ```
528
+
529
+ ---
530
+
531
+ ## Additional tutorials
532
+
533
+ ### Alloy boilerplates
534
+
535
+ See `Titanium_Boilerplates` folder for:
536
+ - TypeScript boilerplates
537
+ - App templates
538
+ - Project scaffolding
539
+
540
+ ### Complete sample apps
541
+
542
+ - ToDoList - CommonJS module pattern example
543
+ - Tweetanium - Namespaced pattern example
544
+ - KitchenSink - Complete API reference (built with Alloy)
545
+
546
+ ---
547
+
548
+ ## Resources
549
+
550
+ - RESTe: https://github.com/jasonkneen/reste
551
+ - Fastlane: https://fastlane.tools
552
+ - Alloy Framework: see alloy-guides skill
@@ -0,0 +1,182 @@
1
+ # Using modules
2
+
3
+ Guide to obtaining, installing, and using Titanium modules to extend app functionality.
4
+
5
+ ## Obtaining modules
6
+
7
+ ### Sources of modules
8
+
9
+ Official modules:
10
+ - Enterprise Extensions
11
+ - InAppBilling (Android)
12
+ - StoreKit (iOS)
13
+ - Barcode (iOS/Android)
14
+ - Compression (iOS/Android)
15
+ - OpenGL (iOS)
16
+ - AirPrint (iOS)
17
+
18
+ Open-source modules:
19
+ - GitHub: tidev
20
+ - https://github.com/tidev/ti.admob - AdMob ads
21
+ - https://github.com/tidev/ti.map - Native maps
22
+ - And more in the org
23
+
24
+ Community modules:
25
+ - From Zero To App list: https://fromzerotoapp.com/modules/
26
+ - Curated list of modules maintained by Michael Gangolf
27
+
28
+ Marketplace:
29
+ The original Appcelerator Marketplace is no longer available. Find community modules on GitHub and npm. A curated list is at https://fromzerotoapp.com/modules/.
30
+
31
+ ### Pre-installed modules
32
+ Some modules ship with the SDK and do not need separate installation: `ti.map`, `ti.identity`, `ti.webdialog`, `ti.applesignin`.
33
+
34
+ ## Installing modules
35
+
36
+ ### Single project installation
37
+ 1. Copy the module ZIP to your app root folder.
38
+ 2. Add the module to `tiapp.xml` (see configuration below).
39
+ 3. Build the project. The ZIP is extracted automatically.
40
+
41
+ ### Global installation (all projects)
42
+ Modules install to platform-specific locations:
43
+
44
+ | Operating system | Path |
45
+ | ---------------- | ---------------------------------------- |
46
+ | macOS | `~/Library/Application Support/Titanium` |
47
+ | Windows | `%ProgramData%\Titanium\mobilesdk\win32` |
48
+
49
+ Show hidden Library folder on macOS:
50
+
51
+ ```bash
52
+ # Permanently show
53
+ chflags nohidden ~/Library/
54
+
55
+ # Open once
56
+ open ~/Library
57
+ ```
58
+
59
+ ## Configuring your app
60
+
61
+ ### Updating tiapp.xml
62
+
63
+ Using Studio/IDE:
64
+ 1. Open `tiapp.xml`.
65
+ 2. Go to the Overview tab.
66
+ 3. Click the plus button in Modules.
67
+ 4. Select module and version.
68
+ 5. Save.
69
+
70
+ Manually (XML):
71
+
72
+ ```xml
73
+ <modules>
74
+ <module version="3.0.2" platform="ios">ti.map</module>
75
+ <module version="5.0.0" platform="android">ti.admob</module>
76
+ </modules>
77
+ ```
78
+
79
+ Attributes:
80
+ - `version`: must match the module manifest
81
+ - `platform`: "ios" or "android"
82
+
83
+ ### Selecting module versions
84
+ If multiple versions are installed, select specific versions per platform and build type (development/production).
85
+
86
+ In Studio, double-click the module to open the Module Properties dialog.
87
+
88
+ ### Enable debugger (for native modules)
89
+ Required for debugging native modules:
90
+
91
+ ```xml
92
+ <ti:app>
93
+ <android xmlns:android="http://schemas.android.com/apk/res/android">
94
+ <manifest>
95
+ <application android:debuggable="true">
96
+ </application>
97
+ </manifest>
98
+ </android>
99
+ </ti:app>
100
+ ```
101
+
102
+ ## Using a module
103
+
104
+ ### Loading the module (ES5)
105
+
106
+ ```javascript
107
+ const Module = require('module.id');
108
+ // Example: const Map = require('ti.map');
109
+ ```
110
+
111
+ ### Loading the module (ES6+)
112
+
113
+ ```javascript
114
+ import Module from 'module.id'
115
+ // Example: import Map from 'ti.map'
116
+ ```
117
+
118
+ Important: do not include the `.js` extension in the module ID.
119
+
120
+ ### Using module functionality
121
+ After requiring, use the module's API:
122
+
123
+ ```javascript
124
+ // ES6+ example with ti.admob
125
+ const Admob = require('ti.admob');
126
+
127
+ const adview = Admob.createView({
128
+ top: 0,
129
+ testing: true,
130
+ adBackgroundColor: 'black',
131
+ primaryTextColor: 'blue',
132
+ publisherId: 'YOUR_PUBLISHER_ID'
133
+ });
134
+
135
+ win.add(adview);
136
+ ```
137
+
138
+ ### Module patterns
139
+
140
+ Singleton pattern:
141
+ ```javascript
142
+ const admob = require('ti.admob');
143
+ admob.createView({ ... });
144
+ ```
145
+
146
+ Constructor pattern:
147
+ ```javascript
148
+ const Map = require('ti.map');
149
+ const view = Map.createView({ ... });
150
+ ```
151
+
152
+ Refer to module documentation for its specific API.
153
+
154
+ ## Troubleshooting
155
+
156
+ ### "Requested module not found"
157
+ Solutions:
158
+ 1. Check module ID spelling in `require()`.
159
+ 2. Verify the module is added to `tiapp.xml`.
160
+ 3. Confirm the module is installed (global or local path).
161
+ 4. Remove the `version` attribute to use the latest version.
162
+
163
+ ### Version conflicts
164
+ If multiple versions exist, specify the exact version in `tiapp.xml`, or remove the version attribute to use the latest.
165
+
166
+ ### Platform-specific issues
167
+ - iOS: the module must support the iOS SDK version you are using.
168
+ - Android: the module manifest `platform` must match the target.
169
+
170
+ ### Clean build
171
+ Sometimes needed after installing modules:
172
+
173
+ ```bash
174
+ # Clean and rebuild
175
+ ti clean
176
+ ```
177
+
178
+ ## Best practices
179
+
180
+ 1. Pin versions for production.
181
+ 2. Check compatibility with your Titanium SDK version.
182
+ 3. Test on devices. Some modules behave differently on simulator vs device.