@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.
- package/AGENTS-TEMPLATE.md +173 -0
- package/README.md +867 -0
- package/agents/ti-researcher.md +108 -0
- package/bin/titools.js +53 -0
- package/lib/commands/agents.js +126 -0
- package/lib/commands/install.js +188 -0
- package/lib/commands/uninstall.js +215 -0
- package/lib/commands/update.js +159 -0
- package/lib/config.js +119 -0
- package/lib/downloader.js +153 -0
- package/lib/installer.js +253 -0
- package/lib/platform.js +108 -0
- package/lib/symlink.js +142 -0
- package/lib/utils.js +270 -0
- package/package.json +67 -0
- package/skills/alloy-expert/SKILL.md +247 -0
- package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
- package/skills/alloy-expert/references/alloy-structure.md +381 -0
- package/skills/alloy-expert/references/anti-patterns.md +133 -0
- package/skills/alloy-expert/references/code-conventions.md +469 -0
- package/skills/alloy-expert/references/contracts.md +280 -0
- package/skills/alloy-expert/references/controller-patterns.md +520 -0
- package/skills/alloy-expert/references/error-handling.md +484 -0
- package/skills/alloy-expert/references/examples.md +735 -0
- package/skills/alloy-expert/references/migration-patterns.md +298 -0
- package/skills/alloy-expert/references/patterns.md +448 -0
- package/skills/alloy-expert/references/performance-patterns.md +855 -0
- package/skills/alloy-expert/references/security-patterns.md +847 -0
- package/skills/alloy-expert/references/state-management.md +779 -0
- package/skills/alloy-expert/references/testing.md +872 -0
- package/skills/alloy-guides/SKILL.md +214 -0
- package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
- package/skills/alloy-guides/references/CONCEPTS.md +191 -0
- package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
- package/skills/alloy-guides/references/MODELS.md +1028 -0
- package/skills/alloy-guides/references/PURGETSS.md +56 -0
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
- package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
- package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
- package/skills/alloy-guides/references/WIDGETS.md +176 -0
- package/skills/alloy-howtos/SKILL.md +203 -0
- package/skills/alloy-howtos/references/best_practices.md +138 -0
- package/skills/alloy-howtos/references/cli_reference.md +253 -0
- package/skills/alloy-howtos/references/config_files.md +87 -0
- package/skills/alloy-howtos/references/custom_tags.md +147 -0
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
- package/skills/alloy-howtos/references/samples.md +167 -0
- package/skills/purgetss/SKILL.md +442 -0
- package/skills/purgetss/assets/purgetss.config.cjs +17 -0
- package/skills/purgetss/references/EXAMPLES.md +247 -0
- package/skills/purgetss/references/animation-system.md +1294 -0
- package/skills/purgetss/references/apply-directive.md +375 -0
- package/skills/purgetss/references/arbitrary-values.md +612 -0
- package/skills/purgetss/references/class-index.md +1350 -0
- package/skills/purgetss/references/cli-commands.md +948 -0
- package/skills/purgetss/references/configurable-properties.md +654 -0
- package/skills/purgetss/references/custom-rules.md +161 -0
- package/skills/purgetss/references/customization-deep-dive.md +722 -0
- package/skills/purgetss/references/dynamic-component-creation.md +489 -0
- package/skills/purgetss/references/grid-layout.md +455 -0
- package/skills/purgetss/references/icon-fonts.md +609 -0
- package/skills/purgetss/references/installation-setup.md +366 -0
- package/skills/purgetss/references/opacity-modifier.md +291 -0
- package/skills/purgetss/references/platform-modifiers.md +479 -0
- package/skills/purgetss/references/smart-mappings.md +42 -0
- package/skills/purgetss/references/titanium-resets.md +359 -0
- package/skills/purgetss/references/ui-ux-design.md +1526 -0
- package/skills/ti-guides/SKILL.md +94 -0
- package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
- package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
- package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
- package/skills/ti-guides/references/android-manifest.md +97 -0
- package/skills/ti-guides/references/app-distribution.md +258 -0
- package/skills/ti-guides/references/application-frameworks.md +377 -0
- package/skills/ti-guides/references/cli-reference.md +402 -0
- package/skills/ti-guides/references/coding-best-practices.md +102 -0
- package/skills/ti-guides/references/commonjs-advanced.md +134 -0
- package/skills/ti-guides/references/hello-world.md +100 -0
- package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
- package/skills/ti-guides/references/javascript-primer.md +411 -0
- package/skills/ti-guides/references/reserved-words.md +36 -0
- package/skills/ti-guides/references/resources.md +183 -0
- package/skills/ti-guides/references/style-and-conventions.md +48 -0
- package/skills/ti-guides/references/tiapp-config.md +609 -0
- package/skills/ti-howtos/SKILL.md +174 -0
- package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
- package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
- package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
- package/skills/ti-howtos/references/cross-platform-development.md +348 -0
- package/skills/ti-howtos/references/debugging-profiling.md +543 -0
- package/skills/ti-howtos/references/extending-titanium.md +723 -0
- package/skills/ti-howtos/references/google-maps-v2.md +169 -0
- package/skills/ti-howtos/references/ios-map-kit.md +143 -0
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
- package/skills/ti-howtos/references/local-data-sources.md +301 -0
- package/skills/ti-howtos/references/location-and-maps.md +252 -0
- package/skills/ti-howtos/references/media-apis.md +210 -0
- package/skills/ti-howtos/references/notification-services.md +599 -0
- package/skills/ti-howtos/references/remote-data-sources.md +349 -0
- package/skills/ti-howtos/references/tutorials.md +502 -0
- package/skills/ti-howtos/references/using-modules.md +237 -0
- package/skills/ti-howtos/references/web-content-integration.md +307 -0
- package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
- package/skills/ti-ui/SKILL.md +179 -0
- package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
- package/skills/ti-ui/references/animation-and-matrices.md +599 -0
- package/skills/ti-ui/references/application-structures.md +655 -0
- package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
- package/skills/ti-ui/references/event-handling.md +393 -0
- package/skills/ti-ui/references/gestures.md +473 -0
- package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
- package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
- package/skills/ti-ui/references/listviews-and-performance.md +619 -0
- package/skills/ti-ui/references/orientation.md +362 -0
- package/skills/ti-ui/references/platform-ui-android.md +635 -0
- package/skills/ti-ui/references/platform-ui-ios.md +469 -0
- package/skills/ti-ui/references/scrolling-views.md +252 -0
- package/skills/ti-ui/references/tableviews.md +568 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Migration Patterns for Legacy Titanium Apps
|
|
2
|
+
|
|
3
|
+
## Assessment Checklist
|
|
4
|
+
|
|
5
|
+
Before migrating, evaluate the current codebase:
|
|
6
|
+
|
|
7
|
+
| Area | Signs of Legacy Code | Target State |
|
|
8
|
+
| ----------- | -------------------------------------------------- | ------------------------------- |
|
|
9
|
+
| Styling | Manual `.tss` files, inline attributes | PurgeTSS utility classes |
|
|
10
|
+
| Controllers | 200+ lines, API calls, business logic | Thin orchestrators (<100 lines) |
|
|
11
|
+
| Events | `Ti.App.fireEvent` everywhere | Backbone.Events or StateStore |
|
|
12
|
+
| Navigation | Direct `Alloy.createController().getView().open()` | Navigation service |
|
|
13
|
+
| Data | Scattered `Ti.App.Properties`, no collections | Centralized state + Collections |
|
|
14
|
+
|
|
15
|
+
## Phase 1: PurgeTSS Integration
|
|
16
|
+
|
|
17
|
+
**Goal**: Migrate from manual TSS to utility-first styling.
|
|
18
|
+
|
|
19
|
+
### Step 1: Initialize PurgeTSS
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# In existing project
|
|
23
|
+
cd your-app
|
|
24
|
+
purgetss init
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Step 2: Backup Existing Styles
|
|
28
|
+
|
|
29
|
+
PurgeTSS automatically backs up `app.tss` to `_app.tss`. Your custom styles are preserved.
|
|
30
|
+
|
|
31
|
+
### Step 3: Migrate Views Incrementally
|
|
32
|
+
|
|
33
|
+
```xml
|
|
34
|
+
<!-- BEFORE: Manual styling -->
|
|
35
|
+
<View id="header">
|
|
36
|
+
<Label id="title" text="Welcome" />
|
|
37
|
+
</View>
|
|
38
|
+
|
|
39
|
+
<!-- styles/index.tss -->
|
|
40
|
+
"#header": { backgroundColor: "#fff", height: 60, top: 0 }
|
|
41
|
+
"#title": { color: "#333", font: { fontSize: 18, fontWeight: "bold" } }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```xml
|
|
45
|
+
<!-- AFTER: PurgeTSS classes -->
|
|
46
|
+
<View class="top-0 h-16 bg-white">
|
|
47
|
+
<Label class="text-lg font-bold text-gray-800" text="Welcome" />
|
|
48
|
+
</View>
|
|
49
|
+
|
|
50
|
+
<!-- No manual TSS needed - delete #header and #title styles -->
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 4: Remove Manual TSS Files
|
|
54
|
+
|
|
55
|
+
Once a view is fully migrated to utility classes:
|
|
56
|
+
1. Remove corresponding entries from `_app.tss`
|
|
57
|
+
2. Delete any controller-specific `.tss` files
|
|
58
|
+
3. Run `purgetss` to regenerate `app.tss`
|
|
59
|
+
|
|
60
|
+
## Phase 2: Service Layer Extraction
|
|
61
|
+
|
|
62
|
+
**Goal**: Move business logic from controllers to services.
|
|
63
|
+
|
|
64
|
+
### Identify Fat Controllers
|
|
65
|
+
|
|
66
|
+
Signs of a fat controller:
|
|
67
|
+
- API calls with `Ti.Network.createHTTPClient`
|
|
68
|
+
- Complex data transformations
|
|
69
|
+
- Native module interactions
|
|
70
|
+
- 100+ lines of code
|
|
71
|
+
|
|
72
|
+
### Extract to Services
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// BEFORE: Fat controller
|
|
76
|
+
// controllers/user/profile.js
|
|
77
|
+
function loadProfile() {
|
|
78
|
+
const client = Ti.Network.createHTTPClient({
|
|
79
|
+
onload: function() {
|
|
80
|
+
const data = JSON.parse(this.responseText)
|
|
81
|
+
// 50 lines of data transformation...
|
|
82
|
+
updateUI(transformedData)
|
|
83
|
+
},
|
|
84
|
+
onerror: function() {
|
|
85
|
+
// Error handling...
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
client.open('GET', 'https://api.example.com/profile')
|
|
89
|
+
client.setRequestHeader('Authorization', 'Bearer ' + token)
|
|
90
|
+
client.send()
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
// AFTER: Thin controller + Service
|
|
96
|
+
// lib/api/userApi.js
|
|
97
|
+
exports.getProfile = async function() {
|
|
98
|
+
return apiClient.get('/profile')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// lib/services/userService.js
|
|
102
|
+
exports.loadUserProfile = async function() {
|
|
103
|
+
const data = await userApi.getProfile()
|
|
104
|
+
return transformProfile(data)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// controllers/user/profile.js
|
|
108
|
+
async function loadProfile() {
|
|
109
|
+
try {
|
|
110
|
+
const profile = await userService.loadUserProfile()
|
|
111
|
+
updateUI(profile)
|
|
112
|
+
} catch (error) {
|
|
113
|
+
handleError(error)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Phase 3: Event System Migration
|
|
119
|
+
|
|
120
|
+
**Goal**: Replace `Ti.App.fireEvent` with Backbone.Events.
|
|
121
|
+
|
|
122
|
+
### Step 1: Create Event Bus
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// alloy.js
|
|
126
|
+
Alloy.Events = _.clone(Backbone.Events)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Step 2: Find All Ti.App Event Usage
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Find all Ti.App.fireEvent calls
|
|
133
|
+
grep -r "Ti.App.fireEvent" app/controllers/
|
|
134
|
+
grep -r "Ti.App.addEventListener" app/controllers/
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Step 3: Migrate Events
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
// BEFORE: Ti.App events (memory leaks, no cleanup)
|
|
141
|
+
Ti.App.fireEvent('user:updated', { user: userData })
|
|
142
|
+
Ti.App.addEventListener('user:updated', onUserUpdated)
|
|
143
|
+
|
|
144
|
+
// AFTER: Backbone.Events (proper cleanup)
|
|
145
|
+
Alloy.Events.trigger('user:updated', { user: userData })
|
|
146
|
+
Alloy.Events.on('user:updated', onUserUpdated)
|
|
147
|
+
|
|
148
|
+
// In cleanup()
|
|
149
|
+
Alloy.Events.off('user:updated', onUserUpdated)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Step 4: Add Cleanup Functions
|
|
153
|
+
|
|
154
|
+
Every controller that listens to events needs cleanup:
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// controllers/dashboard.js
|
|
158
|
+
function init() {
|
|
159
|
+
Alloy.Events.on('user:updated', refreshUser)
|
|
160
|
+
Alloy.Events.on('data:sync', refreshData)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function cleanup() {
|
|
164
|
+
Alloy.Events.off('user:updated', refreshUser)
|
|
165
|
+
Alloy.Events.off('data:sync', refreshData)
|
|
166
|
+
$.destroy()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
$.cleanup = cleanup
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Phase 4: Navigation Service
|
|
173
|
+
|
|
174
|
+
**Goal**: Centralize navigation with automatic cleanup.
|
|
175
|
+
|
|
176
|
+
### Step 1: Create Navigation Service
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// lib/services/navigation.js
|
|
180
|
+
const stack = []
|
|
181
|
+
|
|
182
|
+
exports.open = function(route, params = {}, options = {}) {
|
|
183
|
+
const controller = Alloy.createController(route, params)
|
|
184
|
+
const view = controller.getView()
|
|
185
|
+
|
|
186
|
+
// Bind cleanup to close event
|
|
187
|
+
view.addEventListener('close', () => {
|
|
188
|
+
if (controller.cleanup) {
|
|
189
|
+
controller.cleanup()
|
|
190
|
+
}
|
|
191
|
+
stack.pop()
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
stack.push({ route, controller })
|
|
195
|
+
|
|
196
|
+
if (options.modal) {
|
|
197
|
+
view.open({ modal: true })
|
|
198
|
+
} else {
|
|
199
|
+
view.open()
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return controller
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
exports.back = function() {
|
|
206
|
+
const current = stack[stack.length - 1]
|
|
207
|
+
if (current) {
|
|
208
|
+
current.controller.getView().close()
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
exports.getStack = function() {
|
|
213
|
+
return [...stack]
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Step 2: Replace Direct Navigation
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
// BEFORE: Direct navigation (no cleanup)
|
|
221
|
+
Alloy.createController('detail', { id: 123 }).getView().open()
|
|
222
|
+
|
|
223
|
+
// AFTER: Navigation service (auto cleanup)
|
|
224
|
+
const navigation = require('lib/services/navigation')
|
|
225
|
+
navigation.open('detail', { id: 123 })
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Phase 5: State Management
|
|
229
|
+
|
|
230
|
+
**Goal**: Centralize app state for consistency.
|
|
231
|
+
|
|
232
|
+
### Step 1: Identify Scattered State
|
|
233
|
+
|
|
234
|
+
Look for:
|
|
235
|
+
- `Ti.App.Properties.getString/setString` scattered across controllers
|
|
236
|
+
- `Alloy.Globals` for sharing data
|
|
237
|
+
- Direct collection access from multiple controllers
|
|
238
|
+
|
|
239
|
+
### Step 2: Create State Store
|
|
240
|
+
|
|
241
|
+
See [state-management.md](state-management.md) for full implementation.
|
|
242
|
+
|
|
243
|
+
### Step 3: Migrate State Access
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
// BEFORE: Scattered state
|
|
247
|
+
// In controller A
|
|
248
|
+
Ti.App.Properties.setString('user', JSON.stringify(user))
|
|
249
|
+
|
|
250
|
+
// In controller B
|
|
251
|
+
const user = JSON.parse(Ti.App.Properties.getString('user'))
|
|
252
|
+
|
|
253
|
+
// AFTER: Centralized state
|
|
254
|
+
// In service
|
|
255
|
+
const { appStore } = require('lib/services/stateStore')
|
|
256
|
+
appStore.setState({ user })
|
|
257
|
+
|
|
258
|
+
// In any controller
|
|
259
|
+
const { user } = appStore.getState()
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Migration Order
|
|
263
|
+
|
|
264
|
+
Recommended sequence to minimize risk:
|
|
265
|
+
|
|
266
|
+
1. **PurgeTSS** - Visual only, no logic changes
|
|
267
|
+
2. **Service Layer** - Extract logic without changing behavior
|
|
268
|
+
3. **Navigation Service** - Centralize with cleanup
|
|
269
|
+
4. **Event System** - Replace Ti.App events
|
|
270
|
+
5. **State Management** - Last, as it touches everything
|
|
271
|
+
|
|
272
|
+
## Rollback Strategy
|
|
273
|
+
|
|
274
|
+
For each phase:
|
|
275
|
+
|
|
276
|
+
1. **Create a branch** before starting
|
|
277
|
+
2. **Migrate one feature** completely
|
|
278
|
+
3. **Test thoroughly** before moving to next feature
|
|
279
|
+
4. **Keep legacy code** commented until stable
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// Temporary: Keep both during migration
|
|
283
|
+
// Legacy:
|
|
284
|
+
// Ti.App.fireEvent('user:updated', data)
|
|
285
|
+
|
|
286
|
+
// New:
|
|
287
|
+
Alloy.Events.trigger('user:updated', data)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Common Migration Pitfalls
|
|
291
|
+
|
|
292
|
+
| Pitfall | Consequence | Prevention |
|
|
293
|
+
| -------------------------------- | ------------------- | ------------------------------------ |
|
|
294
|
+
| Migrating styles without testing | Broken layouts | Test each view on both platforms |
|
|
295
|
+
| Forgetting cleanup functions | Memory leaks | Add cleanup before adding listeners |
|
|
296
|
+
| Partial event migration | Duplicate events | Grep for all usages before migrating |
|
|
297
|
+
| Breaking navigation flow | Lost state, crashes | Test all navigation paths |
|
|
298
|
+
| Rushing state migration | Inconsistent UI | Migrate one state slice at a time |
|