@maccesar/titools 2.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 (120) hide show
  1. package/AGENTS-TEMPLATE.md +173 -0
  2. package/README.md +867 -0
  3. package/agents/ti-researcher.md +108 -0
  4. package/bin/titools.js +53 -0
  5. package/lib/commands/agents.js +126 -0
  6. package/lib/commands/install.js +188 -0
  7. package/lib/commands/uninstall.js +215 -0
  8. package/lib/commands/update.js +159 -0
  9. package/lib/config.js +119 -0
  10. package/lib/downloader.js +153 -0
  11. package/lib/installer.js +253 -0
  12. package/lib/platform.js +108 -0
  13. package/lib/symlink.js +142 -0
  14. package/lib/utils.js +270 -0
  15. package/package.json +67 -0
  16. package/skills/alloy-expert/SKILL.md +247 -0
  17. package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
  18. package/skills/alloy-expert/references/alloy-structure.md +381 -0
  19. package/skills/alloy-expert/references/anti-patterns.md +133 -0
  20. package/skills/alloy-expert/references/code-conventions.md +469 -0
  21. package/skills/alloy-expert/references/contracts.md +280 -0
  22. package/skills/alloy-expert/references/controller-patterns.md +520 -0
  23. package/skills/alloy-expert/references/error-handling.md +484 -0
  24. package/skills/alloy-expert/references/examples.md +735 -0
  25. package/skills/alloy-expert/references/migration-patterns.md +298 -0
  26. package/skills/alloy-expert/references/patterns.md +448 -0
  27. package/skills/alloy-expert/references/performance-patterns.md +855 -0
  28. package/skills/alloy-expert/references/security-patterns.md +847 -0
  29. package/skills/alloy-expert/references/state-management.md +779 -0
  30. package/skills/alloy-expert/references/testing.md +872 -0
  31. package/skills/alloy-guides/SKILL.md +214 -0
  32. package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
  33. package/skills/alloy-guides/references/CONCEPTS.md +191 -0
  34. package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
  35. package/skills/alloy-guides/references/MODELS.md +1028 -0
  36. package/skills/alloy-guides/references/PURGETSS.md +56 -0
  37. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
  38. package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
  39. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
  40. package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
  41. package/skills/alloy-guides/references/WIDGETS.md +176 -0
  42. package/skills/alloy-howtos/SKILL.md +203 -0
  43. package/skills/alloy-howtos/references/best_practices.md +138 -0
  44. package/skills/alloy-howtos/references/cli_reference.md +253 -0
  45. package/skills/alloy-howtos/references/config_files.md +87 -0
  46. package/skills/alloy-howtos/references/custom_tags.md +147 -0
  47. package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
  48. package/skills/alloy-howtos/references/samples.md +167 -0
  49. package/skills/purgetss/SKILL.md +442 -0
  50. package/skills/purgetss/assets/purgetss.config.cjs +17 -0
  51. package/skills/purgetss/references/EXAMPLES.md +247 -0
  52. package/skills/purgetss/references/animation-system.md +1294 -0
  53. package/skills/purgetss/references/apply-directive.md +375 -0
  54. package/skills/purgetss/references/arbitrary-values.md +612 -0
  55. package/skills/purgetss/references/class-index.md +1350 -0
  56. package/skills/purgetss/references/cli-commands.md +948 -0
  57. package/skills/purgetss/references/configurable-properties.md +654 -0
  58. package/skills/purgetss/references/custom-rules.md +161 -0
  59. package/skills/purgetss/references/customization-deep-dive.md +722 -0
  60. package/skills/purgetss/references/dynamic-component-creation.md +489 -0
  61. package/skills/purgetss/references/grid-layout.md +455 -0
  62. package/skills/purgetss/references/icon-fonts.md +609 -0
  63. package/skills/purgetss/references/installation-setup.md +366 -0
  64. package/skills/purgetss/references/opacity-modifier.md +291 -0
  65. package/skills/purgetss/references/platform-modifiers.md +479 -0
  66. package/skills/purgetss/references/smart-mappings.md +42 -0
  67. package/skills/purgetss/references/titanium-resets.md +359 -0
  68. package/skills/purgetss/references/ui-ux-design.md +1526 -0
  69. package/skills/ti-guides/SKILL.md +94 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
  71. package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
  72. package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
  73. package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
  74. package/skills/ti-guides/references/android-manifest.md +97 -0
  75. package/skills/ti-guides/references/app-distribution.md +258 -0
  76. package/skills/ti-guides/references/application-frameworks.md +377 -0
  77. package/skills/ti-guides/references/cli-reference.md +402 -0
  78. package/skills/ti-guides/references/coding-best-practices.md +102 -0
  79. package/skills/ti-guides/references/commonjs-advanced.md +134 -0
  80. package/skills/ti-guides/references/hello-world.md +100 -0
  81. package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
  82. package/skills/ti-guides/references/javascript-primer.md +411 -0
  83. package/skills/ti-guides/references/reserved-words.md +36 -0
  84. package/skills/ti-guides/references/resources.md +183 -0
  85. package/skills/ti-guides/references/style-and-conventions.md +48 -0
  86. package/skills/ti-guides/references/tiapp-config.md +609 -0
  87. package/skills/ti-howtos/SKILL.md +174 -0
  88. package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
  89. package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
  90. package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
  91. package/skills/ti-howtos/references/cross-platform-development.md +348 -0
  92. package/skills/ti-howtos/references/debugging-profiling.md +543 -0
  93. package/skills/ti-howtos/references/extending-titanium.md +723 -0
  94. package/skills/ti-howtos/references/google-maps-v2.md +169 -0
  95. package/skills/ti-howtos/references/ios-map-kit.md +143 -0
  96. package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
  97. package/skills/ti-howtos/references/local-data-sources.md +301 -0
  98. package/skills/ti-howtos/references/location-and-maps.md +252 -0
  99. package/skills/ti-howtos/references/media-apis.md +210 -0
  100. package/skills/ti-howtos/references/notification-services.md +599 -0
  101. package/skills/ti-howtos/references/remote-data-sources.md +349 -0
  102. package/skills/ti-howtos/references/tutorials.md +502 -0
  103. package/skills/ti-howtos/references/using-modules.md +237 -0
  104. package/skills/ti-howtos/references/web-content-integration.md +307 -0
  105. package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
  106. package/skills/ti-ui/SKILL.md +179 -0
  107. package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
  108. package/skills/ti-ui/references/animation-and-matrices.md +599 -0
  109. package/skills/ti-ui/references/application-structures.md +655 -0
  110. package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
  111. package/skills/ti-ui/references/event-handling.md +393 -0
  112. package/skills/ti-ui/references/gestures.md +473 -0
  113. package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
  114. package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
  115. package/skills/ti-ui/references/listviews-and-performance.md +619 -0
  116. package/skills/ti-ui/references/orientation.md +362 -0
  117. package/skills/ti-ui/references/platform-ui-android.md +635 -0
  118. package/skills/ti-ui/references/platform-ui-ios.md +469 -0
  119. package/skills/ti-ui/references/scrolling-views.md +252 -0
  120. package/skills/ti-ui/references/tableviews.md +568 -0
