@maccesar/titools 3.2.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 (102) 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 +184 -181
  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 +41 -410
  36. package/skills/purgetss/references/custom-fonts.md +292 -0
  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 +208 -118
  40. package/skills/purgetss/references/installation-setup.md +4 -4
  41. package/skills/purgetss/references/migration-guide.md +53 -1
  42. package/skills/purgetss/references/multi-density-images.md +53 -2
  43. package/skills/purgetss/references/svg-pipeline.md +249 -0
  44. package/skills/purgetss/references/tikit-components.md +2 -2
  45. package/skills/purgetss/references/titanium-resets.md +2 -2
  46. package/skills/purgetss/references/ui-ux-design.md +7 -5
  47. package/skills/purgetss/references/version-history.md +71 -82
  48. package/skills/ti-api/SKILL.md +128 -0
  49. package/skills/ti-api/references/api-android.md +675 -0
  50. package/skills/ti-api/references/api-app-platform.md +636 -0
  51. package/skills/ti-api/references/api-core.md +764 -0
  52. package/skills/ti-api/references/api-data-network.md +641 -0
  53. package/skills/ti-api/references/api-media.md +655 -0
  54. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  55. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  56. package/skills/ti-api/references/api-modules-map.md +632 -0
  57. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  58. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  59. package/skills/ti-api/references/api-services.md +700 -0
  60. package/skills/ti-api/references/api-ui-android.md +499 -0
  61. package/skills/ti-api/references/api-ui-extras.md +702 -0
  62. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  63. package/skills/ti-api/references/api-ui-ios.md +756 -0
  64. package/skills/ti-api/references/api-ui-lists.md +581 -0
  65. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  66. package/skills/ti-api/references/api-ui-views.md +572 -0
  67. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  68. package/skills/ti-api/references/api-xml-global.md +743 -0
  69. package/skills/ti-guides/SKILL.md +82 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
  71. package/skills/ti-guides/references/android-manifest.md +97 -0
  72. package/skills/ti-guides/references/app-distribution.md +373 -0
  73. package/skills/ti-guides/references/application-frameworks.md +366 -0
  74. package/skills/ti-guides/references/cli-reference.md +700 -0
  75. package/skills/ti-guides/references/coding-best-practices.md +150 -0
  76. package/skills/ti-guides/references/commonjs-advanced.md +279 -0
  77. package/skills/ti-guides/references/hello-world.md +99 -0
  78. package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
  79. package/skills/ti-guides/references/javascript-primer.md +402 -0
  80. package/skills/ti-guides/references/reserved-words.md +36 -0
  81. package/skills/ti-guides/references/resources.md +172 -0
  82. package/skills/ti-guides/references/style-and-conventions.md +104 -0
  83. package/skills/ti-guides/references/tiapp-config.md +655 -0
  84. package/skills/ti-howtos/SKILL.md +131 -0
  85. package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
  86. package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
  87. package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
  88. package/skills/ti-howtos/references/cross-platform-development.md +358 -0
  89. package/skills/ti-howtos/references/debugging-profiling.md +473 -0
  90. package/skills/ti-howtos/references/extending-titanium.md +684 -0
  91. package/skills/ti-howtos/references/google-maps-v2.md +172 -0
  92. package/skills/ti-howtos/references/ios-map-kit.md +149 -0
  93. package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
  94. package/skills/ti-howtos/references/local-data-sources.md +310 -0
  95. package/skills/ti-howtos/references/location-and-maps.md +267 -0
  96. package/skills/ti-howtos/references/media-apis.md +268 -0
  97. package/skills/ti-howtos/references/notification-services.md +539 -0
  98. package/skills/ti-howtos/references/remote-data-sources.md +339 -0
  99. package/skills/ti-howtos/references/tutorials.md +552 -0
  100. package/skills/ti-howtos/references/using-modules.md +182 -0
  101. package/skills/ti-howtos/references/web-content-integration.md +288 -0
  102. package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
