@maccesar/titools 2.2.11 → 2.3.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 (99) hide show
  1. package/README.md +255 -713
  2. package/bin/titools.js +1 -1
  3. package/lib/commands/update.js +5 -6
  4. package/lib/config.js +1 -0
  5. package/lib/downloader.js +10 -0
  6. package/package.json +1 -1
  7. package/skills/alloy-guides/SKILL.md +46 -48
  8. package/skills/alloy-guides/references/CONTROLLERS.md +4 -6
  9. package/skills/alloy-guides/references/MODELS.md +340 -184
  10. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +3 -4
  11. package/skills/alloy-guides/references/VIEWS_STYLES.md +44 -46
  12. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +4 -5
  13. package/skills/alloy-guides/references/VIEWS_XML.md +51 -17
  14. package/skills/alloy-guides/references/WIDGETS.md +1 -1
  15. package/skills/alloy-howtos/SKILL.md +12 -13
  16. package/skills/alloy-howtos/references/cli_reference.md +40 -41
  17. package/skills/alloy-howtos/references/samples.md +3 -4
  18. package/skills/purgetss/SKILL.md +369 -356
  19. package/skills/purgetss/references/EXAMPLES.md +24 -25
  20. package/skills/purgetss/references/animation-advanced.md +555 -0
  21. package/skills/purgetss/references/animation-system.md +395 -995
  22. package/skills/purgetss/references/apply-directive.md +111 -141
  23. package/skills/purgetss/references/arbitrary-values.md +206 -480
  24. package/skills/purgetss/references/class-categories.md +277 -0
  25. package/skills/purgetss/references/class-index.md +1 -420
  26. package/skills/purgetss/references/cli-commands.md +446 -556
  27. package/skills/purgetss/references/configurable-properties.md +163 -599
  28. package/skills/purgetss/references/custom-rules.md +33 -76
  29. package/skills/purgetss/references/customization-deep-dive.md +319 -518
  30. package/skills/purgetss/references/dynamic-component-creation.md +33 -37
  31. package/skills/purgetss/references/grid-layout.md +42 -371
  32. package/skills/purgetss/references/icon-fonts.md +82 -475
  33. package/skills/purgetss/references/installation-setup.md +159 -331
  34. package/skills/purgetss/references/migration-guide.md +54 -109
  35. package/skills/purgetss/references/opacity-modifier.md +25 -222
  36. package/skills/purgetss/references/performance-tips.md +2 -2
  37. package/skills/purgetss/references/platform-modifiers.md +21 -407
  38. package/skills/purgetss/references/tikit-components.md +237 -104
  39. package/skills/purgetss/references/titanium-resets.md +20 -21
  40. package/skills/purgetss/references/ui-ux-design.md +171 -1702
  41. package/skills/ti-api/SKILL.md +109 -0
  42. package/skills/ti-api/references/api-android.md +675 -0
  43. package/skills/ti-api/references/api-app-platform.md +636 -0
  44. package/skills/ti-api/references/api-core.md +764 -0
  45. package/skills/ti-api/references/api-data-network.md +641 -0
  46. package/skills/ti-api/references/api-media.md +655 -0
  47. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  48. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  49. package/skills/ti-api/references/api-modules-map.md +632 -0
  50. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  51. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  52. package/skills/ti-api/references/api-services.md +700 -0
  53. package/skills/ti-api/references/api-ui-android.md +499 -0
  54. package/skills/ti-api/references/api-ui-extras.md +702 -0
  55. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  56. package/skills/ti-api/references/api-ui-ios.md +756 -0
  57. package/skills/ti-api/references/api-ui-lists.md +581 -0
  58. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  59. package/skills/ti-api/references/api-ui-views.md +572 -0
  60. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  61. package/skills/ti-api/references/api-xml-global.md +743 -0
  62. package/skills/ti-expert/SKILL.md +106 -138
  63. package/skills/ti-expert/references/adaptive-layouts.md +414 -0
  64. package/skills/ti-expert/references/alloy-builtins.md +16 -20
  65. package/skills/ti-expert/references/alloy-structure.md +40 -42
  66. package/skills/ti-expert/references/anti-patterns.md +34 -0
  67. package/skills/ti-expert/references/architecture-tiers.md +248 -0
  68. package/skills/ti-expert/references/code-conventions.md +5 -3
  69. package/skills/ti-expert/references/error-handling.md +14 -7
  70. package/skills/ti-expert/references/examples.md +4 -2
  71. package/skills/ti-expert/references/performance-optimization.md +26 -24
  72. package/skills/ti-expert/references/security-device.md +17 -14
  73. package/skills/ti-expert/references/security-fundamentals.md +60 -101
  74. package/skills/ti-expert/references/state-management.md +15 -14
  75. package/skills/ti-expert/references/testing-e2e-ci.md +30 -21
  76. package/skills/ti-expert/references/theming.md +12 -20
  77. package/skills/ti-guides/SKILL.md +13 -17
  78. package/skills/ti-guides/references/advanced-data-and-images.md +30 -10
  79. package/skills/ti-guides/references/application-frameworks.md +3 -3
  80. package/skills/ti-guides/references/coding-best-practices.md +31 -2
  81. package/skills/ti-guides/references/commonjs-advanced.md +46 -4
  82. package/skills/ti-guides/references/hello-world.md +9 -13
  83. package/skills/ti-guides/references/hyperloop-native-access.md +4 -1
  84. package/skills/ti-guides/references/javascript-primer.md +13 -5
  85. package/skills/ti-guides/references/resources.md +0 -2
  86. package/skills/ti-guides/references/style-and-conventions.md +1 -0
  87. package/skills/ti-guides/references/tiapp-config.md +0 -32
  88. package/skills/ti-howtos/SKILL.md +43 -45
  89. package/skills/ti-howtos/references/buffer-codec-streams.md +25 -3
  90. package/skills/ti-howtos/references/debugging-profiling.md +14 -25
  91. package/skills/ti-howtos/references/google-maps-v2.md +3 -3
  92. package/skills/ti-howtos/references/ios-map-kit.md +8 -1
  93. package/skills/ti-howtos/references/notification-services.md +0 -1
  94. package/skills/ti-howtos/references/webpack-build-pipeline.md +3 -0
  95. package/skills/ti-ui/SKILL.md +47 -49
  96. package/skills/ti-ui/references/application-structures.md +3 -2
  97. package/skills/ti-ui/references/orientation.md +17 -9
  98. package/skills/ti-ui/references/platform-ui-ios.md +63 -0
  99. package/skills/ti-ui/references/scrolling-views.md +39 -0
