@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,469 @@
1
+ # PurgeTSS & Code Conventions
2
+
3
+ ## Module System: CommonJS (NOT ES6 modules)
4
+
5
+ Titanium uses **CommonJS** for modules. Do NOT use ES6 `import`/`export`:
6
+
7
+ ```javascript
8
+ // CORRECT - CommonJS
9
+ const { Navigation } = require('lib/services/navigation')
10
+ exports.Navigation = { /* ... */ }
11
+
12
+ // WRONG - ES6 modules (won't work in Titanium)
13
+ import { Navigation } from 'lib/services/navigation'
14
+ export const Navigation = { /* ... */ }
15
+ ```
16
+
17
+ ## ES6+ Features (Non-Module)
18
+
19
+ Use `const`, `let`, destructuring, and template literals. Prefer arrow functions for callbacks and traditional functions for main logic.
20
+
21
+ ```javascript
22
+ const loadUserData = (userId) => {
23
+ const user = fetchUser(userId)
24
+ return { ...user, loadedAt: Date.now() }
25
+ }
26
+ ```
27
+
28
+ ## No Semicolons
29
+ Omit semicolons at the end of lines (ASI handles it).
30
+
31
+ ```javascript
32
+ const users = fetchUsers()
33
+ const name = user.name
34
+ ```
35
+
36
+ ## Styling with PurgeTSS (Utility-First)
37
+ Use utility classes for layout, colors, typography, and spacing. Avoid manual TSS files.
38
+
39
+ ```xml
40
+ <!-- GOOD: PurgeTSS Utility Classes -->
41
+ <View class="vertical h-auto w-screen bg-gray-100">
42
+ <Label class="m-4 text-xl font-bold text-blue-600" text="L('welcome')" />
43
+ </View>
44
+ ```
45
+
46
+ **Critical PurgeTSS Rules:**
47
+ - NO `flex-row`/`flex-col` → Use `horizontal`/`vertical`
48
+ - NO `w-full` → Use `w-screen`
49
+ - NO `p-*` on Views → Use `m-*` on children
50
+ - NO `justify-*`/`items-center` → Use margins/positioning
51
+
52
+ ## Platform & Device Modifiers
53
+ Leverage PurgeTSS modifiers instead of writing conditional logic in controllers.
54
+
55
+ ```xml
56
+ <View class="ios:mt-10 tablet:mt-20 mt-5" />
57
+ ```
58
+
59
+ ## applyProperties() Pattern
60
+ Use `applyProperties()` to batch UI updates and minimize bridge crossings for properties not managed by classes.
61
+
62
+ ```javascript
63
+ $.nameLabel.applyProperties({
64
+ text: user.name,
65
+ opacity: 1
66
+ })
67
+ ```
68
+
69
+ ## ListView Templates
70
+ Always use templates for performance. Never create views dynamically inside list rows.
71
+
72
+ ```javascript
73
+ function renderUsers(users) {
74
+ const data = users.map(user => ({
75
+ name: { text: user.name },
76
+ template: 'userTemplate'
77
+ }))
78
+ $.section.items = data
79
+ }
80
+ ```
81
+
82
+ ## Memory Cleanup
83
+ Always remove listeners to avoid memory leaks. Implement a `cleanup` function.
84
+
85
+ ```javascript
86
+ function cleanup() {
87
+ $.destroy()
88
+ // Remove Ti.App listeners here
89
+ }
90
+ ```
91
+
92
+ ## i18n and Accessibility (a11y)
93
+ Use `L()` for all text and always include `accessibilityLabel` for interactive elements.
94
+
95
+ ```xml
96
+ <Label text="L('welcome_message')" accessibilityLabel="Welcome Header" />
97
+ <ImageView class="fa-solid fa-user" accessibilityLabel="User Profile Picture" />
98
+ ```
99
+
100
+ ## Icon Fonts (PurgeTSS Workflow)
101
+ Integrate icons using classes generated by `purgetss build-fonts`. Classes are mapped to both `text` and `title` properties.
102
+
103
+ ```xml
104
+ <Label class="fa-solid fa-envelope mr-2 text-gray-400" />
105
+ <Button class="fas fa-play" title="L('play')" />
106
+ ```
107
+
108
+ ## Grid System
109
+ Use PurgeTSS percentage-based grid for alignments.
110
+
111
+ ```xml
112
+ <View class="horizontal w-screen">
113
+ <View class="w-8/12 bg-red-500" />
114
+ <View class="w-4/12 bg-blue-500" />
115
+ </View>
116
+ ```
117
+
118
+ For true grid layouts, use the Grid component:
119
+ ```xml
120
+ <View class="grid-cols-3 gap-2">
121
+ <View class="bg-red-500" />
122
+ <View class="bg-blue-500" />
123
+ <View class="bg-green-500" />
124
+ </View>
125
+ ```
126
+
127
+ ## Animation Component
128
+ PurgeTSS includes an Animation component (`purgetss.ui`) for 2D Matrix transformations.
129
+
130
+ ```xml
131
+ <Animation id="myAnim" module="purgetss.ui" class="close:opacity-0 duration-500 open:opacity-100" />
132
+ ```
133
+
134
+ ## Naming Conventions
135
+
136
+ ### Files and Folders
137
+ ```
138
+ app/
139
+ ├── controllers/
140
+ │ ├── index.js # camelCase for files
141
+ │ ├── user/ # lowercase folders
142
+ │ │ ├── profile.js # feature-based grouping
143
+ │ │ └── settings.js
144
+ ├── lib/
145
+ │ ├── api/
146
+ │ │ └── userApi.js # suffixed with type (Api, Service)
147
+ │ ├── services/
148
+ │ │ └── authService.js
149
+ │ └── helpers/
150
+ │ └── dateHelper.js
151
+ ├── views/
152
+ │ └── user/
153
+ │ └── profile.xml # match controller path exactly
154
+ ```
155
+
156
+ ### Variables and Functions
157
+ ```javascript
158
+ // Constants: UPPER_SNAKE_CASE
159
+ const API_BASE_URL = 'https://api.example.com'
160
+ const MAX_RETRY_COUNT = 3
161
+ const DEFAULT_TIMEOUT = 5000
162
+
163
+ // Variables: camelCase
164
+ const userId = $.args.userId
165
+ const isLoading = false
166
+ let currentPage = 1
167
+
168
+ // Functions: camelCase, verb prefix for actions
169
+ function loadUserData() { /* ... */ }
170
+ function handleLoginClick() { /* ... */ }
171
+ function validateEmail(email) { /* ... */ }
172
+
173
+ // Boolean variables: is/has/should prefix
174
+ const isAuthenticated = true
175
+ const hasPermission = false
176
+ const shouldRefresh = true
177
+
178
+ // Event handlers: on + Event
179
+ function onItemClick(e) { /* ... */ }
180
+ function onRefresh() { /* ... */ }
181
+ function onSearchChange(e) { /* ... */ }
182
+
183
+ // Private functions: underscore prefix (optional)
184
+ function _calculateTotal(items) { /* ... */ }
185
+ ```
186
+
187
+ ### Classes and Services
188
+ ```javascript
189
+ // Classes: PascalCase
190
+ class UserService {
191
+ constructor() { /* ... */ }
192
+ }
193
+
194
+ // Singleton exports: camelCase instance
195
+ exports.userService = new UserService()
196
+
197
+ // Factory functions: create prefix
198
+ function createHTTPClient(config) { /* ... */ }
199
+ function createAnimationController() { /* ... */ }
200
+ ```
201
+
202
+ ### Events and Constants
203
+ ```javascript
204
+ // Event names: namespace:action format
205
+ const Events = {
206
+ USER_LOGGED_IN: 'user:loggedIn',
207
+ USER_LOGGED_OUT: 'user:loggedOut',
208
+ CART_UPDATED: 'cart:updated',
209
+ NETWORK_ONLINE: 'network:online'
210
+ }
211
+
212
+ // Error codes: UPPER_SNAKE_CASE
213
+ const ErrorCodes = {
214
+ AUTH_ERROR: 'AUTH_ERROR',
215
+ NETWORK_ERROR: 'NETWORK_ERROR',
216
+ VALIDATION_ERROR: 'VALIDATION_ERROR'
217
+ }
218
+ ```
219
+
220
+ ## Import/Export Patterns
221
+
222
+ ### Named Exports (Preferred)
223
+ ```javascript
224
+ // lib/api/userApi.js
225
+ exports.getUser = async function(id) { /* ... */ }
226
+ exports.updateUser = async function(id, data) { /* ... */ }
227
+ exports.deleteUser = async function(id) { /* ... */ }
228
+
229
+ // Usage
230
+ const { getUser, updateUser } = require('lib/api/userApi')
231
+ ```
232
+
233
+ ### Default Export (For Classes/Singletons)
234
+ ```javascript
235
+ // lib/services/logger.js
236
+ class Logger {
237
+ debug(tag, message) { /* ... */ }
238
+ info(tag, message) { /* ... */ }
239
+ error(tag, message) { /* ... */ }
240
+ }
241
+
242
+ module.exports = new Logger()
243
+
244
+ // Usage
245
+ const logger = require('lib/services/logger')
246
+ ```
247
+
248
+ ### Mixed Exports
249
+ ```javascript
250
+ // lib/services/eventBus.js
251
+ const _ = require('alloy/underscore')._
252
+ const Backbone = require('alloy/backbone')
253
+
254
+ const EventBus = _.clone(Backbone.Events)
255
+
256
+ // Named export for event constants
257
+ exports.Events = {
258
+ USER_UPDATED: 'user:updated',
259
+ SYNC_COMPLETE: 'sync:complete'
260
+ }
261
+
262
+ // Default export for the bus itself
263
+ module.exports = EventBus
264
+
265
+ // Usage
266
+ const EventBus = require('lib/services/eventBus')
267
+ const { Events } = EventBus
268
+ ```
269
+
270
+ ### Re-exports (Barrel Files)
271
+ ```javascript
272
+ // lib/api/index.js - Barrel file
273
+ exports.userApi = require('./userApi').userApi
274
+ exports.productApi = require('./productApi').productApi
275
+ exports.orderApi = require('./orderApi').orderApi
276
+
277
+ // Usage - cleaner imports
278
+ const { userApi, productApi } = require('lib/api')
279
+ ```
280
+
281
+ ### CommonJS Compatibility
282
+ ```javascript
283
+ // When using native modules that use require()
284
+ const SomeNativeModule = require('ti.somemodule')
285
+
286
+ // Wrap in ES6 service
287
+ exports.nativeService = {
288
+ doSomething() {
289
+ return SomeNativeModule.performAction()
290
+ }
291
+ }
292
+ ```
293
+
294
+ ## Async/Promise Patterns
295
+
296
+ ### Async/Await (Preferred)
297
+ ```javascript
298
+ // Service layer - always async
299
+ exports.fetchUserProfile = async function(userId) {
300
+ const user = await userApi.getById(userId)
301
+ const preferences = await preferencesApi.getByUser(userId)
302
+
303
+ return {
304
+ ...user,
305
+ preferences
306
+ }
307
+ }
308
+
309
+ // Controller - with error handling
310
+ async function loadData() {
311
+ setLoading(true)
312
+
313
+ try {
314
+ const data = await service.fetchData()
315
+ renderData(data)
316
+ } catch (error) {
317
+ handleError(error)
318
+ } finally {
319
+ setLoading(false)
320
+ }
321
+ }
322
+ ```
323
+
324
+ ### Parallel Requests
325
+ ```javascript
326
+ // When requests are independent - run in parallel
327
+ async function loadDashboard() {
328
+ const [user, stats, notifications] = await Promise.all([
329
+ userService.getCurrentUser(),
330
+ statsService.getDashboardStats(),
331
+ notificationService.getUnread()
332
+ ])
333
+
334
+ renderDashboard({ user, stats, notifications })
335
+ }
336
+ ```
337
+
338
+ ### Sequential with Dependencies
339
+ ```javascript
340
+ // When each request depends on the previous
341
+ async function processOrder(cartId) {
342
+ // 1. Get cart (needed for order)
343
+ const cart = await cartService.getById(cartId)
344
+
345
+ // 2. Create order (needs cart data)
346
+ const order = await orderService.create(cart)
347
+
348
+ // 3. Process payment (needs order)
349
+ const payment = await paymentService.process(order.id)
350
+
351
+ return { order, payment }
352
+ }
353
+ ```
354
+
355
+ ### Error Handling with Specific Catches
356
+ ```javascript
357
+ async function login(email, password) {
358
+ try {
359
+ const result = await authService.login(email, password)
360
+ return result
361
+
362
+ } catch (error) {
363
+ // Handle specific error types differently
364
+ if (error.code === 'AUTH_ERROR') {
365
+ showMessage(L('invalid_credentials'))
366
+ } else if (error.code === 'NETWORK_ERROR') {
367
+ showMessage(L('check_connection'))
368
+ } else {
369
+ showMessage(L('unknown_error'))
370
+ logger.error('Login', 'Unexpected error', { error: error.message })
371
+ }
372
+
373
+ throw error // Re-throw for caller to handle if needed
374
+ }
375
+ }
376
+ ```
377
+
378
+ ### Converting Callbacks to Promises
379
+ ```javascript
380
+ // Wrap Ti.Network.createHTTPClient in Promise
381
+ function httpGet(url) {
382
+ return new Promise((resolve, reject) => {
383
+ const client = Ti.Network.createHTTPClient({
384
+ onload: function() {
385
+ try {
386
+ resolve(JSON.parse(this.responseText))
387
+ } catch (e) {
388
+ reject(new Error('Invalid JSON response'))
389
+ }
390
+ },
391
+ onerror: function(e) {
392
+ reject(new Error(e.error || 'Request failed'))
393
+ },
394
+ timeout: 10000
395
+ })
396
+
397
+ client.open('GET', url)
398
+ client.send()
399
+ })
400
+ }
401
+
402
+ // Wrap Ti.Media.showCamera in Promise
403
+ function takePhoto() {
404
+ return new Promise((resolve, reject) => {
405
+ Ti.Media.showCamera({
406
+ success: (e) => resolve(e.media),
407
+ cancel: () => reject(new Error('User cancelled')),
408
+ error: (e) => reject(new Error(e.error))
409
+ })
410
+ })
411
+ }
412
+ ```
413
+
414
+ ### Debouncing Async Operations
415
+ ```javascript
416
+ // Useful for search, auto-save, etc.
417
+ let searchTimeout = null
418
+
419
+ function onSearchChange(e) {
420
+ clearTimeout(searchTimeout)
421
+
422
+ searchTimeout = setTimeout(async () => {
423
+ const query = e.value.trim()
424
+
425
+ if (query.length < 2) {
426
+ return renderResults([])
427
+ }
428
+
429
+ try {
430
+ const results = await searchService.search(query)
431
+ renderResults(results)
432
+ } catch (error) {
433
+ // Ignore errors for outdated searches
434
+ logger.debug('Search', 'Search failed', { query })
435
+ }
436
+ }, 300)
437
+ }
438
+
439
+ function cleanup() {
440
+ clearTimeout(searchTimeout)
441
+ $.destroy()
442
+ }
443
+ ```
444
+
445
+ ### Retry Pattern
446
+ ```javascript
447
+ async function fetchWithRetry(fn, maxRetries = 3) {
448
+ let lastError
449
+
450
+ for (let i = 0; i < maxRetries; i++) {
451
+ try {
452
+ return await fn()
453
+ } catch (error) {
454
+ lastError = error
455
+
456
+ // Exponential backoff
457
+ const delay = Math.pow(2, i) * 1000
458
+ await new Promise(resolve => setTimeout(resolve, delay))
459
+
460
+ logger.warn('Retry', `Attempt ${i + 1} failed`, { error: error.message })
461
+ }
462
+ }
463
+
464
+ throw lastError
465
+ }
466
+
467
+ // Usage
468
+ const data = await fetchWithRetry(() => api.getData())
469
+ ```