@@ -0,0 +1,448 @@
1
+ # Architectural Patterns for Titanium + Alloy
2
+
3
+ ## 1. Native Module Abstraction (Wrapper)
4
+
5
+ **Use when:** Using native modules like Maps, Biometrics, or specialized Media players.
6
+
7
+ ```javascript
8
+ // lib/services/biometricService.js
9
+ const Identity = require('ti.identity')
10
+
11
+ let isAvailable = null
12
+
13
+ exports.BiometricService = {
14
+ checkAvailability() {
15
+ if (isAvailable !== null) return isAvailable
16
+
17
+ isAvailable = Identity.isSupported() &&
18
+ (Identity.deviceCanAuthenticate() === Identity.SUCCESS)
19
+
20
+ return isAvailable
21
+ },
22
+
23
+ authenticate(reason) {
24
+ return new Promise((resolve, reject) => {
25
+ if (!this.checkAvailability()) {
26
+ return reject(new Error('Biometrics not available'))
27
+ }
28
+
29
+ Identity.authenticate({
30
+ reason: reason || L('biometric_reason'),
31
+ callback: (e) => {
32
+ if (e.success) {
33
+ resolve(true)
34
+ } else {
35
+ reject(new Error(e.error || 'Authentication failed'))
36
+ }
37
+ }
38
+ })
39
+ })
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## 2. Repository Pattern for Data
45
+
46
+ **Use when:** Complex data access, multiple data sources, or need to abstract SQLite/API.
47
+
48
+ ```javascript
49
+ // lib/repositories/userRepository.js
50
+ const db = Ti.Database.open('app')
51
+
52
+ exports.UserRepository = {
53
+ getById(id) {
54
+ const rs = db.execute('SELECT * FROM users WHERE id = ?', id)
55
+ const user = rs.isValidRow() ? this._rowToUser(rs) : null
56
+ rs.close()
57
+ return user
58
+ },
59
+
60
+ getAll() {
61
+ const rs = db.execute('SELECT * FROM users ORDER BY name')
62
+ const users = []
63
+ while (rs.isValidRow()) {
64
+ users.push(this._rowToUser(rs))
65
+ rs.next()
66
+ }
67
+ rs.close()
68
+ return users
69
+ },
70
+
71
+ save(user) {
72
+ if (user.id) {
73
+ db.execute(
74
+ 'UPDATE users SET name = ?, email = ? WHERE id = ?',
75
+ user.name, user.email, user.id
76
+ )
77
+ } else {
78
+ db.execute(
79
+ 'INSERT INTO users (name, email) VALUES (?, ?)',
80
+ user.name, user.email
81
+ )
82
+ user.id = db.lastInsertRowId
83
+ }
84
+ return user
85
+ },
86
+
87
+ delete(id) {
88
+ db.execute('DELETE FROM users WHERE id = ?', id)
89
+ },
90
+
91
+ _rowToUser(rs) {
92
+ return {
93
+ id: rs.fieldByName('id'),
94
+ name: rs.fieldByName('name'),
95
+ email: rs.fieldByName('email')
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## 3. Service Layer Pattern
102
+
103
+ **Use when:** Business logic, orchestrating multiple operations.
104
+
105
+ ```javascript
106
+ // lib/services/authService.js
107
+ const authApi = require('lib/api/authApi').authApi
108
+ const { TokenStorage } = require('lib/services/tokenStorage')
109
+ const { appStore } = require('lib/services/stateStore')
110
+ const { Validator } = require('lib/helpers/validator')
111
+
112
+ exports.AuthService = {
113
+ async login(email, password) {
114
+ // 1. Validate input
115
+ Validator.email(email)
116
+ Validator.password(password)
117
+
118
+ // 2. Call API
119
+ const response = await authApi.login({ email, password })
120
+
121
+ // 3. Store token securely
122
+ TokenStorage.save(response.token)
123
+
124
+ // 4. Update app state
125
+ appStore.setState({
126
+ user: response.user,
127
+ isAuthenticated: true
128
+ })
129
+
130
+ return response.user
131
+ },
132
+
133
+ async logout() {
134
+ try {
135
+ await authApi.logout()
136
+ } finally {
137
+ TokenStorage.clear()
138
+ appStore.setState({
139
+ user: null,
140
+ isAuthenticated: false
141
+ })
142
+ }
143
+ },
144
+
145
+ isAuthenticated() {
146
+ return !!TokenStorage.get()
147
+ }
148
+ }
149
+ ```
150
+
151
+ ## 4. Event Bus for Decoupling
152
+
153
+ **Use when:** Decoupled modules need to communicate without knowing about each other.
154
+
155
+ ```javascript
156
+ // lib/services/eventBus.js
157
+ const _ = require('alloy/underscore')._
158
+ const Backbone = require('alloy/backbone')
159
+
160
+ const EventBus = _.clone(Backbone.Events)
161
+
162
+ // Named events for type safety
163
+ const Events = {
164
+ USER_UPDATED: 'user:updated',
165
+ CART_CHANGED: 'cart:changed',
166
+ NETWORK_STATUS: 'network:status',
167
+ SYNC_COMPLETE: 'sync:complete'
168
+ }
169
+
170
+ module.exports = EventBus
171
+ module.exports.Events = Events
172
+ ```
173
+
174
+ **Usage in controllers:**
175
+
176
+ ```javascript
177
+ // controllers/profile.js
178
+ const EventBus = require('lib/services/eventBus')
179
+ const { Events } = EventBus
180
+
181
+ function init() {
182
+ EventBus.on(Events.USER_UPDATED, onUserUpdated)
183
+ }
184
+
185
+ function onUserUpdated(user) {
186
+ $.nameLabel.text = user.name
187
+ }
188
+
189
+ function cleanup() {
190
+ EventBus.off(Events.USER_UPDATED, onUserUpdated)
191
+ $.destroy()
192
+ }
193
+
194
+ $.cleanup = cleanup
195
+ ```
196
+
197
+ ## 5. Factory Pattern for Dynamic Views
198
+
199
+ **Use when:** Creating similar views with different configurations.
200
+
201
+ ```javascript
202
+ // lib/factories/cardFactory.js
203
+ exports.createProductCard = function(product) {
204
+ const card = Ti.UI.createView({
205
+ width: Ti.UI.FILL,
206
+ height: 120,
207
+ backgroundColor: '#fff'
208
+ })
209
+
210
+ const image = Ti.UI.createImageView({
211
+ image: product.imageUrl,
212
+ width: 80,
213
+ height: 80,
214
+ left: 16
215
+ })
216
+
217
+ const title = Ti.UI.createLabel({
218
+ text: product.name,
219
+ left: 112,
220
+ top: 16,
221
+ font: { fontSize: 16, fontWeight: 'bold' }
222
+ })
223
+
224
+ const price = Ti.UI.createLabel({
225
+ text: `$${product.price}`,
226
+ left: 112,
227
+ bottom: 16,
228
+ color: '#22c55e'
229
+ })
230
+
231
+ card.add(image)
232
+ card.add(title)
233
+ card.add(price)
234
+
235
+ // Attach data for event handling
236
+ card.productId = product.id
237
+
238
+ return card
239
+ }
240
+ ```
241
+
242
+ ## 6. Navigation Service Pattern
243
+
244
+ **Use when:** Centralizing navigation with automatic cleanup and history management.
245
+
246
+ ```javascript
247
+ // lib/services/navigation.js
248
+ const stack = []
249
+
250
+ exports.Navigation = {
251
+ open(route, params = {}, options = {}) {
252
+ const controller = Alloy.createController(route, params)
253
+ const view = controller.getView()
254
+
255
+ // Auto-cleanup on close
256
+ view.addEventListener('close', () => {
257
+ if (typeof controller.cleanup === 'function') {
258
+ controller.cleanup()
259
+ }
260
+ const idx = stack.findIndex(s => s.controller === controller)
261
+ if (idx !== -1) stack.splice(idx, 1)
262
+ })
263
+
264
+ stack.push({ route, controller, params })
265
+
266
+ if (options.modal) {
267
+ view.open({ modal: true })
268
+ } else if (options.animated === false) {
269
+ view.open({ animated: false })
270
+ } else {
271
+ view.open()
272
+ }
273
+
274
+ return controller
275
+ },
276
+
277
+ back() {
278
+ const current = stack[stack.length - 1]
279
+ if (current) {
280
+ current.controller.getView().close()
281
+ }
282
+ },
283
+
284
+ backTo(route) {
285
+ while (stack.length > 0) {
286
+ const current = stack[stack.length - 1]
287
+ if (current.route === route) break
288
+ current.controller.getView().close()
289
+ }
290
+ },
291
+
292
+ replace(route, params = {}) {
293
+ const current = stack.pop()
294
+ if (current) {
295
+ current.controller.getView().close({ animated: false })
296
+ }
297
+ return this.open(route, params, { animated: false })
298
+ },
299
+
300
+ getStack() {
301
+ return stack.map(s => s.route)
302
+ }
303
+ }
304
+ ```
305
+
306
+ ## 7. Collection Binding Pattern
307
+
308
+ **Use when:** Binding API data to ListViews with automatic updates.
309
+
310
+ ```javascript
311
+ // alloy.js - Initialize collection
312
+ Alloy.Collections.products = new Backbone.Collection()
313
+
314
+ // controllers/products/list.js
315
+ function init() {
316
+ loadProducts()
317
+
318
+ // Collection changes auto-update bound ListView
319
+ Alloy.Collections.products.on('reset add remove', onCollectionChange)
320
+ }
321
+
322
+ async function loadProducts() {
323
+ const products = await productApi.getAll()
324
+ Alloy.Collections.products.reset(products)
325
+ }
326
+
327
+ function onCollectionChange() {
328
+ // Optional: Handle empty state
329
+ $.emptyState.visible = Alloy.Collections.products.length === 0
330
+ }
331
+
332
+ function cleanup() {
333
+ Alloy.Collections.products.off('reset add remove', onCollectionChange)
334
+ $.destroy()
335
+ }
336
+
337
+ $.cleanup = cleanup
338
+ ```
339
+
340
+ ```xml
341
+ <!-- views/products/list.xml -->
342
+ <ListView class="wh-screen">
343
+ <ListSection dataCollection="products">
344
+ <ListItem title="{name}" subtitle="{description}" />
345
+ </ListSection>
346
+ </ListView>
347
+ ```
348
+
349
+ ## 8. Cleanup Pattern
350
+
351
+ **Use when:** Preventing memory leaks by removing global listeners.
352
+
353
+ ```javascript
354
+ // controllers/dashboard.js
355
+ const EventBus = require('lib/services/eventBus')
356
+ const { Events } = EventBus
357
+ const { appStore } = require('lib/services/stateStore')
358
+
359
+ // Store references for cleanup
360
+ let storeUnsubscribe = null
361
+
362
+ function init() {
363
+ // Event bus listeners
364
+ EventBus.on(Events.USER_UPDATED, onUserUpdated)
365
+ EventBus.on(Events.SYNC_COMPLETE, onSyncComplete)
366
+
367
+ // State store subscription
368
+ storeUnsubscribe = appStore.onChange(onStateChange)
369
+
370
+ // Ti.App listeners (avoid if possible, use EventBus)
371
+ Ti.App.addEventListener('pause', onAppPause)
372
+ Ti.App.addEventListener('resume', onAppResume)
373
+ }
374
+
375
+ function cleanup() {
376
+ // Remove all event bus listeners
377
+ EventBus.off(Events.USER_UPDATED, onUserUpdated)
378
+ EventBus.off(Events.SYNC_COMPLETE, onSyncComplete)
379
+
380
+ // Unsubscribe from store
381
+ if (storeUnsubscribe) {
382
+ storeUnsubscribe()
383
+ storeUnsubscribe = null
384
+ }
385
+
386
+ // Remove Ti.App listeners
387
+ Ti.App.removeEventListener('pause', onAppPause)
388
+ Ti.App.removeEventListener('resume', onAppResume)
389
+
390
+ // Destroy Alloy bindings
391
+ $.destroy()
392
+ }
393
+
394
+ // CRITICAL: Expose cleanup
395
+ $.cleanup = cleanup
396
+ ```
397
+
398
+ ## 9. Singleton Service Pattern
399
+
400
+ **Use when:** Services that should have only one instance app-wide.
401
+
402
+ ```javascript
403
+ // lib/services/analyticsService.js
404
+ let instance = null
405
+
406
+ class AnalyticsService {
407
+ constructor() {
408
+ if (instance) {
409
+ return instance
410
+ }
411
+
412
+ this.queue = []
413
+ this.isInitialized = false
414
+ instance = this
415
+ }
416
+
417
+ init(config) {
418
+ if (this.isInitialized) return
419
+
420
+ // Initialize analytics SDK
421
+ this.isInitialized = true
422
+
423
+ // Flush queued events
424
+ this.queue.forEach(event => this._send(event))
425
+ this.queue = []
426
+ }
427
+
428
+ track(eventName, properties = {}) {
429
+ const event = {
430
+ name: eventName,
431
+ properties,
432
+ timestamp: Date.now()
433
+ }
434
+
435
+ if (this.isInitialized) {
436
+ this._send(event)
437
+ } else {
438
+ this.queue.push(event)
439
+ }
440
+ }
441
+
442
+ _send(event) {
443
+ // Send to analytics backend
444
+ Ti.API.info(`[Analytics] ${event.name}`, event.properties)
445
+ }
446
+ }
447
+
448
+ exports.Analytics = new AnalyticsService()