@maccesar/titools 2.2.10 → 2.2.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maccesar/titools",
3
- "version": "2.2.10",
3
+ "version": "2.2.12",
4
4
  "description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -31,78 +31,46 @@ Behavior:
31
31
 
32
32
  ## Workflow
33
33
 
34
- 1. Architecture: define structure (`lib/api`, `lib/services`, `lib/helpers`)
34
+ 1. Architecture: define structure by technical type with flat folders (`lib/api`, `lib/services`, `lib/actions`, `lib/repositories`, `lib/helpers`)
35
35
  2. Data strategy: choose Models (SQLite) or Collections (API)
36
36
  3. Contracts: define I/O specs between layers
37
37
  4. Implementation: write XML views and ES6+ controllers
38
38
  5. Quality: testing, error handling, logging, performance
39
39
  6. Cleanup: implement a `cleanup()` pattern for memory management
40
40
 
41
- ## Quick start example
42
-
43
- Minimal example that matches the conventions:
44
-
45
- View (`views/user/card.xml`)
46
- ```xml
47
- <Alloy>
48
- <View id="cardContainer">
49
- <View id="headerRow">
50
- <ImageView id="userIcon" image="/images/user.png" />
51
- <Label id="name" />
52
- </View>
53
- <Button id="viewProfileBtn"
54
- title="L('view_profile')"
55
- onClick="onViewProfile"
56
- />
57
- </View>
58
- </Alloy>
59
- ```
41
+ ## Architectural Maturity Tiers
60
42
 
61
- Styles (`styles/user/card.tss`)
62
- ```tss
63
- "#cardContainer": { left: 8, right: 8, top: 8, height: Ti.UI.SIZE, borderRadius: 12, backgroundColor: '#fff' }
64
- "#headerRow": { layout: 'horizontal', left: 12, right: 12, top: 12, height: Ti.UI.SIZE, width: Ti.UI.FILL }
65
- "#userIcon": { width: 32, height: 32 }
66
- "#name": { left: 12, font: { fontSize: 18, fontWeight: 'bold' } }
67
- "#viewProfileBtn": { left: 12, right: 12, bottom: 12, height: 40, width: Ti.UI.FILL, borderRadius: 6, backgroundColor: '#2563eb', color: '#fff' }
68
- ```
43
+ Choose the appropriate tier based on project complexity:
69
44
 
70
- Controller (`controllers/user/card.js`)
71
- ```javascript
72
- const { Navigation } = require('services/navigation')
73
-
74
- function init() {
75
- const user = $.args.user
76
- $.name.text = user.name
77
- }
45
+ ### Tier 1: Basic (Rapid Prototyping)
46
+ - **Best for**: Simple utility apps or developers transitioning from Classic.
47
+ - **Structure**: Logic resides directly within `index.js`.
48
+ - **UI Access**: Direct usage of the `$` object throughout the file.
49
+ - **Pros**: Zero boilerplate, extremely fast start.
50
+ - **Cons**: Unmaintainable beyond 500 lines of code.
78
51
 
79
- function onViewProfile() {
80
- Navigation.open('user/profile', { userId: $.args.user.id })
81
- }
52
+ ### Tier 2: Intermediate (Modular Alloy)
53
+ - **Best for**: Standard commercial applications.
54
+ - **Structure**: Business logic extracted to `app/lib/` using a flat technical-type organization.
55
+ - **Pattern**: Slim Controllers that `require()` services.
56
+ - **Memory**: Mandatory implementation of `$.cleanup = cleanup`.
82
57
 
83
- function cleanup() {
84
- $.destroy()
85
- }
58
+ ### Tier 3: Advanced / Enterprise (Service-Oriented)
59
+ - **Best for**: High-complexity apps (IDEs like TiDesigner, multi-state platforms).
60
+ - **Architecture**: Dependency Injection via a `ServiceRegistry`.
61
+ - **ID Scoping**: Services do not receive the entire `$` object. They receive a "Scoped UI" object containing only relevant IDs.
62
+ - **Cognitive Load**: "Black Box" logic—encapsulated units that reduce mental fatigue.
63
+ - **Observability**: Structured logging with a mandatory `service` context.
86
64
 
87
- $.cleanup = cleanup
88
- ```
65
+ Detailed examples and full implementation samples are available in: [Architectural Tiers Detail](references/architecture-tiers.md)
89
66
 