@@ -0,0 +1,150 @@
1
+ # Coding best practices
2
+
3
+ Titanium apps are easiest to maintain when they use a single-context, modular pattern with clear structure and organized resources.
4
+
5
+ ## 1. Scope management
6
+
7
+ - Avoid global scope. Global variables are not automatically garbage collected and can create naming conflicts.
8
+ - Always use `let` or `const`. The original guide uses `var`, but modern code should not. Omitting declarations places variables in global scope.
9
+
10
+ ## 2. Memory leak prevention
11
+
12
+ - Listeners on `Ti.App`, `Ti.Geolocation`, and similar globals can leak memory if they reference local objects and are not removed.
13
+ ```javascript
14
+ // Anti-pattern
15
+ Ti.App.addEventListener('data:sync', (e) => {
16
+ localView.text = e.text // localView is now leaked
17
+ })
18
+ ```
19
+ - Rule: global events should only handle global objects. Always `removeEventListener` during cleanup.
20
+
21
+ ## 3. Event naming conventions
22
+
23
+ - Do not use spaces in event names. Spaces can cause issues with Backbone.js and other libraries that split event names on spaces.
24
+ ```javascript
25
+ // Wrong - may fire multiple times
26
+ Ti.App.fireEvent('my event')
27
+
28
+ // Correct - use colon or underscore
29
+ Ti.App.fireEvent('my:event')
30
+ Ti.App.fireEvent('my_event')
31
+ ```
32
+
33
+ ## 4. Performance
34
+
35
+ - Defer script loading. Only `require` modules when you need them.
36
+
37
+ Defer loading to reduce startup time. Only `require` modules when you need them.
38
+
39
+ Lazy script loading example:
40
+ ```javascript
41
+ // must be loaded at launch
42
+ const WindowOne = require('ui/WindowOne').WindowOne;
43
+ const win1 = new WindowOne();
44
+ win1.open();
45
+
46
+ win1.addEventListener('click', () => {
47
+ // load window two JavaScript only when needed
48
+ const WindowTwo = require('ui/WindowTwo').WindowTwo;
49
+ const win2 = new WindowTwo();
50
+ win2.open();
51
+
52
+ win2.addEventListener('click', () => {
53
+ // load window three JavaScript only when needed
54
+ const WindowThree = require('ui/WindowThree').WindowThree;
55
+ const win3 = new WindowThree();
56
+ win3.open();
57
+ });
58
+ });
59
+ ```
60
+
61
+ - Bridge efficiency: minimize requests for device properties like `Ti.Platform.osname`. Store them in a local variable:
62
+ ```javascript
63
+ const isAndroid = (Ti.Platform.osname === 'android')
64
+ if (isAndroid) { /* Android path */ } else { /* iOS path */ }
65
+ ```
66
+ - Avoid extending the `Ti` namespace. Three reasons:
67
+ 1. Ti objects are proxies to native OS components — your extensions may conflict with native functionality.
68
+ 2. Arrays stored on the namespace may be immutable; objects may be null unexpectedly.
69
+ 3. There is no guarantee properties persist across SDK versions.
70
+ Use your own namespace or CommonJS module instead of modifying `Ti`.
71
+
72
+ ## 5. App architecture recommendations
73
+
74
+ ### Modular components with CommonJS (recommended)
75
+
76
+ Titanium's primary recommended architecture. It uses discrete modules and avoids globals. See `commonjs-advanced.md` for module patterns and path resolution.
77
+
78
+ MyModule.js:
79
+ ```javascript
80
+ // Private variable
81
+ const defaultMessage = "Hello world";
82
+
83
+ exports.sayHello = (msg) => {
84
+ Ti.API.info('Hello ' + msg);
85
+ };
86
+
87
+ exports.helloWorld = () => {
88
+ Ti.API.info(defaultMessage);
89
+ }
90
+ ```
91
+
92
+ app.js:
93
+ ```javascript
94
+ const myModule = require('/MyModule');
95
+ myModule.sayHello('User');
96
+ ```
97
+
98
+ ### Namespace with deferred loading (alternative pattern)
99
+
100
+ If not using CommonJS, you can still defer loading with a namespace:
101
+
102
+ ```javascript
103
+ const someNameSpace = () => {
104
+ const API = {
105
+ init() {
106
+ // create UI or initialize
107
+ },
108
+ reset() {
109
+ // null objects, clean up
110
+ }
111
+ }
112
+ return API
113
+ }
114
+ const ns = new someNameSpace()
115
+ ```
116
+
117
+ ### Custom objects as components
118
+
119
+ Popular for rapid deployment. It uses a namespace hierarchy. This pattern is less efficient than CommonJS modules, and object references can persist after they are no longer needed.
120
+
121
+ ```javascript
122
+ const myapp = {};
123
+ (() => {
124
+ myapp.ui = {};
125
+ myapp.ui.createApplicationWindow = () => {
126
+ const win = Ti.UI.createWindow({ backgroundColor:'white' });
127
+ return win;
128
+ };
129
+ })();
130
+ ```
131
+
132
+ ### Classical-based patterns
133
+
134
+ Not recommended. JavaScript is not class-based in the same way, and this approach adds overhead during rapid prototyping.
135
+
136
+ ## 6. Security best practices
137
+
138
+ - Do not store sensitive data in non-JS files. JavaScript files are minified and obfuscated, but images, JSON, SQLite databases, and other non-JS files are packaged as-is. APK and IPA files are ZIP files that can be extracted.
139
+ ```javascript
140
+ // Wrong - API keys visible in app/assets/config.json
141
+ const config = require('assets/config.json')
142
+
143
+ // Correct - store in code or use secure storage
144
+ const API_KEY = Ti.App.Properties.getString('api_key')
145
+ ```
146
+
147
+ ## 7. Multiplatform strategies
148
+
149
+ - Code branching: use for small differences.
150
+ - Platform files: use `.ios.js` or `.android.js` for major logic differences so code stays readable.
@@ -0,0 +1,279 @@
1
+ # CommonJS advanced patterns
2
+
3
+ For more on CommonJS in Titanium, see the official CommonJS Modules guide in the Titanium SDK documentation.
4
+
5
+ ## Definitions
6
+
7
+ - Module: any CommonJS-compliant module used in a Titanium SDK application. This can be a JavaScript file bundled with the app or a native extension that exposes a JavaScript API.
8
+ - Resources: the Resources directory of a Titanium application, where source code lives before the build system processes it. In Alloy, CommonJS modules live in `app/lib`.
9
+ - `exports`: a free variable within a module. Add properties to expose a public API.
10
+ - `module.exports`: an object you can replace to define the module's public API.
11
+
12
+ ## 1. Stateful modules (singleton pattern)
13
+
14
+ Modules in Titanium are created once per JavaScript context and reused on subsequent `require()` calls. This makes them useful for shared state.
15
+
16
+ ### Example: stateful counter module
17
+
18
+ ```javascript
19
+ // app/lib/counter.js
20
+ let _count = 0
21
+
22
+ exports.increment = () => {
23
+ _count++
24
+ }
25
+
26
+ exports.getCount = () => {
27
+ return _count
28
+ }
29
+
30
+ exports.reset = () => {
31
+ _count = 0
32
+ }
33
+ ```
34
+
35
+ Usage: multiple controllers that require this module share the same `_count` state.
36
+
37
+ A module is created once per Titanium JavaScript context. Additional contexts create new module instances.
38
+
39
+ ## 2. Native/compiled modules
40
+
41
+ When `require()` is called, Titanium checks for a native/compiled module before it looks for a JavaScript module. Native modules take priority.
42
+
43
+ Native modules are identified by a single string and configured in `tiapp.xml`:
44
+
45
+ ```xml
46
+ <modules>
47
+ <module version="1.0">ti.paypal</module>
48
+ </modules>
49
+ ```
50
+
51
+ ```javascript
52
+ const paypal = require('ti.paypal')
53
+ ```
54
+
55
+ Titanium loads `ti.paypal` as a native module and will not look for a JavaScript file in Resources. If no native module matches, it falls back to JavaScript module resolution.
56
+
57
+ ## 3. Module path resolution
58
+
59
+ The string passed to `require()` is treated as a path to a JavaScript file, without the `.js` extension.
60
+
61
+ Resolution rules:
62
+ - No prefix (`require('app/lib/myModule')`): resolved relative to the `Resources` directory (or `app/lib` in Alloy)
63
+ - `/` prefix (`require('/app/lib/myModule')`): also resolved relative to the `Resources` directory
64
+ - `./` or `../` prefix (`require('./widgets/SomeView')`): resolved relative to the current module file
65
+
66
+ Example with relative paths:
67
+
68
+ Given these files:
69
+ - `Resources/app/ui/SomeCustomView.js`
70
+ - `Resources/app/ui/widgets/SomeOtherCustomView.js`
71
+ - `Resources/app/lib/myModule.js`
72
+
73
+ Inside `SomeCustomView.js`:
74
+ ```javascript
75
+ const myModule = require('../lib/myModule')
76
+ const SomeOtherCustomView = require('./widgets/SomeOtherCustomView')
77
+ ```
78
+
79
+ The `.js` extension is omitted in `require()` calls.
80
+
81
+ ## 4. Caching behavior
82
+
83
+ Titanium caches the object returned by `require()` and returns the same reference without re-evaluating the code.
84
+
85
+ If you need code evaluated multiple times, export a function that creates what you need instead.
86
+
87
+ ```javascript
88
+ // Good: factory pattern
89
+ exports.createView = (args) => {
90
+ return Ti.UI.createView(args)
91
+ }
92
+
93
+ // Bad: expecting re-evaluation
94
+ ```
95
+
96
+ ## 5. ES6+ support (SDK 7.1.0+)
97
+
98
+ Since Titanium SDK 7.1.0, you can use ES6+ module syntax. Code is transpiled to ES5 for all platforms.
99
+
100
+ ```javascript
101
+ // MyClass.js
102
+ export default class MyClass {
103
+ constructor(name) {
104
+ this.name = name
105
+ }
106
+
107
+ greet() {
108
+ return `Hello, ${this.name}`
109
+ }
110
+ }
111
+
112
+ // Usage in controller
113
+ import MyClass from 'MyClass'
114
+ const instance = new MyClass('World')
115
+ ```
116
+
117
+ ## 6. Module composition patterns
118
+
119
+ ### Exports object pattern
120
+
121
+ ```javascript
122
+ exports.sayHello = (name) => {
123
+ Ti.API.info(`Hello ${name}`)
124
+ }
125
+
126
+ exports.version = 1.4
127
+ ```
128
+
129
+ ### Constructor pattern (`module.exports`)
130
+
131
+ ```javascript
132
+ class Person {
133
+ constructor(firstName, lastName) {
134
+ this.firstName = firstName
135
+ this.lastName = lastName
136
+ }
137
+
138
+ fullName() {
139
+ return `${this.firstName} ${this.lastName}`
140
+ }
141
+ }
142
+
143
+ module.exports = Person
144
+ ```
145
+
146
+ ### Utility library pattern
147
+
148
+ ```javascript
149
+ // app/lib/logger.js
150
+ exports.info = (str) => {
151
+ Ti.API.info(`${new Date()}: ${str}`)
152
+ }
153
+
154
+ exports.debug = (str) => {
155
+ Ti.API.debug(`${new Date()}: ${str}`)
156
+ }
157
+ ```
158
+
159
+ Usage:
160
+ ```javascript
161
+ const logger = require('logger')
162
+ logger.info('some log statement with a timestamp')
163
+ ```
164
+
165
+ ## 7. Packages of related functionality
166
+
167
+ Group related classes or helpers in a single module:
168
+
169
+ ```javascript
170
+ // app/lib/geo.js
171
+ class Point {
172
+ constructor(x, y) {
173
+ this.x = x
174
+ this.y = y
175
+ }
176
+ }
177
+
178
+ class Line {
179
+ constructor(start, end) {
180
+ this.start = start
181
+ this.end = end
182
+ }
183
+
184
+ slope() {
185
+ return (this.end.y - this.start.y) / (this.end.x - this.start.x)
186
+ }
187
+
188
+ yIntercept() {
189
+ return this.start.y - (this.slope() * this.start.x)
190
+ }
191
+ }
192
+
193
+ exports.Point = Point
194
+ exports.Line = Line
195
+ ```
196
+
197
+ Usage:
198
+ ```javascript
199
+ const Geo = require('lib/geo')
200
+
201
+ const start = new Geo.Point(1, -5)
202
+ const end = new Geo.Point(10, 2)
203
+ const line = new Geo.Line(start, end)
204
+ Ti.API.info(line.slope())
205
+ ```
206
+
207
+ ## 8. Inter-module state sharing
208
+
209
+ When a module assigns a primitive value to `exports`, the consumer gets a copy, not a live reference. Changes to the internal variable are not reflected in the exported property.
210
+
211
+ ```javascript
212
+ // app/lib/statefulModule.js
213
+ let _stepVal = 5
214
+
215
+ exports.setPointStep = (value) => {
216
+ _stepVal = value
217
+ }
218
+
219
+ exports.getPointStep = () => {
220
+ return _stepVal
221
+ }
222
+
223
+ exports.stepVal = _stepVal // This is a copy of _stepVal (value: 5)
224
+ ```
225
+
226
+ ```javascript
227
+ const stateful = require('statefulModule')
228
+ stateful.setPointStep(10)
229
+ Ti.API.info(stateful.getPointStep()) // 10 - correct, uses getter
230
+ Ti.API.info(stateful.stepVal) // 5 - still the original copy
231
+ ```
232
+
233
+ Rule: use getter/setter functions for stateful values. Direct property exports of primitives are snapshots at module load time.
234
+
235
+ ## 9. Antipatterns to avoid
236
+
237
+ ### Do not assign directly to `exports`
238
+
239
+ ```javascript
240
+ // Wrong
241
+ function Person() {}
242
+ exports = Person
243
+
244
+ // Correct
245
+ module.exports = Person
246
+ ```
247
+
248
+ ### Do not mix `module.exports` and `exports.*`
249
+
250
+ ```javascript
251
+ // Discouraged
252
+ module.exports = Person
253
+ exports.foo = 'bar'
254
+
255
+ // Use one consistently
256
+ ```
257
+
258
+ ### Avoid globals across modules
259
+
260
+ Any data a module needs should be passed during construction or initialization. Avoid globals shared across modules.
261
+
262
+ ## 10. Security and scope
263
+
264
+ All modules have private scope. Variables declared within the module are private unless added to `exports`.
265
+
266
+ ```javascript
267
+ const _privateVar = 'secret' // Not accessible outside
268
+
269
+ exports.publicMethod = () => {
270
+ // Can access _privateVar
271
+ return _privateVar
272
+ }
273
+ ```
274
+
275
+ ## 11. Node.js compatibility
276
+
277
+ Titanium supports Node.js module patterns and `require()` resolution. Node.js modules can often be used directly.
278
+
279
+ For details, refer to the official Titanium Node.js guide.
@@ -0,0 +1,99 @@
1
+ # Hello world: project creation
2
+
3
+ Quick guide to creating your first Titanium project.
4
+
5
+ ## Creating a new project
6
+
7
+ ### Using CLI
8
+
9
+ ```bash
10
+ ti create -t app --id <APP_ID> -n <APP_NAME> -p <PLATFORMS> -d <WORKSPACE>
11
+ ```
12
+
13
+ Example:
14
+ ```bash
15
+ ti create -t app --id com.example.hello -n HelloWorld -p android,ios -d ~/Projects
16
+ ```
17
+
18
+ ### Using VS Code
19
+
20
+ VS Code with the Titanium extension supports project creation via the command palette. The CLI is the most reliable method and works in any editor.
21
+
22
+ ## Project fields
23
+
24
+ | Field | Description | Rules |
25
+ | ------------------ | ----------------------- | -------------------------- |
26
+ | Project name | App name shown to users | - |
27
+ | App ID | Reverse domain notation | `com.company.appname` |
28
+ | Company URL | Your website | - |
29
+ | SDK Version | Titanium SDK to use | Use latest |
30
+ | Deployment Targets | Platforms to support | android, ios, ipad, iphone |
31
+
32
+ ### App ID naming guidelines
33
+
34
+ - Use Java package style: `com.yourdomain.yourappname`
35
+ - No spaces or special characters
36
+ - All lowercase (Android issues with uppercase)
37
+ - No Java keywords (`case`, `package`, etc.)
38
+ - Cannot change after publishing
39
+ - On iOS, the App ID must match the Bundle Identifier. On Android, it becomes the Application Package Name.
40
+
41
+ ## Project structure
42
+
43
+ ```
44
+ MyApp/
45
+ ├── app/ # Alloy app source
46
+ │ ├── assets/ # Images, fonts
47
+ │ ├── controllers/ # JS controllers
48
+ │ ├── models/ # Backbone models
49
+ │ ├── views/ # XML views
50
+ │ └── styles/ # TSS styles
51
+ ├── platform/ # Platform-specific files
52
+ │ ├── android/
53
+ │ └── ios/
54
+ ├── Resources/ # Code files and graphics with platform-specific subdirectories
55
+ │ ├── android/ # Android-specific assets
56
+ │ └── iphone/ # iOS-specific assets
57
+ ├── i18n/ # Internationalization
58
+ ├── tiapp.xml # App configuration
59
+ ├── config.json # Alloy config
60
+ └── app.js # Bootstrap file loaded first when app launches
61
+ ```
62
+
63
+ ## Running your app
64
+
65
+ ### iOS simulator
66
+ ```bash
67
+ ti build -p ios -C "iPhone 15"
68
+ ```
69
+
70
+ ### Android emulator
71
+ ```bash
72
+ ti build -p android -C "Pixel_4_API_34"
73
+ ```
74
+
75
+ ### Physical device
76
+ ```bash
77
+ ti build -p ios -T device
78
+ ti build -p android -T device
79
+ ```
80
+
81
+ ## Simulator vs emulator
82
+
83
+ - iOS simulator: simulates the environment within an iOS device. It is a macOS executable that runs your cross-compiled code.
84
+ - Android emulator: provides a virtual hardware environment that runs the Android OS and platform components.
85
+
86
+ Neither environment is a perfect representation of a physical device. Always test on real hardware before publishing.
87
+
88
+ ## How Titanium works (under the covers)
89
+
90
+ 1. Pre-compile: JavaScript is minified and statically analyzed to build a dependency hierarchy of Titanium APIs used.
91
+ 2. Stub generation: a front-end compiler creates native stub files, native project files, and platform-specific code needed for compilation.
92
+ 3. Native build: Titanium calls platform-specific compilers (for example, `xcodebuild` for iOS and Gradle for Android) to build the native app.
93
+ 4. Encryption: JavaScript code is encrypted when building for production (release) or for device. Original code is not retrievable in human-readable form.
94
+
95
+ ## Best practices
96
+
97
+ 1. Test on physical devices. The simulator/emulator is not a perfect proxy.
98
+ 2. Use Alloy for new projects for better structure and maintainability.
99
+ 3. Keep the App ID consistent. Match Bundle ID (iOS) and Package ID (Android).