@craft-native/ios 0.0.451 → 0.0.464
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/README.md +63 -0
- package/dist/cli.js +290 -81
- package/dist/index.d.ts +1 -685
- package/dist/index.js +292 -81
- package/dist/internal/ios/src/index.d.ts +684 -0
- package/dist/internal/typescript/src/native-notifications.d.ts +17 -0
- package/dist/internal/typescript/src/native-routing.d.ts +26 -0
- package/package.json +1 -1
- package/templates/CraftApp.swift +118 -16
- package/templates/CraftHybrid.swift +75 -5
- package/templates/CraftNativeActions.swift +84 -13
- package/templates/CraftNativeFiles.swift +83 -1
- package/templates/CraftNativeScreen.swift +130 -4
- package/templates/CraftNotificationService.swift +199 -0
- package/templates/CraftVoiceRecording.swift +29 -1
- package/templates/testing/DriverTests.swift.template +44 -5
- /package/dist/{app-shortcuts.d.ts → internal/ios/src/app-shortcuts.d.ts} +0 -0
- /package/dist/{runtime-profile.d.ts → internal/ios/src/runtime-profile.d.ts} +0 -0
- /package/dist/{source-audit.d.ts → internal/ios/src/source-audit.d.ts} +0 -0
- /package/dist/{testing.d.ts → internal/ios/src/testing.d.ts} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,685 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function compressNativeSources(target: string): void;
|
|
3
|
-
import { type CraftAppShortcut } from './app-shortcuts.js';
|
|
4
|
-
/** Package custom fonts and their licenses; removed fonts cannot linger in the app. */
|
|
5
|
-
export declare function syncNativeFonts(fonts: CraftConfig['nativeFonts'], output: string): string[];
|
|
6
|
-
/** This package's version, which the app names in its user agent (`Craft/<version>`). */
|
|
7
|
-
export declare function resolveCraftVersion(startDir?: string): string;
|
|
8
|
-
export type CraftAppearance = 'light' | 'dark' | 'system';
|
|
9
|
-
/** A declared command Craft runs after the native project has been generated. */
|
|
10
|
-
export interface CraftPostGenerateHook {
|
|
11
|
-
command: string;
|
|
12
|
-
args?: string[];
|
|
13
|
-
}
|
|
14
|
-
export interface CraftTabBarConfig {
|
|
15
|
-
selection?: {
|
|
16
|
-
/** The selected tab indicator's corner radius in points; omitted keeps a capsule. */
|
|
17
|
-
cornerRadius?: number;
|
|
18
|
-
/** The selected tab indicator fill as #RRGGBB. */
|
|
19
|
-
color?: string;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
export interface CraftConfig {
|
|
23
|
-
appShortcuts?: CraftAppShortcut[];
|
|
24
|
-
/** Bundled font files keyed by their PostScript font name, used as native fontFamily. */
|
|
25
|
-
nativeFonts?: Record<string, {
|
|
26
|
-
src: string;
|
|
27
|
-
license?: string;
|
|
28
|
-
}>;
|
|
29
|
-
appName: string;
|
|
30
|
-
bundleId: string;
|
|
31
|
-
/** Opt in to UIKit + JavaScriptCore instead of the default WebView. */
|
|
32
|
-
renderer?: 'web' | 'native';
|
|
33
|
-
version?: string;
|
|
34
|
-
buildNumber?: string;
|
|
35
|
-
darkMode?: boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Which interface style the app draws in. `system` follows the phone's
|
|
38
|
-
* Light/Dark setting (and the page's `prefers-color-scheme` with it); `light`
|
|
39
|
-
* and `dark` pin one. Unset keeps the older `darkMode` switch.
|
|
40
|
-
*/
|
|
41
|
-
appearance?: CraftAppearance;
|
|
42
|
-
/** Static native tab-bar styling applied before the page's own tabBar.set call. */
|
|
43
|
-
tabBar?: CraftTabBarConfig;
|
|
44
|
-
/** Runs from the generated project root after `craft ios build` writes it. */
|
|
45
|
-
postGenerate?: CraftPostGenerateHook;
|
|
46
|
-
backgroundColor?: string;
|
|
47
|
-
/** Default tint for native controls and selected tabs, as #RRGGBB. */
|
|
48
|
-
tintColor?: string;
|
|
49
|
-
/**
|
|
50
|
-
* CSS font stack for the native chrome's labels (tab bar, bar buttons); the
|
|
51
|
-
* first family packaged in `nativeFonts` wins, a generic one keeps the system face.
|
|
52
|
-
*/
|
|
53
|
-
fontFamily?: string;
|
|
54
|
-
/** CSS font stack for navigation titles; `fontFamily` when unset. */
|
|
55
|
-
headingFontFamily?: string;
|
|
56
|
-
/** The launch and webview background while the phone is in Dark Mode. */
|
|
57
|
-
backgroundColorDark?: string;
|
|
58
|
-
/** Edge-swipe back and forward through the page's history, pushState entries included. */
|
|
59
|
-
swipeNavigation?: boolean;
|
|
60
|
-
enableSpeechRecognition?: boolean;
|
|
61
|
-
enableHaptics?: boolean;
|
|
62
|
-
enableShare?: boolean;
|
|
63
|
-
enableCamera?: boolean;
|
|
64
|
-
enableBiometric?: boolean;
|
|
65
|
-
enablePushNotifications?: boolean;
|
|
66
|
-
enableSecureStorage?: boolean;
|
|
67
|
-
enableGeolocation?: boolean;
|
|
68
|
-
enableClipboard?: boolean;
|
|
69
|
-
enableContacts?: boolean;
|
|
70
|
-
enableCalendar?: boolean;
|
|
71
|
-
enableLocalNotifications?: boolean;
|
|
72
|
-
enableInAppPurchase?: boolean;
|
|
73
|
-
enableKeepAwake?: boolean;
|
|
74
|
-
enableOrientationLock?: boolean;
|
|
75
|
-
enableDeepLinks?: boolean;
|
|
76
|
-
enableQRScanner?: boolean;
|
|
77
|
-
/** Reach devices on the local network (a Mac on the same Wi-Fi); iOS asks first. */
|
|
78
|
-
enableLocalNetwork?: boolean;
|
|
79
|
-
enableFilePicker?: boolean;
|
|
80
|
-
enableFileDownload?: boolean;
|
|
81
|
-
enableSocialAuth?: boolean;
|
|
82
|
-
/** Native passkeys; requires a matching `webcredentials:` associated domain. */
|
|
83
|
-
enablePasskeys?: boolean;
|
|
84
|
-
enableAudioRecording?: boolean;
|
|
85
|
-
enableVideoRecording?: boolean;
|
|
86
|
-
enableMotionSensors?: boolean;
|
|
87
|
-
/** Core Motion relative altitude and pressure; includes the motion usage description. */
|
|
88
|
-
enableBarometer?: boolean;
|
|
89
|
-
/** Core Motion interval steps, cadence and seven-day device history. */
|
|
90
|
-
enablePedometer?: boolean;
|
|
91
|
-
/** Shaking the phone raises a `shake` event. Arms the accelerometer while the app is in front. */
|
|
92
|
-
enableShakeGesture?: boolean;
|
|
93
|
-
enableLocalDatabase?: boolean;
|
|
94
|
-
enableBluetooth?: boolean;
|
|
95
|
-
enableNFC?: boolean;
|
|
96
|
-
enableHealthKit?: boolean;
|
|
97
|
-
/** Observe declared HealthKit types on background wakes; requires enableHealthKit. */
|
|
98
|
-
enableHealthKitBackground?: boolean;
|
|
99
|
-
healthKitBackgroundTypes?: Array<'steps' | 'heartRate' | 'restingHeartRate' | 'heartRateVariability' | 'activeEnergy' | 'distance' | 'bodyMass' | 'sleep' | 'workouts'>;
|
|
100
|
-
healthKitBackgroundFrequency?: 'immediate' | 'hourly' | 'daily' | 'weekly';
|
|
101
|
-
/** Native Apple Wallet pass presentation and lookup for native screens. */
|
|
102
|
-
enableWallet?: boolean;
|
|
103
|
-
enableLiveActivities?: boolean;
|
|
104
|
-
enableWatchApp?: boolean;
|
|
105
|
-
enableBackgroundLocation?: boolean;
|
|
106
|
-
enableBackgroundTasks?: boolean;
|
|
107
|
-
enableScreenCapture?: boolean;
|
|
108
|
-
enablePDFViewer?: boolean;
|
|
109
|
-
enableAR?: boolean;
|
|
110
|
-
enableMLKit?: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* Show and control what the Music app is playing (`craft.music`, through
|
|
113
|
-
* MPMusicPlayerController.systemMusicPlayer). Only Apple Music: iOS gives
|
|
114
|
-
* no app the controls of another player such as Spotify. iOS asks the
|
|
115
|
-
* person for media library access the first time the page calls
|
|
116
|
-
* `craft.music.requestAuthorization()`, never at launch.
|
|
117
|
-
*/
|
|
118
|
-
enableAppleMusic?: boolean;
|
|
119
|
-
/**
|
|
120
|
-
* Read a Bluetooth heart-rate strap, or a watch broadcasting its heart rate
|
|
121
|
-
* (the standard Heart Rate Service), through `craft.heartRate`: scan,
|
|
122
|
-
* connect, live readings with RR intervals, and a recording kept natively.
|
|
123
|
-
* Adds the `bluetooth-central` background mode, so readings keep coming
|
|
124
|
-
* during a workout with the screen locked. iOS asks for Bluetooth the first
|
|
125
|
-
* time the page scans or connects.
|
|
126
|
-
*/
|
|
127
|
-
enableHeartRate?: boolean;
|
|
128
|
-
/**
|
|
129
|
-
* Keep playing sound with the screen locked or the app in the background:
|
|
130
|
-
* a sleep soundscape, a meditation timer's ambience. Adds the `audio`
|
|
131
|
-
* background mode. iOS keeps the app running only while it plays, and App
|
|
132
|
-
* Review expects audible content, so turn it on only for an app that plays
|
|
133
|
-
* some (Web Audio on native screens and in the web view, which use the
|
|
134
|
-
* playback session).
|
|
135
|
-
*/
|
|
136
|
-
enableBackgroundAudio?: boolean;
|
|
137
|
-
/**
|
|
138
|
-
* Schedule structured workouts onto the paired Apple Watch through
|
|
139
|
-
* `craft.scheduledWorkouts` (WorkoutKit's WorkoutScheduler, iOS 17+): each
|
|
140
|
-
* appears in the watch's Workout app on its day, with its steps, goals and
|
|
141
|
-
* alerts. Compiles CraftScheduledWorkouts.swift with the
|
|
142
|
-
* `CRAFT_SCHEDULED_WORKOUTS` condition, so an app without it never links
|
|
143
|
-
* WorkoutKit; below iOS 17 it is weak-linked and answers unsupported. iOS
|
|
144
|
-
* asks the person the first time the page calls
|
|
145
|
-
* `craft.scheduledWorkouts.requestAuthorization()`, never at launch.
|
|
146
|
-
*/
|
|
147
|
-
enableScheduledWorkouts?: boolean;
|
|
148
|
-
/**
|
|
149
|
-
* Purpose strings in the app's own words, by Info.plist key
|
|
150
|
-
* (`{ NSAppleMusicUsageDescription: 'Shows the song playing during a workout.' }`).
|
|
151
|
-
* Each replaces the generic sentence Craft writes for that key.
|
|
152
|
-
*/
|
|
153
|
-
usageDescriptions?: Record<string, string>;
|
|
154
|
-
/**
|
|
155
|
-
* The app's site. With `renderer: "web"` it is the page the web view loads.
|
|
156
|
-
* With `renderer: "native"` and `nativeScreens` there is no web view: its
|
|
157
|
-
* path is the path the app starts on (`/` when unset), and a path no native
|
|
158
|
-
* screen draws (`craft.navigation.open('/terms')`, or a link to this host)
|
|
159
|
-
* opens in the in-app browser against its origin. Native screens read it as
|
|
160
|
-
* `__stxNativeBridge.appURL`.
|
|
161
|
-
*/
|
|
162
|
-
devServerURL?: string;
|
|
163
|
-
iosVersion?: string;
|
|
164
|
-
watchosVersion?: string;
|
|
165
|
-
teamId?: string;
|
|
166
|
-
urlSchemes?: string[];
|
|
167
|
-
trustedOrigins?: string[];
|
|
168
|
-
/**
|
|
169
|
-
* The domains the app's web view treats as its own (WKAppBoundDomains, at
|
|
170
|
-
* most 10). Service workers only run in an iOS web view on these, so a site
|
|
171
|
-
* that works offline in Safari works offline in the app. Unset, they are the
|
|
172
|
-
* hosts of `trustedOrigins` and the dev server: the origins the bridge is
|
|
173
|
-
* already injected into, and once any are declared iOS keeps script
|
|
174
|
-
* injection to them. `[]` declares none.
|
|
175
|
-
*/
|
|
176
|
-
appBoundDomains?: string[];
|
|
177
|
-
/**
|
|
178
|
-
* Also refuse to load anything but the app-bound domains in the web view
|
|
179
|
-
* (WKWebViewConfiguration.limitsNavigationsToAppBoundDomains). Off by
|
|
180
|
-
* default: links elsewhere already open in Safari. WebKit applies the limit
|
|
181
|
-
* to the main frame only, so embedded players and maps in cross-origin
|
|
182
|
-
* iframes (YouTube, Vimeo) keep loading with it on (checked in the iOS 26
|
|
183
|
-
* simulator); WebKit only declines to inject user scripts into them, which
|
|
184
|
-
* the bridge never does.
|
|
185
|
-
*/
|
|
186
|
-
limitNavigationsToAppBoundDomains?: boolean;
|
|
187
|
-
/**
|
|
188
|
-
* Universal links and shared web credentials
|
|
189
|
-
* (`com.apple.developer.associated-domains`). A bare host such as
|
|
190
|
-
* `hq.training` is written as `applinks:hq.training`; an entry with its own
|
|
191
|
-
* service (`webcredentials:`, `applinks:…?mode=developer`) is kept as given.
|
|
192
|
-
* A universal link reaches the page the way a custom-scheme link does, as
|
|
193
|
-
* `craftDeepLink`.
|
|
194
|
-
*/
|
|
195
|
-
associatedDomains?: string[];
|
|
196
|
-
/**
|
|
197
|
-
* iOS's scheduled background refresh (BGAppRefreshTask). When enabled the
|
|
198
|
-
* page gets `craftBackgroundRefresh` and answers with
|
|
199
|
-
* `craft.background.complete(ok)`. The identifier defaults to
|
|
200
|
-
* `<bundleId>.refresh` and is declared in BGTaskSchedulerPermittedIdentifiers,
|
|
201
|
-
* with the `fetch` background mode.
|
|
202
|
-
*/
|
|
203
|
-
backgroundRefresh?: CraftBackgroundRefresh;
|
|
204
|
-
appGroups?: string[];
|
|
205
|
-
appIconPath?: string;
|
|
206
|
-
/**
|
|
207
|
-
* The logo the launch screen shows on `backgroundColor`, and that stays on
|
|
208
|
-
* screen until the page says it is ready (`splash.hide()`), so the app goes
|
|
209
|
-
* from launch to content without a blank web view in between. PNG, PDF or
|
|
210
|
-
* SVG, drawn at its own size in points: give an SVG the width and height it
|
|
211
|
-
* should have on screen. A PNG with `@2x` and `@3x` files beside it
|
|
212
|
-
* (`LaunchLogo.png`, `LaunchLogo@2x.png`, `LaunchLogo@3x.png`, as ts-images'
|
|
213
|
-
* `generateSplashScreens` writes them) is sharp on every screen.
|
|
214
|
-
*/
|
|
215
|
-
splashImagePath?: string;
|
|
216
|
-
/** The splash logo in Dark Mode, on `backgroundColorDark`. The light one if unset. */
|
|
217
|
-
splashImagePathDark?: string;
|
|
218
|
-
/**
|
|
219
|
-
* Whether the app uses encryption beyond the exempt kinds (HTTPS, the
|
|
220
|
-
* system's own). Written as `ITSAppUsesNonExemptEncryption`, so App Store
|
|
221
|
-
* Connect does not ask the export-compliance question on every build.
|
|
222
|
-
* Default false: a WebView app that talks HTTPS is exempt.
|
|
223
|
-
*/
|
|
224
|
-
usesNonExemptEncryption?: boolean;
|
|
225
|
-
privacy?: CraftPrivacyManifest;
|
|
226
|
-
/** Press-and-hold link previews, as in Safari. Default false. */
|
|
227
|
-
allowsLinkPreview?: boolean;
|
|
228
|
-
/**
|
|
229
|
-
* WebKit's bar above the keyboard for a form field (previous, next, Done),
|
|
230
|
-
* which no native app's keyboard has. Default false: hidden. A page can
|
|
231
|
-
* change it with `craft.chrome.setKeyboardAccessory()`.
|
|
232
|
-
*/
|
|
233
|
-
keyboardAccessory?: boolean;
|
|
234
|
-
/** Pinch and double-tap zoom off, and the page's viewport pinned at scale 1. Default true. */
|
|
235
|
-
disableZoom?: boolean;
|
|
236
|
-
/**
|
|
237
|
-
* The longest the launch splash stays up, in seconds, when the page neither
|
|
238
|
-
* hides it (`splash.hide()`) nor paints. Default 3.
|
|
239
|
-
*/
|
|
240
|
-
splashMaxSeconds?: number;
|
|
241
|
-
/**
|
|
242
|
-
* How long the app's own page may take to answer, in seconds, before the
|
|
243
|
-
* load counts as unreachable and the bundled page stands in. Default 10.
|
|
244
|
-
*/
|
|
245
|
-
requestTimeoutSeconds?: number;
|
|
246
|
-
orientations?: Array<'portrait' | 'landscape-left' | 'landscape-right' | 'portrait-upside-down'>;
|
|
247
|
-
deviceFamilies?: Array<'iphone' | 'ipad'>;
|
|
248
|
-
/**
|
|
249
|
-
* App paths drawn as native stx screens, each to the screen in the native
|
|
250
|
-
* bundle that draws it, e.g. `{ "/m": "Today", "/m/calendar": "Calendar" }`.
|
|
251
|
-
* A segment may be a parameter (`/m/workout/:id`) and the last one `*`.
|
|
252
|
-
* Needs `nativeBundle`.
|
|
253
|
-
*
|
|
254
|
-
* With `renderer: "web"` (hybrid) every other path stays in the web view,
|
|
255
|
-
* and a path whose screen is missing or throws falls back to it.
|
|
256
|
-
*
|
|
257
|
-
* With `renderer: "native"` the app is all native, with the same tabs and
|
|
258
|
-
* path routing and no web view at all: every tab id and the start path (the
|
|
259
|
-
* path of `devServerURL`) must be a native screen's, and any other path
|
|
260
|
-
* opens in the in-app browser on the app's site.
|
|
261
|
-
*/
|
|
262
|
-
nativeScreens?: Record<string, string>;
|
|
263
|
-
/**
|
|
264
|
-
* The bundle `stx native compile --format bundle` wrote, copied to
|
|
265
|
-
* `dist/native-screen.js`; or a directory of route bundles (stx's
|
|
266
|
-
* `routesDir`: `<Screen>.js` and `__app.js`), copied to
|
|
267
|
-
* `dist/native-screens/`, so each screen evaluates only its own file.
|
|
268
|
-
*/
|
|
269
|
-
nativeBundle?: string;
|
|
270
|
-
/**
|
|
271
|
-
* The bundle route of a screen-less script that runs once for the app's
|
|
272
|
-
* whole life, beside the screens (Stacks names it `__app`). It hears the
|
|
273
|
-
* app's events (`craftNotificationResponse`, `craftNotificationReceived`,
|
|
274
|
-
* `craftSilentPush`, `craftBackgroundRefresh`, `craftShortcut`,
|
|
275
|
-
* `craftSiriShortcut`) as `CRAFT_EVENT` messages instead of the page, every
|
|
276
|
-
* `APP_STATE`, and can open paths with `craft.navigation.open`. Needs
|
|
277
|
-
* `nativeScreens` or `renderer: "native"`, and the native bundle.
|
|
278
|
-
*/
|
|
279
|
-
nativeApp?: string;
|
|
280
|
-
/**
|
|
281
|
-
* Where native screens run their JavaScript. `"main"` (the default) runs it
|
|
282
|
-
* on the main thread; `"background"` gives screens a serial thread of their
|
|
283
|
-
* own, so a screen's script, its timers and its renders never hold the
|
|
284
|
-
* main thread while it scrolls or animates. UIKit still runs on main: the
|
|
285
|
-
* shell hands each render to it, and a pushed screen waits for its first
|
|
286
|
-
* render (at most 0.3 s) so it never slides in empty.
|
|
287
|
-
*/
|
|
288
|
-
nativeScriptThread?: 'main' | 'background';
|
|
289
|
-
/**
|
|
290
|
-
* The native tab bar, shown from the first frame, before the page loads.
|
|
291
|
-
* The page's own `tabBar.set` replaces it later. Each `id` is the tab's
|
|
292
|
-
* root path, as the page's tab links name it.
|
|
293
|
-
*/
|
|
294
|
-
tabs?: CraftTab[];
|
|
295
|
-
/**
|
|
296
|
-
* Hybrid: web-storage keys the page writes (localStorage or
|
|
297
|
-
* sessionStorage) that native screens need, mirrored into the Keychain
|
|
298
|
-
* under the name given, e.g. `{ "auth_token": "auth.token" }` for
|
|
299
|
-
* `craft.secureStorage.getSync('auth.token')`. Turns on secure storage.
|
|
300
|
-
*/
|
|
301
|
-
shareStorage?: Record<string, string>;
|
|
302
|
-
/**
|
|
303
|
-
* The secure-storage key the signed-in account's token lives under
|
|
304
|
-
* (default `auth.token`). `craft.session` follows it: a change of it, made
|
|
305
|
-
* by any native screen or by the page through a `shareStorage` key, is
|
|
306
|
-
* `SESSION_CHANGED { key, token, previous }` on every native screen and a
|
|
307
|
-
* `craftsession` event on the page.
|
|
308
|
-
*/
|
|
309
|
-
sessionTokenKey?: string;
|
|
310
|
-
/**
|
|
311
|
-
* Crash and error reporting to bughq (CraftCrashReporter.swift): crashes
|
|
312
|
-
* and hangs (signal handlers, NSException, MetricKit), uncaught JavaScript
|
|
313
|
-
* errors in native screens and the app script, and what the page sends
|
|
314
|
-
* through `craft.crashReporter`. Queued on disk and sent when online.
|
|
315
|
-
*/
|
|
316
|
-
crashReporting?: CraftCrashReporting;
|
|
317
|
-
}
|
|
318
|
-
export interface CraftCrashReporting {
|
|
319
|
-
/** The bughq project's public ingest key. Ships in the app; it is not a secret. */
|
|
320
|
-
key: string;
|
|
321
|
-
/** The bughq host. Default https://bughq.org. */
|
|
322
|
-
host?: string;
|
|
323
|
-
/** Default `production`. */
|
|
324
|
-
environment?: string;
|
|
325
|
-
/** The release every event names. Default `<version>+<build>`, e.g. `1.0.0+41`. */
|
|
326
|
-
release?: string;
|
|
327
|
-
/** One session per launch, for crash-free sessions per release. Default on. */
|
|
328
|
-
sessions?: boolean;
|
|
329
|
-
}
|
|
330
|
-
export interface CraftTab {
|
|
331
|
-
/** The tab's root path; comes back to the page in `craftTabSelect`. */
|
|
332
|
-
id: string;
|
|
333
|
-
title: string;
|
|
334
|
-
/** An SF Symbol name. */
|
|
335
|
-
symbol?: string;
|
|
336
|
-
/** Native selected-tab icon overrides; retained pushed screens keep their owning tab's policy. */
|
|
337
|
-
selectedSymbol?: string;
|
|
338
|
-
selectedIconTint?: string;
|
|
339
|
-
/** False suppresses the legacy pulse while selected; omission uses the legacy policy. */
|
|
340
|
-
selectedIconPulse?: boolean;
|
|
341
|
-
}
|
|
342
|
-
/** `/a//b/?q#h` → `/a/b`, the way the shell and the page compare paths. Null for a relative path. */
|
|
343
|
-
export declare function normalizeNativePath(raw: string): string | null;
|
|
344
|
-
export interface NativePathMatch {
|
|
345
|
-
path: string;
|
|
346
|
-
screen: string;
|
|
347
|
-
params: Record<string, string>;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* The native screen for a path, by the rules the shell (`CraftHybridRoutes`)
|
|
351
|
-
* and the page script apply: static segments win over `:params`, which win
|
|
352
|
-
* over a trailing `*`; query items become params under the path's own.
|
|
353
|
-
*/
|
|
354
|
-
export declare function matchNativePath(nativeScreens: Record<string, string> | undefined, raw: string): NativePathMatch | null;
|
|
355
|
-
/** Whether a config mixes native screens into its web page. */
|
|
356
|
-
export declare function isHybrid(config: Pick<CraftConfig, 'renderer' | 'nativeScreens'>): boolean;
|
|
357
|
-
/** Whether a config is an all-native app with routes: `renderer: "native"` and `nativeScreens`, tabs and paths with no web view. */
|
|
358
|
-
export declare function hasNativeRoutes(config: Pick<CraftConfig, 'renderer' | 'nativeScreens'>): boolean;
|
|
359
|
-
/** Whether a config draws any native screen, and so needs `dist/native-screen.js`. */
|
|
360
|
-
export declare function usesNativeBundle(config: Pick<CraftConfig, 'renderer' | 'nativeScreens'>): boolean;
|
|
361
|
-
/**
|
|
362
|
-
* The path the app starts on: the path of `devServerURL` (with its query),
|
|
363
|
-
* `/` when there is none. The shell reads it the same way
|
|
364
|
-
* (`CraftHybridRoutes.appPath`).
|
|
365
|
-
*/
|
|
366
|
-
export declare function nativeStartPath(config: Pick<CraftConfig, 'devServerURL'>): string;
|
|
367
|
-
/** What is wrong with a config's hybrid and tab settings, one sentence each. */
|
|
368
|
-
export declare function hybridConfigProblems(config: Pick<CraftConfig, 'renderer' | 'nativeScreens' | 'tabs' | 'shareStorage' | 'devServerURL' | 'nativeApp' | 'nativeScriptThread'>): string[];
|
|
369
|
-
/**
|
|
370
|
-
* The builder installs a directory of route bundles (stx's `routesDir`) as
|
|
371
|
-
* well as the one-file bundle, and the app runs each screen from its own
|
|
372
|
-
* route's file. Stacks asks for route bundles only when this is true.
|
|
373
|
-
*/
|
|
374
|
-
/** Build-time proof for Stacks capability mappings, including unreleased source builds. */
|
|
375
|
-
export declare const nativeSensorCapabilities: readonly ['barometer', 'pedometer', 'healthKitBackground'];
|
|
376
|
-
export declare const nativeRouteBundles = true;
|
|
377
|
-
/**
|
|
378
|
-
* The app evaluates stx's shared runtime (`__runtime.js`, stx's
|
|
379
|
-
* `sharedRuntime`) in each screen's context before the route's own file.
|
|
380
|
-
* Stacks asks stx for it only when this is true: a route file built so
|
|
381
|
-
* refuses to run without it.
|
|
382
|
-
*/
|
|
383
|
-
export declare const nativeRouteRuntime = true;
|
|
384
|
-
/**
|
|
385
|
-
* The app gives a screen its messages a language at a time (stx's
|
|
386
|
-
* `messages`, `native-screens/__messages/`): read when the screen first
|
|
387
|
-
* looks inside them (`__stxNativeReadMessages`). Stacks leaves the languages
|
|
388
|
-
* out of the screens' code only when this is true.
|
|
389
|
-
*/
|
|
390
|
-
export declare const nativeMessages = true;
|
|
391
|
-
export interface CraftBackgroundRefresh {
|
|
392
|
-
enabled: boolean;
|
|
393
|
-
/** The BGTaskScheduler identifier. Default `<bundleId>.refresh`. */
|
|
394
|
-
identifier?: string;
|
|
395
|
-
/** The soonest iOS may run it again, in minutes. Default 15. */
|
|
396
|
-
minimumIntervalMinutes?: number;
|
|
397
|
-
}
|
|
398
|
-
export interface CraftPrivacyDataType {
|
|
399
|
-
type: string;
|
|
400
|
-
linked?: boolean;
|
|
401
|
-
tracking?: boolean;
|
|
402
|
-
purposes: string[];
|
|
403
|
-
}
|
|
404
|
-
export interface CraftPrivacyAccessedApiType {
|
|
405
|
-
type: string;
|
|
406
|
-
reasons: string[];
|
|
407
|
-
}
|
|
408
|
-
export interface CraftPrivacyManifest {
|
|
409
|
-
tracking?: boolean;
|
|
410
|
-
trackingDomains?: string[];
|
|
411
|
-
collectedDataTypes?: CraftPrivacyDataType[];
|
|
412
|
-
accessedApiTypes?: CraftPrivacyAccessedApiType[];
|
|
413
|
-
}
|
|
414
|
-
export interface InitOptions {
|
|
415
|
-
name: string;
|
|
416
|
-
bundleId?: string;
|
|
417
|
-
teamId?: string;
|
|
418
|
-
output: string;
|
|
419
|
-
config?: Partial<CraftConfig>;
|
|
420
|
-
/**
|
|
421
|
-
* Where the Zig runtime archives live, overriding `CRAFT_IOS_RUNTIME`.
|
|
422
|
-
*
|
|
423
|
-
* `null` means "no runtime, whatever the environment says" — the shape
|
|
424
|
-
* `AppConfig.craftPath` has for `CRAFT_BIN`, and the reason it exists here
|
|
425
|
-
* is the same: a caller that does not opt in should not be steered by an
|
|
426
|
-
* ambient variable. Without it this package's own tests inherited whatever
|
|
427
|
-
* the developer's shell exported, and went from 12 passing to 8 passing and
|
|
428
|
-
* 4 failing when `CRAFT_IOS_RUNTIME` happened to be set.
|
|
429
|
-
*
|
|
430
|
-
* Omitted (`undefined`) keeps the environment lookup, which is what the
|
|
431
|
-
* monorepo dev loop uses.
|
|
432
|
-
*/
|
|
433
|
-
runtimeDir?: string | null;
|
|
434
|
-
/** Explicit Craft Zig source package for a per-app runtime build (or CRAFT_IOS_RUNTIME_SOURCE). */
|
|
435
|
-
runtimeSource?: string | null;
|
|
436
|
-
}
|
|
437
|
-
export interface BuildOptions {
|
|
438
|
-
htmlPath?: string;
|
|
439
|
-
/** JavaScript bundle emitted by `stx native compile Screen.stx --format bundle`. */
|
|
440
|
-
nativeBundlePath?: string;
|
|
441
|
-
devServer?: string;
|
|
442
|
-
output: string;
|
|
443
|
-
generateProject?: boolean;
|
|
444
|
-
/**
|
|
445
|
-
* Where to re-read the Zig runtime archives from, overriding
|
|
446
|
-
* `CRAFT_IOS_RUNTIME`. Same meaning as `InitOptions.runtimeDir`; `null`
|
|
447
|
-
* leaves whatever `init` installed exactly as it is.
|
|
448
|
-
*/
|
|
449
|
-
runtimeDir?: string | null;
|
|
450
|
-
/** Rebuild the installed runtime from this source using the app's current feature flags. */
|
|
451
|
-
runtimeSource?: string | null;
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Run the app's declared generator hook without invoking a shell.
|
|
455
|
-
*
|
|
456
|
-
* A hook gets the generated project as its cwd and explicit metadata so a
|
|
457
|
-
* patch can target the right platform and phase without guessing from paths.
|
|
458
|
-
*/
|
|
459
|
-
export declare function runPostGenerateHook(hook: CraftPostGenerateHook | undefined, output: string, phase?: 'build'): void;
|
|
460
|
-
export interface OpenOptions {
|
|
461
|
-
output: string;
|
|
462
|
-
}
|
|
463
|
-
export interface RunOptions {
|
|
464
|
-
simulator: boolean;
|
|
465
|
-
output: string;
|
|
466
|
-
}
|
|
467
|
-
export declare function renderDeviceFamilies(config: CraftConfig): string;
|
|
468
|
-
/** `appearance` when set, otherwise what the older `darkMode` switch pinned. */
|
|
469
|
-
export declare function resolveAppearance(config: Pick<CraftConfig, 'appearance' | 'darkMode'>): CraftAppearance;
|
|
470
|
-
/**
|
|
471
|
-
* The Info.plist interface style and the status bar that reads on it.
|
|
472
|
-
*
|
|
473
|
-
* The status bar used to be `LightContent` whatever the app looked like:
|
|
474
|
-
* white text that vanished on a light page. It now follows the appearance —
|
|
475
|
-
* dark text on a light app, light on a dark one, and the system's choice when
|
|
476
|
-
* the app follows the system.
|
|
477
|
-
*/
|
|
478
|
-
export declare function renderAppearance(config: Pick<CraftConfig, 'appearance' | 'darkMode'>): {
|
|
479
|
-
interfaceStyle: string;
|
|
480
|
-
statusBarStyle: string;
|
|
481
|
-
};
|
|
482
|
-
export declare function renderUsageDescriptions(config: CraftConfig): string;
|
|
483
|
-
export declare function renderOrientations(config: CraftConfig): string;
|
|
484
|
-
/** WKAppBoundDomains: the configured domains plus the dev server's host, at most 10. */
|
|
485
|
-
export declare function renderAppBoundDomains(config: CraftConfig): string;
|
|
486
|
-
export declare function renderUrlTypes(config: CraftConfig): string;
|
|
487
|
-
export declare function renderBackgroundModes(config: CraftConfig): string;
|
|
488
|
-
/** The background refresh task's identifier, or null when it is off. */
|
|
489
|
-
export declare function backgroundRefreshIdentifier(config: Pick<CraftConfig, 'backgroundRefresh' | 'bundleId'>): string | null;
|
|
490
|
-
/** BGTaskSchedulerPermittedIdentifiers: iOS runs no task it does not list. */
|
|
491
|
-
export declare function renderBackgroundTaskIdentifiers(config: Pick<CraftConfig, 'backgroundRefresh' | 'bundleId'>): string;
|
|
492
|
-
/**
|
|
493
|
-
* The associated-domains entitlement's entries. Each needs a service prefix,
|
|
494
|
-
* and a bare host (the easy thing to write) used to be signed as it was and
|
|
495
|
-
* then matched nothing, so universal links silently never opened the app.
|
|
496
|
-
*/
|
|
497
|
-
export declare function associatedDomainEntries(domains: string[] | undefined): string[];
|
|
498
|
-
export declare function renderEntitlements(config: CraftConfig): string;
|
|
499
|
-
export declare function renderWatchEntitlements(config: CraftConfig): string;
|
|
500
|
-
/**
|
|
501
|
-
* The build settings that link the Zig runtime into the app target.
|
|
502
|
-
*
|
|
503
|
-
* Two things are load-bearing here:
|
|
504
|
-
*
|
|
505
|
-
* `LIBRARY_SEARCH_PATHS` is written twice, once per SDK, so `-lcraft-ios`
|
|
506
|
-
* resolves to the device archive for a device build and the simulator archive
|
|
507
|
-
* for a simulator one without the flag itself changing. Xcode applies the
|
|
508
|
-
* `[sdk=...]` condition; xcodegen passes these keys through verbatim.
|
|
509
|
-
*
|
|
510
|
-
* The four `-u` flags are the reason anything works at all. Nothing in the
|
|
511
|
-
* Swift source *references* these symbols — `CraftZigRuntime` and
|
|
512
|
-
* `CraftSwiftShim` both find them with `dlsym` at runtime — so a static
|
|
513
|
-
* archive contributes no objects for them and the linker drops the entire
|
|
514
|
-
* runtime as unreachable. `-u` names them as undefined so the objects are
|
|
515
|
-
* pulled in and the symbols end up in the binary for `dlsym` to find.
|
|
516
|
-
*
|
|
517
|
-
* `-u` rather than `-force_load`: forcing the whole archive would pull in
|
|
518
|
-
* every object whether reachable or not, and these four entry points already
|
|
519
|
-
* reach everything the bridge actually uses.
|
|
520
|
-
*/
|
|
521
|
-
export declare function renderRuntimeSettings(): string;
|
|
522
|
-
/**
|
|
523
|
-
* Build settings a feature adds to the app target. WorkoutKit is compiled in
|
|
524
|
-
* only for `enableScheduledWorkouts`: CraftScheduledWorkouts.swift imports it
|
|
525
|
-
* behind the `CRAFT_SCHEDULED_WORKOUTS` condition, so an app that does not
|
|
526
|
-
* schedule workouts does not link it. `$(inherited)` keeps Debug's `DEBUG`.
|
|
527
|
-
*/
|
|
528
|
-
export declare function renderFeatureSettings(config: Partial<CraftConfig>): string;
|
|
529
|
-
export declare function renderPrivacyManifest(config: CraftConfig): string;
|
|
530
|
-
/**
|
|
531
|
-
* Whether a PNG carries an alpha channel, from its header: colour type 4
|
|
532
|
-
* (grey + alpha) or 6 (RGB + alpha), or a tRNS chunk before the image data.
|
|
533
|
-
*/
|
|
534
|
-
export declare function pngHasAlpha(bytes: Uint8Array): boolean;
|
|
535
|
-
/** The asset the launch screen and the splash both draw, so one hands over to the other unseen. */
|
|
536
|
-
export declare const LAUNCH_LOGO = "LaunchLogo";
|
|
537
|
-
/**
|
|
538
|
-
* A bitmap splash's `@2x` and `@3x` files beside it (`LaunchLogo.png`,
|
|
539
|
-
* `LaunchLogo@2x.png`, `LaunchLogo@3x.png`, as ts-images'
|
|
540
|
-
* `generateSplashScreens` writes them), by scale. A bitmap without them is
|
|
541
|
-
* one image, drawn at its pixel size in points.
|
|
542
|
-
*/
|
|
543
|
-
export declare function splashScales(source: string): Array<{
|
|
544
|
-
scale: 1 | 2 | 3;
|
|
545
|
-
path: string;
|
|
546
|
-
}>;
|
|
547
|
-
/** The launch screen: the background colour, and the splash logo on it when there is one. */
|
|
548
|
-
export declare function renderLaunchScreen(config: Pick<CraftConfig, 'splashImagePath'>): string;
|
|
549
|
-
/** Near-black or near-white, whichever reads on `background` (WCAG relative luminance). */
|
|
550
|
-
export declare function readableTextOn(background: string | undefined): string;
|
|
551
|
-
/**
|
|
552
|
-
* The page the app shows when its own page cannot be reached: the generated
|
|
553
|
-
* `dist/index.html` until the app's web assets replace it.
|
|
554
|
-
*
|
|
555
|
-
* An app whose page has a service worker normally opens from it offline, so
|
|
556
|
-
* this only shows on a first launch without one, or when the remote fails
|
|
557
|
-
* hard. It used to be a placeholder that said "Built with Craft iOS" in white
|
|
558
|
-
* on whatever the background was (invisible on a light one) with a bridge
|
|
559
|
-
* status line under it: debug output, in front of the person using the app.
|
|
560
|
-
*
|
|
561
|
-
* Now it says what happened in the app's own colours, light and dark, sized
|
|
562
|
-
* with Dynamic Type, and Retry asks the shell to load the app's page again.
|
|
563
|
-
* The shell also goes back to the app's page by itself when the connection
|
|
564
|
-
* returns, so the page does not retry on `online` as well.
|
|
565
|
-
*/
|
|
566
|
-
export declare function renderOfflinePage(config: Pick<CraftConfig, 'appName' | 'backgroundColor' | 'backgroundColorDark'>): string;
|
|
567
|
-
/** Replace the bundled web application atomically so removed assets cannot linger. */
|
|
568
|
-
export declare function syncWebAssets(source: string, output: string): void;
|
|
569
|
-
/**
|
|
570
|
-
* Initialize a new iOS project
|
|
571
|
-
*/
|
|
572
|
-
/**
|
|
573
|
-
* Where the Zig runtime archives live, or null when this build has none.
|
|
574
|
-
*
|
|
575
|
-
* `CRAFT_IOS_RUNTIME` points at a directory holding the archives `zig build
|
|
576
|
-
* build-ios-all` produces. It is opt-in and there is deliberately no fallback
|
|
577
|
-
* search: a generated project with no runtime is the shipping default today,
|
|
578
|
-
* and it works — `CraftZigRuntime.offer` is a `dlsym` miss, every action
|
|
579
|
-
* answers false, and the Swift switch serves the whole surface exactly as it
|
|
580
|
-
* always has. Guessing at a path would turn "no runtime" into "some runtime,
|
|
581
|
-
* from somewhere", which is the failure mode the pantry contract exists to
|
|
582
|
-
* rule out.
|
|
583
|
-
*
|
|
584
|
-
* This is the same shape as `CRAFT_BIN`: an explicit override for the monorepo
|
|
585
|
-
* dev loop, not a lookup path. Shipping the runtime to real apps means putting
|
|
586
|
-
* these archives in the pantry package beside the `craft` binary, which is a
|
|
587
|
-
* distribution decision this function does not make.
|
|
588
|
-
*
|
|
589
|
-
* `override` is what `InitOptions.runtimeDir` passes: a path to use instead of
|
|
590
|
-
* the variable, or `null` to declare there is no runtime regardless of what the
|
|
591
|
-
* environment says. `undefined` falls through to `CRAFT_IOS_RUNTIME`.
|
|
592
|
-
*/
|
|
593
|
-
export declare function resolveRuntimeDir(override?: string | null): string | null;
|
|
594
|
-
/**
|
|
595
|
-
* Copy the Zig archives into the generated project as `Runtime/<sdk>/libcraft-ios.a`.
|
|
596
|
-
*
|
|
597
|
-
* One name for both SDKs, in two directories, because that is what lets a
|
|
598
|
-
* single `-lcraft-ios` in OTHER_LDFLAGS work for device and simulator builds:
|
|
599
|
-
* Xcode picks the directory by SDK and the flag never changes.
|
|
600
|
-
*
|
|
601
|
-
* Returns true when a runtime was installed.
|
|
602
|
-
*/
|
|
603
|
-
export declare function installRuntime(output: string, runtimeDir: string, config?: CraftConfig): Promise<boolean>;
|
|
604
|
-
/**
|
|
605
|
-
* The identifier an app's display name becomes wherever Xcode or Swift needs
|
|
606
|
-
* one: the project, the target, the product and the `@main` type.
|
|
607
|
-
*
|
|
608
|
-
* The display name goes in front of people and may say anything; an
|
|
609
|
-
* identifier may not. "HQ.training" used to become `struct HQ.trainingApp`,
|
|
610
|
-
* which does not compile. Words are joined in PascalCase ("HQTraining"), and
|
|
611
|
-
* a name that starts with a digit or has no letters at all still yields a
|
|
612
|
-
* valid Swift type.
|
|
613
|
-
*/
|
|
614
|
-
export declare function productName(name: string): string;
|
|
615
|
-
/** Restore package-owned Swift, retaining Xcode metadata and bundled screens.
|
|
616
|
-
* Xcode Cloud assigns the distributed build number independently of the source
|
|
617
|
-
* config; keep the packaged runtime identity in step with Apple's build.
|
|
618
|
-
*/
|
|
619
|
-
export declare function restoreShell(output: string): void;
|
|
620
|
-
export { assertNoApplicationSwiftSources, findApplicationSwiftSources } from './source-audit.js';
|
|
621
|
-
export declare function init(options: InitOptions): Promise<void>;
|
|
622
|
-
/**
|
|
623
|
-
* Build web assets and generate Xcode project
|
|
624
|
-
*/
|
|
625
|
-
export declare function build(options: BuildOptions): Promise<void>;
|
|
626
|
-
/**
|
|
627
|
-
* Open Xcode project
|
|
628
|
-
*/
|
|
629
|
-
export declare function open(options: OpenOptions): Promise<void>;
|
|
630
|
-
/**
|
|
631
|
-
* Build and run on simulator or device
|
|
632
|
-
*/
|
|
633
|
-
/** One bootable simulator, as `simctl list` describes it. */
|
|
634
|
-
export interface SimulatorDevice {
|
|
635
|
-
name: string;
|
|
636
|
-
udid: string;
|
|
637
|
-
state: string;
|
|
638
|
-
runtime: string;
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* Every available *iOS* simulator, newest runtime first, iPhones before iPads.
|
|
642
|
-
*
|
|
643
|
-
* Exported because the choice is worth testing without a simulator present -
|
|
644
|
-
* `pickSimulator` is the policy and this is the data it reads.
|
|
645
|
-
*/
|
|
646
|
-
export declare function orderSimulators(devices: SimulatorDevice[], sdkVersion?: string): SimulatorDevice[];
|
|
647
|
-
/**
|
|
648
|
-
* The device to run on.
|
|
649
|
-
*
|
|
650
|
-
* A booted one first - if the developer already has a simulator open, that is
|
|
651
|
-
* the one they are looking at - then the newest iPhone.
|
|
652
|
-
*
|
|
653
|
-
* This used to be the string `iPhone 15`, hard-coded into the `-destination`
|
|
654
|
-
* argument. On a machine whose Xcode ships iPhone 17 and no iPhone 15, that is
|
|
655
|
-
* not a fallback, it is `xcodebuild: error: Unable to find a device named
|
|
656
|
-
* 'iPhone 15'` - the command fails for a reason that has nothing to do with the
|
|
657
|
-
* app being built, and the fix is invisible from the error.
|
|
658
|
-
*/
|
|
659
|
-
export declare function pickSimulator(): Promise<SimulatorDevice | null>;
|
|
660
|
-
/**
|
|
661
|
-
* Boot it, and wait until it can actually do something.
|
|
662
|
-
*
|
|
663
|
-
* `simctl boot` returns as soon as the device starts booting, and a device
|
|
664
|
-
* that reports `Booted` is minutes away from being able to install anything on
|
|
665
|
-
* a cold runtime. `bootstatus` is the wait, and skipping it is why a first run
|
|
666
|
-
* on a fresh machine fails where the second succeeds.
|
|
667
|
-
*/
|
|
668
|
-
export declare function bootSimulator(device: SimulatorDevice): Promise<void>;
|
|
669
|
-
/**
|
|
670
|
-
* Bring the Simulator window to the front, if it can be found.
|
|
671
|
-
*
|
|
672
|
-
* `open -a Simulator` resolves through LaunchServices, and LaunchServices only
|
|
673
|
-
* knows the name if a Simulator.app has been registered under it - which is not
|
|
674
|
-
* true on a machine running Xcode-beta, where the answer is `Unable to find
|
|
675
|
-
* application named 'Simulator'`. The app is always at a known path under the
|
|
676
|
-
* *selected* developer directory, so that is tried first.
|
|
677
|
-
*
|
|
678
|
-
* Never throws. The window is a convenience: the app is installed and launched
|
|
679
|
-
* either way, and failing the whole run because a window did not come to the
|
|
680
|
-
* front would be reporting a cosmetic problem as a build failure.
|
|
681
|
-
*/
|
|
682
|
-
export declare function showSimulator(): Promise<void>;
|
|
683
|
-
export declare function run(options: RunOptions): Promise<void>;
|
|
684
|
-
export { createNativeMutationValidator, initSimulatorDriver, serializeSimulatorSteps } from './testing.js';
|
|
685
|
-
export type { NativeMutationValidator, NativeValidationResult, SimulatorDriverOptions, SimulatorStep, TimedTouchPoint } from './testing.js';
|
|
1
|
+
export * from './internal/ios/src/index.js'
|