90
- Service (`lib/services/navigation.js`)
91
- ```javascript
92
- exports.Navigation = {
93
- open(route, params = {}) {
94
- const controller = Alloy.createController(route, params)
95
- const view = controller.getView()
67
+ ## Organization policy (low freedom)
96
68
 
97
- view.addEventListener('close', function() {
98
- if (controller.cleanup) controller.cleanup()
99
- })
69
+ - Use technical-type organization in `lib` (for example: `api`, `services`, `actions`, `repositories`, `helpers`, `policies`, `providers`).
70
+ - Keep `lib` flat and predictable: `lib/<type>/<file>.js` only.
71
+ - Do not recommend deep nesting like `lib/services/auth/session/login.js`.
72
+ - Keep UI layers aligned by screen (`controllers/`, `views/`, `styles/`) and avoid unnecessary depth.
100
73
 
101
- view.open()
102
- return controller
103
- }
104
- }
105
- ```
106
74
 
107
75
  ## Code standards (low freedom)
108
76
 
@@ -159,40 +127,47 @@ For the complete reference with examples, see [Alloy builtins and globals](refer
159
127
 
160
128
  | Question | Answer |
161
129
  | ---------------------------------- | -------------------------------------------------------------- |
162
- | How to create a new Alloy project? | `ti create -t app --alloy` (not `--classic` + `alloy new`) |
130
+ | How to create a new Alloy project? | `ti create -t app --alloy` (not `--classic` + `alloy new`) |
163
131
  | Fastest way to build? | `tn <recipe>` (using TiNy CLI wrapper) |
132
+ | Controller > 100 lines? | Extract to Tier 2 (Services) |
133
+ | More than 50 IDs in XML? | Use Tier 3 (ID Scoping) |
164
134
  | Where does API call go? | `lib/api/` |
165
135
  | Where does business logic go? | `lib/services/` |
136
+ | How deep should `lib` folders be? | One level: `lib/<type>/<file>.js` |
166
137
  | Where do I store auth tokens? | Keychain (iOS) / KeyStore (Android) via service |
167
138
  | Models or Collections? | Collections for API data, Models for SQLite persistence |
168
139
  | Ti.App.fireEvent or EventBus? | Always EventBus (Backbone.Events) |
169
140
  | Direct navigation or service? | Always Navigation service (auto cleanup) |
170
- | Inline styles or TSS files? | Always TSS files (per-controller + `app.tss` for global) |
171
- | Controller 100+ lines? | Extract logic to services |
141
+ | Inline styles or TSS files? | Always TSS files (per-controller + `app.tss` for global) |
172
142
 
173
143
  ## Reference guides (progressive disclosure)
174
144
 
175
- Architecture
176
- - [CLI expert and TiNy](references/cli-expert.md): advanced build workflows, LiveView, TiNy (`tn`) recipes
177
- - [Structure and organization](references/alloy-structure.md): models vs collections, folder maps, widget patterns, automatic cleanup
178
- - [Alloy builtins and globals](references/alloy-builtins.md): `OS_IOS`/`OS_ANDROID`, `Alloy.CFG`, `Alloy.Globals`, `$.args`, compiler directives
179
- - [ControllerAutoCleanup.js](assets/ControllerAutoCleanup.js): drop-in utility for automatic controller cleanup
180
- - [Architectural patterns](references/patterns.md): repository, service layer, event bus, factory, singleton
181
- - [Contracts and communication](references/contracts.md): layer interaction examples and JSDoc specs
182
- - [Anti-patterns](references/anti-patterns.md): fat controllers, memory leaks, inline styling, direct API calls
183
-
184
- Implementation
185
- - [Code conventions](references/code-conventions.md): ES6 features, TSS design system, accessibility
186
- - [Theming and dark mode](references/theming.md): theme system, Alloy.Globals palette, runtime switching, design tokens
187
- - [Controller patterns](references/controller-patterns.md): templates, animation, dynamic styling
188
- - [Examples](references/examples.md): API clients, SQL models, full screen examples
189
-
190
- Quality and reliability
191
- - [Unit and integration testing](references/testing-unit.md): unit testing, mocking patterns, controller testing, test helpers
192
- - [E2E testing and CI/CD](references/testing-e2e-ci.md): Appium, WebdriverIO, GitHub Actions, Fastlane
193
- - [Error handling and logging](references/error-handling.md): AppError classes, Logger service, validation
194
-
195
- Performance and security
196
- - [ListView and ScrollView performance](references/performance-listview.md): ListView templates, data binding, image caching, ScrollView optimization
197
- - [Performance optimization](references/performance-optimization.md): bridge crossings, memory management, animations, debounce/throttle, database
198
- - [Security fundamentals](references/security-fundamentals.md): token storage, certificate pinning, encryption, HTTPS, OWASP
145
+ ### Architecture & Patterns
146
+ - [Architectural Tiers Detail](references/architecture-tiers.md)
147
+ - [Architectural Patterns](references/patterns.md) (Factory, Singleton, Repository)
148
+ - [Structure & Organization](references/alloy-structure.md)
149
+ - [Contracts & Communication](references/contracts.md)
150
+ - [State Management](references/state-management.md)
151
+ - [Anti-patterns to Avoid](references/anti-patterns.md)
152
+
153
+ ### Implementation & API
154
+ - [Alloy Builtins & Globals](references/alloy-builtins.md)
155
+ - [Code Conventions](references/code-conventions.md)
156
+ - [Controller Patterns](references/controller-patterns.md)
157
+ - [Theming & Dark Mode](references/theming.md)
158
+ - [Migration Patterns](references/migration-patterns.md)
159
+ - [Examples Collection](references/examples.md)
160
+
161
+ ### Quality & Performance
162
+ - [Performance Optimization](references/performance-optimization.md)
163
+ - [ListView & ScrollView Performance](references/performance-listview.md)
164
+ - [Error Handling & Logging](references/error-handling.md)
165
+ - [Unit & Integration Testing](references/testing-unit.md)
166
+ - [E2E Testing & CI/CD](references/testing-e2e-ci.md)
167
+
168
+ ### Security
169
+ - [Security Fundamentals](references/security-fundamentals.md)
170
+ - [Device Security](references/security-device.md)
171
+
172
+ ### Tools
173
+ - [CLI Expert & TiNy](references/cli-expert.md)
@@ -4,52 +4,81 @@
4
4
 
5
5
  ```
6
6
  app/
7
- ├── controllers/ # View orchestrators
7
+ ├── controllers/ # View orchestrators
8
8
  │ ├── index.js # Bootstrap only (no business logic)
9
- └── feature/
10
- └── list.js # Controller for list view
9
+ ├── home.js
10
+ └── userProfile.js
11
11
  ├── models/ # OPTIONAL: For persistence with migrations
12
12
  │ └── user.js # Model definition (ONLY if using SQLite)
13
13
  ├── views/ # XML views
14
14
  │ ├── index.xml
15
- └── feature/
16
- └── list.xml # View definition
15
+ ├── home.xml
16
+ └── userProfile.xml
17
17
  ├── styles/ # TSS styles (one per view + global)
18
18
  │ ├── app.tss # Global application styles
19
19
  │ ├── index.tss # Styles for index view
20
- └── feature/
21
- └── list.tss # Styles for feature/list view
20
+ ├── home.tss
21
+ └── userProfile.tss
22
22
  ├── lib/ # Reusable logic (no UI)
23
23
  │ ├── api/
24
- │ │ └── client.js # API calls
24
+ │ │ ├── authApi.js
25
+ │ │ ├── userApi.js
26
+ │ │ └── frameApi.js
25
27
  │ ├── services/
26
- │ │ ├── auth.js # Business logic services
27
- │ │ ├── navigation.js # Navigation orchestration
28
- │ │ └── nativeService.js # Native module wrapper (e.g. Audio, FB, Maps)
29
- └── helpers/
30
- ├── utils.js # Pure utility functions
31
- └── i18n.js # Complex string transformations
28
+ │ │ ├── authService.js
29
+ │ │ ├── navigationService.js
30
+ │ │ └── notificationService.js
31
+ ├── actions/
32
+ ├── syncUserAction.js
33
+ └── refreshSessionAction.js
34
+ │ ├── repositories/
35
+ │ │ ├── userRepository.js
36
+ │ │ └── settingsRepository.js
37
+ │ ├── helpers/
38
+ │ │ ├── validator.js
39
+ │ │ ├── formatter.js
40
+ │ │ └── dateHelper.js
41
+ │ ├── policies/
42
+ │ │ ├── permissionPolicy.js
43
+ │ │ └── featurePolicy.js
44
+ │ └── providers/
45
+ │ ├── containerProvider.js
46
+ │ └── loggerProvider.js
32
47
  ├── widgets/ # Truly reusable components (used in 3+ places)
33
48
  │ └── customButton/
34
49
  ├── config.json # Alloy configuration
35
50
  └── alloy.js # Collections & Global services
36
51
  ```
37
52
 
53
+ ## Organization strategy
54
+
55
+ - `lib/` uses technical-type grouping (Laravel-style naming adapted to Titanium).
56
+ - UI stays in Alloy MVC folders (`controllers`, `views`, `styles`).
57
+ - This is a hybrid approach: technical grouping for reusable logic + screen-based organization for UI files.
58
+ - Keep folder depth low to preserve discoverability.
59
+ - Use clear composed names (`authService.js`, `userRepository.js`, `authApi.js`) and keep multiple files per folder as the normal case.
60
+
61
+ ### Folder depth policy (critical)
62
+
63
+ - Allowed in `lib`: `lib/<type>/<file>.js`
64
+ - Avoid in `lib`: `lib/<type>/<domain>/<subdomain>/<file>.js`
65
+ - If a folder grows too much, split by new technical type, not deep tree nesting.
66
+
38
67
  ## lib/ folder and module require paths
39
68
 
40
69
  :::danger CRITICAL: lib/ Folder is FLATTENED During Build
41
70
  When Alloy compiles, the **entire `lib/` folder is flattened to the root of Resources**. This means:
42
- - `app/lib/services/picsum.js` → `Resources/iphone/services/picsum.js`
43
- - `app/lib/api/client.js` → `Resources/iphone/api/client.js`
71
+ - `app/lib/services/authService.js` → `Resources/iphone/services/authService.js`
72
+ - `app/lib/api/authApi.js` → `Resources/iphone/api/authApi.js`
44
73
 
45
74
  **Therefore, require statements should NOT include `lib/` prefix:**
46
75
  ```javascript
47
76
  // ❌ WRONG - Will fail at runtime
48
- const client = require('lib/api/client')
77
+ const authApi = require('lib/api/authApi')
49
78
 
50
79
  // ✅ CORRECT - Path relative to flattened lib/
51
- const client = require('api/client')
52
- const picsum = require('services/picsum')
80
+ const authApi = require('api/authApi')
81
+ const authService = require('services/authService')
53
82
  ```
54
83
 
55
84
  **This applies to:**
@@ -62,13 +91,18 @@ const picsum = require('services/picsum')
62
91
  app/
63
92
  ├── lib/
64
93
  │ ├── services/
65
- │ │ ├── picsum.js # require('services/logger')
66
- │ │ ├── navigation.js # require('services/logger')
67
- │ │ └── logger.js
68
- └── api/
69
- └── client.js # require('services/logger')
94
+ │ │ ├── authService.js # require('services/navigationService')
95
+ │ │ ├── navigationService.js # require('services/notificationService')
96
+ │ │ └── notificationService.js
97
+ ├── api/
98
+ │ ├── authApi.js # require('services/authService')
99
+ │ │ ├── userApi.js
100
+ │ │ └── frameApi.js
101
+ │ └── repositories/
102
+ │ ├── userRepository.js
103
+ │ └── settingsRepository.js
70
104
  ├── controllers/
71
- │ └── index.js # require('services/picsum')
105
+ │ └── index.js # require('services/authService')
72
106
  ```
73
107
  :::
74
108
 
@@ -145,6 +179,7 @@ api.getFrames()
145
179
  - Handle UI events and delegate to services.
146
180
  - Format data for display (simple cases).
147
181
  - Manage view lifecycle (including cleanup).
182
+ - Keep `lib` modules flat and easy to locate.
148
183
 
149
184
  **DON'T:**
150
185
  - Use inline style attributes in XML (define in TSS files).
@@ -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
+ ---
@@ -198,3 +198,176 @@ Installation method:
198
198
  2. Open Xcode, then Window, then Devices.
199
199
  3. Select the device, then Installed Apps, then +.
200
200
  4. Select the IPA file.
201
+
202
+ ---
203
+
204
+ ## Mac Catalyst distribution (Mac App Store)
205
+
206
+ Mac Catalyst allows you to run your iPad app on macOS. Titanium SDK 13.1.1.GA and later supports building for Mac Catalyst.
207
+
208
+ ### 1. Enable Mac Catalyst for your App ID
209
+
210
+ 1. Go to [Apple Developer → Identifiers](https://developer.apple.com/account/resources/identifiers/list)
211
+ 2. Select your App ID or create a new one
212
+ 3. Enable **Mac Catalyst** capability
213
+ 4. Save the changes
214
+
215
+ ### 2. Create Mac App Store Distribution Certificate
216
+
217
+ 1. Go to [Apple Developer → Certificates](https://developer.apple.com/account/resources/certificates/list)
218
+ 2. Click **+** to create a new certificate
219
+ 3. Select **Mac App Store Distribution**
220
+ 4. Upload your CSR (Certificate Signing Request)
221
+ 5. Download and install the certificate
222
+
223
+ ### 3. Mac Catalyst build targets
224
+
225
+ Titanium provides two targets for Mac Catalyst:
226
+
227
+ | Target | Description | Configuration |
228
+ |--------|-------------|---------------|
229
+ | `macos` | Development builds for testing on Mac | Debug-maccatalyst |
230
+ | `dist-macappstore` | Production builds for Mac App Store | Release-maccatalyst |
231
+
232
+ ### 4. Build for Mac Catalyst (Development)
233
+
234
+ ```bash
235
+ ti build -p ios -T macos
236
+ ```
237
+
238
+ The `.app` bundle will be created at:
239
+ ```
240
+ build/iphone/build/Products/Debug-maccatalyst/AppName.app
241
+ ```
242
+
243
+ For a production-ready build:
244
+ ```bash
245
+ ti build -p ios -T macos --deploy-type production
246
+ ```
247
+
248
+ The `.app` bundle will be at:
249
+ ```
250
+ build/iphone/build/Products/Release-maccatalyst/AppName.app
251
+ ```
252
+
253
+ ### 5. Build for Mac App Store (Distribution)
254
+
255
+ ```bash
256
+ ti build -p ios -T dist-macappstore [-R <CERTIFICATE_NAME>]
257
+ ```
258
+
259
+ Example:
260
+ ```bash
261
+ ti build -p ios -T dist-macappstore -R "Apple Distribution: Your Team Name (TEAM_ID)"
262
+ ```
263
+
264
+ If you omit the `-R` flag, Titanium will prompt you to select a certificate.
265
+
266
+ **What happens during the build:**
267
+ - Uses `Release-maccatalyst` configuration
268
+ - Sets code signing to Manual with identity `-`
269
+ - Creates a `.xcarchive` for Mac App Store
270
+ - Installs the archive in Xcode's Organizer
271
+ - Destination: `generic/platform=macOS`
272
+
273
+ ### 6. Upload to Mac App Store Connect
274
+
275
+ 1. Open Xcode → Window → Organizer
276
+ 2. Select your Mac Catalyst archive
277
+ 3. Click **Validate App** to check for issues
278
+ 4. Click **Distribute App**
279
+ 5. Select **Mac App Store**
280
+ 6. Follow the prompts to upload
281
+
282
+ ### 7. Create app listing in App Store Connect
283
+
284
+ 1. Go to [App Store Connect](https://appstoreconnect.apple.com)
285
+ 2. **My Apps → + → New App**
286
+ 3. Select **Mac** as platform
287
+ 4. Enter app details:
288
+ - Name
289
+ - Primary Language
290
+ - Bundle ID (must match your App ID with Mac Catalyst enabled)
291
+ - SKU
292
+ 5. Complete required metadata:
293
+ - Description
294
+ - Keywords
295
+ - Screenshots (Mac-specific sizes)
296
+ - Category
297
+ - Age rating
298
+
299
+ ### 8. Mac Catalyst entitlements
300
+
301
+ Add Mac-specific entitlements in `tiapp.xml`:
302
+
303
+ ```xml
304
+ <ios>
305
+ <entitlements>
306
+ <dict>
307
+ <!-- File access for saving to Downloads -->
308
+ <key>com.apple.security.files.user-selected.read-write</key>
309
+ <true/>
310
+ <key>com.apple.security.files.downloads.read-write</key>
311
+ <true/>
312
+
313
+ <!-- App sandbox (required for Mac App Store) -->
314
+ <key>com.apple.security.app-sandbox</key>
315
+ <true/>
316
+
317
+ <!-- Network access -->
318
+ <key>com.apple.security.network.client</key>
319
+ <true/>
320
+
321
+ <!-- Additional entitlements as needed -->
322
+ <key>com.apple.security.print</key>
323
+ <true/>
324
+ </dict>
325
+ </entitlements>
326
+ </ios>
327
+ ```
328
+
329
+ ### 9. Common issues
330
+
331
+ **Issue**: "No suitable signing certificate found"
332
+ - Ensure you have a **Mac App Store Distribution Certificate** (not iOS Distribution)
333
+ - The certificate must be installed in your Keychain
334
+
335
+ **Issue**: Build fails with code signing errors
336
+ - Verify your App ID has Mac Catalyst enabled
337
+ - Check that the certificate matches the App ID
338
+ - Try cleaning the build: `ti clean -p ios`
339
+
340
+ **Issue**: App crashes on launch
341
+ - Verify entitlements are correctly configured
342
+ - Check Console.app for crash logs
343
+ - Ensure all required capabilities are enabled
344
+
345
+ ### 10. Versioning
346
+
347
+ Update version numbers in `tiapp.xml`:
348
+
349
+ ```xml
350
+ <ti:app xmlns:ti="http://ti.tidev.io">
351
+ <id>com.yourcompany.yourapp</id>
352
+ <name>Your App Name</name>
353
+ <version>1.0.0</version>
354
+ <publisher>Your Company</publisher>
355
+ ...
356
+ </ti:app>
357
+ ```
358
+
359
+ - `version`: Display version (e.g., "1.0.0")
360
+ - For iOS, use `pv-version-code` in `<ios>` section for build number
361
+ - For Mac, the build number can be set in Xcode or via `CFBundleVersion`
362
+
363
+ ### 11. Testing on Mac
364
+
365
+ Before submitting to Mac App Store:
366
+
367
+ 1. Build with `macos` target for testing
368
+ 2. Run the app on different Mac architectures (Intel and Apple Silicon)
369
+ 3. Test all features that use file system, network, and other sandboxed resources
370
+ 4. Verify entitlements are working correctly
371
+ 5. Test on macOS versions you plan to support
372
+
373
+ ---
@@ -258,7 +258,7 @@ Omit `-V` and `-P` to be prompted.
258
258
  | `-P, --pp-uuid <uuid>` | Provisioning profile UUID (for device/dist targets). |
259
259
  | `-R, --distribution-name <name>` | iOS Distribution Certificate (for dist targets). |
260
260
  | `--sim-focus` | Focus the iOS Simulator after launching (default: true). Use --no-sim-focus to disable. |
261
- | `-T, --target <value>` | Target: simulator, device, dist-appstore, or dist-adhoc. |
261
+ | `-T, --target <value>` | Target: simulator, device, dist-appstore, dist-adhoc, macos, or dist-macappstore. |
262
262
  | `-V, --developer-name <name>` | iOS Developer Certificate (required for device target). |
263
263
  | `-W, --watch-device-id <udid>` | Watch simulator UDID (simulator only). |
264
264
  | `--watch-app-name <name>` | Name of the watch app to launch (simulator only). |
@@ -394,6 +394,48 @@ ti build -p ios -T dist-appstore -R "Pseudo, Inc." -P "AAAAAAAA-0000-9999-8888-7
394
394
 
395
395
  Installs the package to Xcode Organizer.
396
396
 
397
+ ### Mac Catalyst (macOS Development)
398
+
399
+ ```bash
400
+ ti build -p ios -T macos
401
+ ```
402
+
403
+ Builds a Mac Catalyst version of your iOS app for local testing. The resulting `.app` bundle is located at:
404
+ ```
405
+ build/iphone/build/Products/Debug-maccatalyst/AppName.app
406
+ ```
407
+
408
+ For a production build:
409
+ ```bash
410
+ ti build -p ios -T macos --deploy-type production
411
+ ```
412
+
413
+ The release `.app` bundle will be at:
414
+ ```
415
+ build/iphone/build/Products/Release-maccatalyst/AppName.app
416
+ ```
417
+
418
+ ### Mac App Store (Mac Catalyst Distribution)
419
+
420
+ ```bash
421
+ ti build -p ios -T dist-macappstore [-R <CERT_NAME>]
422
+ ```
423
+
424
+ Example:
425
+ ```bash
426
+ ti build -p ios -T dist-macappstore -R "Apple Distribution: Your Name (TEAM_ID)"
427
+ ```
428
+
429
+ **Important Notes:**
430
+ - Requires a Mac App Store Distribution Certificate (not iOS Distribution)
431
+ - The build creates an archive for Mac App Store distribution
432
+ - The `.xcarchive` is installed in Xcode's Organizer
433
+ - Uses `Release-maccatalyst` configuration
434
+ - Destination: `generic/platform=macOS`
435
+ - Code signing is set to Manual with identity `-`
436
+
437
+ The target `dist-macappstore` is available in Titanium SDK 13.1.1.GA and later.
438
+
397
439
  ---
398
440
 
399
441
  ## SDK management