@@ -0,0 +1,248 @@
1
+ # Titanium Architectural Maturity Tiers
2
+
3
+ To ensure scalability and maintainability, Titanium projects should follow one of these three tiers based on their complexity.
4
+
5
+ ---
6
+
7
+ # Tier 1 — Basic (Rapid Prototyping)
8
+
9
+ **Best for:** Utilities, internal tools, proof of concept, learning Alloy.
10
+
11
+ ### Characteristics
12
+
13
+ * Logic directly in `index.js`
14
+ * Direct `$` access everywhere
15
+ * No separation of concerns
16
+ * No cleanup strategy
17
+
18
+ ### When to upgrade?
19
+
20
+ * Controller > 100–150 lines
21
+ * Logic duplicated in multiple controllers
22
+ * UI starts feeling coupled
23
+
24
+ ---
25
+
26
+ ## Example (Tier 1)
27
+
28
+ ### Controller (`controllers/index.js`)
29
+
30
+ ```javascript
31
+ function onButtonClick() {
32
+ $.label.text = "Clicked!"
33
+ Ti.API.info("Button was clicked")
34
+ }
35
+
36
+ $.index.open()
37
+ ```
38
+
39
+ Simple. Fast. Dangerous beyond small apps.
40
+
41
+ ---
42
+
43
+ # Tier 2 — Intermediate (Modular Alloy)
44
+
45
+ **Best for:** Standard commercial applications.
46
+
47
+ ### Characteristics
48
+
49
+ * Business logic extracted to `app/lib/`
50
+ * Slim controllers
51
+ * Flat organization (`lib/services`, `lib/api`)
52
+ * Mandatory `cleanup`
53
+ * Reusable UI components
54
+
55
+ ### Why this tier exists
56
+
57
+ This tier separates UI from logic, but still allows services to reference global dependencies.
58
+
59
+ It’s modular — but not yet decoupled.
60
+
61
+ ---
62
+
63
+ ## Example (Tier 2)
64
+
65
+ ### View (`views/userCard.xml`)
66
+
67
+ ```xml
68
+ <Alloy>
69
+ <View id="cardContainer">
70
+ <View id="headerRow">
71
+ <ImageView id="userIcon" image="/images/user.png" />
72
+ <Label id="name" />
73
+ </View>
74
+
75
+ <Button id="viewProfileBtn"
76
+ title="View Profile"
77
+ onClick="onViewProfile" />
78
+ </View>
79
+ </Alloy>
80
+ ```
81
+
82
+ ---
83
+
84
+ ### Controller (`controllers/userCard.js`)
85
+
86
+ ```javascript
87
+ const { Navigation } = require('services/navigation')
88
+
89
+ function init() {
90
+ const user = $.args.user
91
+ $.name.text = user.name
92
+ }
93
+
94
+ function onViewProfile() {
95
+ Navigation.open('userProfile', { userId: $.args.user.id })
96
+ }
97
+
98
+ function cleanup() {
99
+ $.destroy()
100
+ }
101
+
102
+ $.cleanup = cleanup
103
+ ```
104
+
105
+ ---
106
+
107
+ ### Service (`lib/services/navigation.js`)
108
+
109
+ ```javascript
110
+ exports.Navigation = {
111
+ open(route, params = {}) {
112
+ const controller = Alloy.createController(route, params)
113
+ const view = controller.getView()
114
+
115
+ view.addEventListener('close', () => {
116
+ if (controller.cleanup) controller.cleanup()
117
+ })
118
+
119
+ view.open()
120
+ return controller
121
+ }
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ### What improves from Tier 1?
128
+
129
+ * Controllers stay under control
130
+ * Logic is reusable
131
+ * Memory is explicitly cleaned
132
+ * Code is easier to test
133
+
134
+ But services can still depend directly on other services or globals.
135
+
136
+ ---
137
+
138
+ # Tier 3 — Advanced / Enterprise (Service-Oriented)
139
+
140
+ **Best for:** Complex applications (IDEs, platforms, multi-state apps).
141
+
142
+ This is where architectural maturity changes fundamentally.
143
+
144
+ ---
145
+
146
+ ## Core Concepts
147
+
148
+ ### 1️⃣ Dependency Injection
149
+
150
+ Services receive what they need — they don’t fetch it.
151
+
152
+ ### 2️⃣ Service Registry
153
+
154
+ Centralized dependency wiring.
155
+
156
+ ### 3️⃣ ID Scoping
157
+
158
+ Services receive only the UI elements they own.
159
+
160
+ ### 4️⃣ Encapsulation (Black Box Principle)
161
+
162
+ Once a service method works, treat it as trusted.
163
+
164
+ ### 5️⃣ Observability
165
+
166
+ All logs are structured and include service context.
167
+
168
+ ---
169
+
170
+ ## Example (Tier 3)
171
+
172
+ ---
173
+
174
+ ### Service (`lib/services/chatService.js`)
175
+
176
+ ```javascript
177
+ /**
178
+ * @param {Object} deps
179
+ * @param {Object} deps.ui - Scoped UI elements
180
+ * @param {Object} deps.logger
181
+ * @param {Object} deps.designService
182
+ */
183
+ module.exports = function createChatService(deps) {
184
+ const { ui, logger, designService } = deps
185
+
186
+ function sendMessage(text) {
187
+ if (!text) return
188
+
189
+ ui.sendBtn.enabled = false // ID Scoping
190
+ designService.trackMessage(text) // Inter-service communication
191
+
192
+ logger.event('message:sent', {
193
+ service: 'ChatService',
194
+ length: text.length
195
+ })
196
+ }
197
+
198
+ return {
199
+ sendMessage
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ### Registry (`lib/services/indexServiceRegistry.js`)
207
+
208
+ ```javascript
209
+ const createChatService = require('services/chatService')
210
+ const createDesignService = require('services/designService')
211
+
212
+ module.exports = function createIndexServiceRegistry(deps) {
213
+ const { $, Ti, logger } = deps
214
+
215
+ // 1. Independent services
216
+ const designService = createDesignService({ Ti, logger })
217
+
218
+ // 2. Dependent services with scoped UI
219
+ const chatService = createChatService({
220
+ ui: {
221
+ sendBtn: $.sendBtn,
222
+ messageInput: $.messageInput
223
+ },
224
+ logger,
225
+ designService
226
+ })
227
+
228
+ return {
229
+ chatService,
230
+ designService
231
+ }
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Decision Matrix
238
+
239
+ | Signal | Move To |
240
+ | ----------------------------------- | ------- |
241
+ | Controller > 100 lines | Tier 2 |
242
+ | Controller > 300 lines | Tier 3 |
243
+ | More than 50 IDs in XML | Tier 3 |
244
+ | Services need to talk to each other | Tier 3 |
245
+ | Multiple application states | Tier 3 |
246
+ | Memory leaks appear | Tier 3 |
247
+
248
+ ---
@@ -386,13 +386,13 @@ const Backbone = require('alloy/backbone')
386
386
 
387
387
  const EventBus = _.clone(Backbone.Events)
388
388
 
389
- // Named export for event constants
390
- exports.Events = {
389
+ // Attach event constants directly to the bus object so they survive module.exports
390
+ EventBus.Events = {
391
391
  USER_UPDATED: 'user:updated',
392
392
  SYNC_COMPLETE: 'sync:complete'
393
393
  }
394
394
 
395
- // Default export for the bus itself
395
+ // Export the bus (EventBus.Events is accessible as a property)
396
396
  module.exports = EventBus
397
397
 
398
398
  // Usage
@@ -400,6 +400,8 @@ const EventBus = require('services/eventBus')
400
400
  const { Events } = EventBus
401
401
  ```
402
402
 
403
+ > Note: setting `exports.Events = {...}` before `module.exports = EventBus` has no effect — the `module.exports` assignment discards the prior `exports` object. Attach constants directly to the object being exported instead.
404
+
403
405
  ### Re-exports (Barrel Files)
404
406
  ```javascript
405
407
  // lib/api/index.js - Barrel file
@@ -4,7 +4,10 @@
4
4
 
5
5
  ```javascript
6
6
  // lib/core/appError.js
7
- module.exports = class AppError extends Error {
7
+ // IMPORTANT: Use named exports (exports.Foo), NOT module.exports = class Foo.
8
+ // Multiple `module.exports =` assignments overwrite each other — only the last one survives.
9
+
10
+ class AppError extends Error {
8
11
  constructor(message, code, statusCode = 500) {
9
12
  super(message)
10
13
  this.code = code
@@ -14,32 +17,36 @@ module.exports = class AppError extends Error {
14
17
  }
15
18
  }
16
19
 
17
- // Specific error types
18
- module.exports = class NetworkError extends AppError {
20
+ class NetworkError extends AppError {
19
21
  constructor(message = 'Network request failed') {
20
22
  super(message, 'NETWORK_ERROR', 0)
21
23
  }
22
24
  }
23
25
 
24
- module.exports = class AuthError extends AppError {
26
+ class AuthError extends AppError {
25
27
  constructor(message = 'Authentication failed') {
26
28
  super(message, 'AUTH_ERROR', 401)
27
29
  }
28
30
  }
29
31
 
30
- module.exports = class ValidationError extends AppError {
32
+ class ValidationError extends AppError {
31
33
  constructor(message = 'Validation failed') {
32
34
  super(message, 'VALIDATION_ERROR', 400)
33
35
  }
34
36
  }
35
37
 
36
- module.exports = class NotFoundError extends AppError {
38
+ class NotFoundError extends AppError {
37
39
  constructor(message = 'Resource not found') {
38
40
  super(message, 'NOT_FOUND', 404)
39
41
  }
40
42
  }
41
43
 
42
- // Error codes for reference
44
+ exports.AppError = AppError
45
+ exports.NetworkError = NetworkError
46
+ exports.AuthError = AuthError
47
+ exports.ValidationError = ValidationError
48
+ exports.NotFoundError = NotFoundError
49
+
43
50
  exports.ErrorCodes = {
44
51
  NETWORK_ERROR: 'NETWORK_ERROR',
45
52
  AUTH_ERROR: 'AUTH_ERROR',
@@ -736,9 +736,11 @@ function init() {
736
736
  }
737
737
 
738
738
  function onTabFocus(e) {
739
- // Analytics tracking
739
+ // Track tab changes via your analytics service
740
+ // Note: Ti.Analytics was removed from the Titanium SDK.
741
+ // Use a third-party analytics service (e.g., Firebase, Segment) instead.
740
742
  const tabNames = ['home', 'search', 'cart', 'profile']
741
- Ti.Analytics.featureEvent(`tab:${tabNames[e.index]}`)
743
+ Analytics.track(`tab:${tabNames[e.index]}`)
742
744
  }
743
745
 
744
746
  function onCartUpdated({ itemCount }) {
@@ -212,12 +212,14 @@ $.cleanup = cleanup
212
212
  ```javascript
213
213
  // lib/services/database.js
214
214
  exports.DB = {
215
- // Use transactions for multiple writes
215
+ // Use transactions to speed batch inserts
216
+ // Per official docs: use db.execute('BEGIN') / db.execute('COMMIT') — there are no
217
+ // dedicated begin_transaction() / commit() / rollback() methods on Ti.Database.DB.
216
218
  batchInsert(items) {
217
219
  const db = Ti.Database.open('mydb')
218
220
 
219
221
  try {
220
- db.begin_transaction()
222
+ db.execute('BEGIN')
221
223
 
222
224
  items.forEach(item => {
223
225
  db.execute(
@@ -228,12 +230,12 @@ exports.DB = {
228
230
  )
229
231
  })
230
232
 
231
- db.commit()
233
+ db.execute('COMMIT')
232
234
 
233
235
  console.log(`Inserted ${items.length} items`)
234
236
 
235
237
  } catch (e) {
236
- db.rollback()
238
+ db.execute('ROLLBACK')
237
239
  console.error('Batch insert failed', e)
238
240
  throw e
239
241
 
@@ -574,14 +576,14 @@ function cleanup() {
574
576
 
575
577
  ### Common use cases
576
578
 
577
- | Pattern | Use Case | Delay |
579
+ | Pattern | Use Case | Delay |
578
580
  | -------- | ---------------- | ------------ |
579
- | Debounce | Search input | 300ms |
580
- | Debounce | Auto-save | 1000ms |
581
- | Debounce | Window resize | 150ms |
582
- | Throttle | Scroll events | 50-100ms |
581
+ | Debounce | Search input | 300ms |
582
+ | Debounce | Auto-save | 1000ms |
583
+ | Debounce | Window resize | 150ms |
584
+ | Throttle | Scroll events | 50-100ms |
583
585
  | Throttle | Mouse/touch move | 16ms (60fps) |
584
- | Throttle | API polling | 5000ms+ |
586
+ | Throttle | API polling | 5000ms+ |
585
587
 
586
588
  ### Combined pattern for real-time + final
587
589
 
@@ -622,18 +624,18 @@ function cleanup() {
622
624
 
623
625
  ## Performance checklist
624
626
 
625
- | Area | Check |
627
+ | Area | Check |
626
628
  | ------------- | --------------------------------------- |
627
- | **Bridge** | Cached Ti.Platform properties |
628
- | **Bridge** | Using applyProperties for updates |
629
- | **Bridge** | TSS styles instead of inline attributes |
630
- | **Memory** | All global listeners cleaned up |
631
- | **Memory** | Heavy objects nulled in cleanup |
632
- | **Memory** | Images resized appropriately |
633
- | **Database** | Using transactions for batch ops |
634
- | **Database** | Indexes on frequently queried columns |
635
- | **Database** | ResultSets and DB handles closed |
636
- | **Animation** | Using native animations, not intervals |
637
- | **Animation** | GPU-accelerated properties preferred |
638
- | **Timing** | Debounce on search/input |
639
- | **Timing** | Throttle on scroll/touch events |
629
+ | **Bridge** | Cached Ti.Platform properties |
630
+ | **Bridge** | Using applyProperties for updates |
631
+ | **Bridge** | TSS styles instead of inline attributes |
632
+ | **Memory** | All global listeners cleaned up |
633
+ | **Memory** | Heavy objects nulled in cleanup |
634
+ | **Memory** | Images resized appropriately |
635
+ | **Database** | Using transactions for batch ops |
636
+ | **Database** | Indexes on frequently queried columns |
637
+ | **Database** | ResultSets and DB handles closed |
638
+ | **Animation** | Using native animations, not intervals |
639
+ | **Animation** | GPU-accelerated properties preferred |
640
+ | **Timing** | Debounce on search/input |
641
+ | **Timing** | Throttle on scroll/touch events |
@@ -502,6 +502,9 @@ exports.SecurityService = {
502
502
  },
503
503
 
504
504
  _showBlockedScreen() {
505
+ // Note: iOS guidelines prohibit programmatically terminating an app.
506
+ // The best practice is to show a blocking dialog and prevent further interaction.
507
+ // On Android you can call Ti.Android.currentActivity.finish() to close the activity.
505
508
  const dialog = Ti.UI.createAlertDialog({
506
509
  title: L('security_blocked_title'),
507
510
  message: L('security_blocked_msg'),
@@ -509,10 +512,10 @@ exports.SecurityService = {
509
512
  })
510
513
 
511
514
  dialog.addEventListener('click', () => {
512
- // Close the app (iOS) or minimize (Android)
513
- if (OS_IOS) {
514
- Ti.Platform.openURL('prefs:root=General')
515
+ if (OS_ANDROID) {
516
+ Ti.Android.currentActivity.finish()
515
517
  }
518
+ // On iOS: leave the dialog visible — Apple guidelines prohibit force-quitting apps.
516
519
  })
517
520
 
518
521
  dialog.show()
@@ -550,15 +553,15 @@ setInterval(() => {
550
553
 
551
554
  ## Security checklist
552
555
 
553
- | Category | Check | Implementation |
556
+ | Category | Check | Implementation |
554
557
  | -------------- | -------------------------- | ------------------------ |
555
- | **Biometrics** | Use ti.identity for auth | BiometricService wrapper |
556
- | **Biometrics** | Never store biometric data | System handles storage |
557
- | **Biometrics** | Fallback to password | Always offer alternative |
558
- | **Deep Links** | Whitelist allowed schemes | ALLOWED_SCHEMES constant |
559
- | **Deep Links** | Whitelist allowed hosts | ALLOWED_HOSTS constant |
560
- | **Deep Links** | Sanitize all parameters | _sanitizeParams() |
561
- | **Deep Links** | Check auth requirements | requiresAuth per route |
562
- | **Integrity** | Check for jailbreak/root | checkDeviceIntegrity() |
563
- | **Integrity** | Define security policy | block/restrict/warn |
564
- | **Integrity** | Log security events | Always log compromises |
558
+ | **Biometrics** | Use ti.identity for auth | BiometricService wrapper |
559
+ | **Biometrics** | Never store biometric data | System handles storage |
560
+ | **Biometrics** | Fallback to password | Always offer alternative |
561
+ | **Deep Links** | Whitelist allowed schemes | ALLOWED_SCHEMES constant |
562
+ | **Deep Links** | Whitelist allowed hosts | ALLOWED_HOSTS constant |
563
+ | **Deep Links** | Sanitize all parameters | _sanitizeParams() |
564
+ | **Deep Links** | Check auth requirements | requiresAuth per route |
565
+ | **Integrity** | Check for jailbreak/root | checkDeviceIntegrity() |
566
+ | **Integrity** | Define security policy | block/restrict/warn |
567
+ | **Integrity** | Log security events | Always log compromises |