@craft-native/android 0.0.436 → 0.0.442

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/dist/index.js.map CHANGED
@@ -2,13 +2,13 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/native-map.ts", "../src/promise-runtime.ts", "../src/testing.ts", "../src/emulator.ts"],
4
4
  "sourcesContent": [
5
- "import { gzipSync } from 'node:zlib'\n/**\n * Craft Android Builder\n *\n * Generates Android apps with native Craft components and optional WebView content.\n */\n\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs'\n\n/** Store large native source assets compressed; the host decodes each once on demand. */\nexport function compressNativeSources(target: string): void {\n if (statSync(target).isDirectory()) {\n for (const entry of readdirSync(target)) compressNativeSources(join(target, entry))\n return\n }\n if (!/\\.(?:js|json)$/.test(target)) return\n const bytes = readFileSync(target)\n if (bytes.length < 1024 || (bytes[0] === 0x1f && bytes[1] === 0x8b)) return\n const packed = gzipSync(bytes, { level: 9 })\n if (packed.length < bytes.length) writeFileSync(target, packed)\n}\nimport { dirname, extname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport { $ } from 'bun'\nimport { androidMapHost, type AndroidMapProvider } from './native-map.js'\nimport { renderAndroidPromiseRuntime } from './promise-runtime'\n\nexport type { AndroidMapProvider } from './native-map.js'\n/**\n * The builder installs a directory of route bundles (stx's `routesDir`) as\n * well as the one-file bundle, and the app runs each screen from its own\n * route's file. Stacks asks for route bundles only when this is true.\n */\nexport const nativeRouteBundles = true\n\n/**\n * The app evaluates stx's shared runtime (`__runtime.js`, stx's\n * `sharedRuntime`) in each screen's context before the route's own file.\n * Stacks asks stx for it only when this is true: a route file built so\n * refuses to run without it.\n */\nexport const nativeRouteRuntime = true\n\n/**\n * The app gives a screen its messages a language at a time (stx's\n * `messages`, `native-screens/__messages/`): the areas its route uses,\n * evaluated ahead of it (an isolate cannot read a file when asked). Stacks leaves the languages\n * out of the screens' code only when this is true.\n */\nexport const nativeMessages = true\n\n/** Providers this published builder can generate as real Android map views. */\nexport const nativeMapProviders = ['google', 'maplibre'] as const\nexport { runKotlinFixture } from './testing.js'\nexport { createAndroidEmulator } from './emulator.js'\nexport type { AndroidEmulatorOptions, AndroidEmulatorSession } from './emulator.js'\n\n/** Package custom fonts and their licenses; removed fonts cannot linger in the app. */\nexport function syncNativeFonts(fonts: CraftAndroidConfig['nativeFonts'], output: string): string[] {\n const destination = join(output, 'app/src/main/assets/NativeFonts')\n const names = new Set<string>()\n const files = Object.entries(fonts ?? {}).map(([family, entry]) => {\n if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(family))\n throw new Error(`Invalid native font PostScript name: ${family}`)\n if (names.has(family.toLowerCase())) throw new Error(`Duplicate native font name: ${family}`)\n names.add(family.toLowerCase())\n if ([entry.src, entry.license].some(file => file && resolve(file).startsWith(resolve(destination) + sep)))\n throw new Error('Native font sources must be outside the generated NativeFonts directory')\n const extension = extname(entry.src).toLowerCase()\n if (!['.ttf', '.otf'].includes(extension) || !existsSync(entry.src) || !statSync(entry.src).isFile())\n throw new Error(`Native font ${family} must reference an existing TTF or OTF file: ${entry.src}`)\n if (entry.license && (!existsSync(entry.license) || !statSync(entry.license).isFile()))\n throw new Error(`Native font license not found: ${entry.license}`)\n return { family, ...entry, filename: `${family}${extension}` }\n })\n rmSync(destination, { recursive: true, force: true })\n if (!files.length) return []\n mkdirSync(destination, { recursive: true })\n for (const file of files) {\n cpSync(file.src, join(destination, file.filename))\n if (file.license) cpSync(file.license, join(destination, `${file.family}.LICENSE.txt`))\n }\n return files.map(file => `NativeFonts/${file.filename}`)\n}\n\nconst TEMPLATES_DIR = join(dirname(import.meta.dir), 'templates')\n\n/**\n * This builder's version, which the crash reporter names as its SDK version.\n * Walks up from here because a bundled build puts this module below the\n * package root.\n */\nfunction resolveCraftAndroidVersion(startDir: string = import.meta.dir): string {\n let directory = resolve(startDir)\n while (true) {\n try {\n const pkg = JSON.parse(readFileSync(join(directory, 'package.json'), 'utf8')) as { name?: unknown, version?: unknown }\n if ((pkg.name === '@craft-native/android' || pkg.name === 'craft-native') && typeof pkg.version === 'string' && pkg.version)\n return pkg.version\n }\n catch {\n // Keep walking.\n }\n const parent = dirname(directory)\n if (parent === directory) return '0.0.0'\n directory = parent\n }\n}\n\nconst CRAFT_ANDROID_VERSION = resolveCraftAndroidVersion()\nconst LOCAL_DEVELOPMENT_HOSTS = new Set(['localhost', '127.0.0.1', '10.0.2.2'])\nconst KOTLIN_KEYWORDS = new Set([\n 'as',\n 'break',\n 'class',\n 'continue',\n 'do',\n 'else',\n 'false',\n 'for',\n 'fun',\n 'if',\n 'in',\n 'interface',\n 'is',\n 'null',\n 'object',\n 'package',\n 'return',\n 'super',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typealias',\n 'typeof',\n 'val',\n 'var',\n 'when',\n 'while',\n])\n\n/** Oldest Android API level supported by the generated Kotlin runtime. */\nexport const ANDROID_MIN_SDK = 26\nconst ANDROID_HEALTH_SERVICES_MIN_SDK = 30\n\nexport interface CraftAndroidConfig {\n /** Bundled font files keyed by their PostScript font name, used as native fontFamily. */\n nativeFonts?: Record<string, { src: string, license?: string }>\n\n appName: string\n packageName: string\n renderer?: 'web' | 'native'\n /** \"system\" follows the device; light/dark pin the generated host. */\n appearance?: 'light' | 'dark' | 'system'\n /** Static native tab-bar styling applied before the page's own tabBar.set call. */\n tabBar?: CraftTabBarConfig\n /** Runs from the generated project root before Gradle compiles the app. */\n postGenerate?: CraftPostGenerateHook\n version?: string\n versionCode?: number\n darkMode?: boolean\n backgroundColor?: string\n backgroundColorDark?: string\n enableSpeechRecognition?: boolean\n enableAudioRecording?: boolean\n enableHaptics?: boolean\n enableShare?: boolean\n enableCamera?: boolean\n enableBiometric?: boolean\n enablePushNotifications?: boolean\n /** Enable native SQLite queries and transactions. Disabled unless explicitly true. */\n enableLocalDatabase?: boolean\n /** Enable native AlarmManager local notification scheduling. Disabled unless explicitly true. */\n enableLocalNotifications?: boolean\n enableSecureStorage?: boolean\n enableGeolocation?: boolean\n enableBackgroundLocation?: boolean\n enableBluetooth?: boolean\n /**\n * A Bluetooth heart-rate strap, or a watch broadcasting its heart rate (the\n * standard Heart Rate Service), through `craft.heartRate` on a page and the\n * `HeartRate` module on a native screen (CraftHeartRate.kt): scan, connect,\n * live readings as `craftHeartRate` events, and a recording kept natively,\n * in the foreground (a connectedDevice service) while it runs. The iOS\n * builder's flag of the same name.\n */\n enableHeartRate?: boolean\n enableHealthConnect?: boolean\n /** Android Health Services live exercise tracking for native screens. Requires minSdk 30. */\n enableHealthServices?: boolean\n /** Google Wallet save-link or native SDK handoff for native screens. */\n enableWallet?: boolean\n /**\n * The Health Connect data the app reads and writes, by the shared type\n * names (`steps`, `sleep`, `workouts`...). The manifest declares only\n * these, as Play's health permissions review requires; without it, the\n * original set (steps, heart rate, energy, distance, workouts).\n */\n healthConnect?: {\n read?: HealthConnectType[]\n write?: HealthConnectType[]\n /** Read while the app is in the background (a WorkManager refresh): Android 15's READ_HEALTH_DATA_IN_BACKGROUND. */\n background?: boolean\n /** Read further back than the 30 days before the first grant: READ_HEALTH_DATA_HISTORY. */\n history?: boolean\n }\n enableHealthConnectBackground?: boolean\n enableHealthConnectHistory?: boolean\n /** The app's privacy policy, which Health Connect links to from its permission screen. */\n privacyPolicyURL?: string\n enableKeepAwake?: boolean\n enableDeepLinks?: boolean\n /** Reach the person's own devices on the local network over plain HTTP (a Mac companion). */\n enableLocalNetwork?: boolean\n urlSchemes?: string[]\n /** HTTPS hosts owned by the app; path rules are ordered, with `*` matching any path text. */\n /** Ordered path rules: * matches zero or more characters, ? one, and ?* one or more. */\n appLinks?: Array<{ host: string, paths?: Array<{ pattern: string, exclude?: boolean }> }>\n trustedOrigins?: string[]\n appIconPath?: string\n /**\n * The small icon in the status bar and on every notification the app\n * shows, push or local: an Android vector drawable (`.xml`) or a `.png`,\n * white on transparent, since Android draws only its shape. Without one,\n * a white Craft mark. Never the launcher icon, which shows as a white\n * square.\n */\n notificationIconPath?: string\n /** The `#RRGGBB` Android tints the notification icon and app name with. The system's own colour without it. */\n notificationColor?: string\n googleServicesFile?: string\n /** Native map renderer. MapLibre needs no SDK key; Google remains the default for compatibility. */\n mapProvider?: AndroidMapProvider\n /** Google Maps Android SDK key, used only by the Google native map host. */\n mapsApiKey?: string\n devServerURL?: string\n hasBundledFallback?: boolean\n /** Android API level, at least ANDROID_MIN_SDK (26), or 30 with Health Services. */\n minSdk?: number\n compileSdk?: number\n targetSdk?: number\n /**\n * Native renderer: the app's paths and the screen drawing each\n * (`/m/workout/:id` → `Workout`), its tabs, and the bundle route of the\n * script that runs beside the screens. The same keys as the iOS builder.\n */\n nativeScreens?: Record<string, string>\n tabs?: Array<{\n id: string\n title: string\n symbol?: string\n /** Native selected-tab icon overrides, also supported by navigation.setOptions({ tabItem }). */\n selectedSymbol?: string\n selectedIconTint?: string\n selectedIconPulse?: boolean\n }>\n nativeApp?: string\n /**\n * The secure-storage key the signed-in account's token lives under\n * (default `auth.token`). `craft.session` follows it on every native\n * screen, and a change of it is `SESSION_CHANGED { key, token, previous }`.\n */\n sessionTokenKey?: string\n /** Wake the app script every so often (`craftBackgroundRefresh`), through WorkManager. */\n backgroundRefresh?: { enabled?: boolean, minimumIntervalMinutes?: number }\n /**\n * Crash and error reporting to bughq (CraftCrashReporter.kt): uncaught JVM\n * exceptions, ANRs and native crashes (ApplicationExitInfo), uncaught\n * JavaScript errors, and what the page sends through `craft.crashReporter`.\n * Queued on disk and sent when online. Release builds are minified: upload\n * `app/build/outputs/mapping/release/mapping.txt` so bughq can retrace.\n */\n crashReporting?: {\n /** The bughq project's public ingest key. */\n key: string\n /** Default https://bughq.org. */\n host?: string\n /** Default `production`. */\n environment?: string\n /** Default `<versionName>+<versionCode>`, e.g. `1.0.0+41`. */\n release?: string\n /** One session per launch, for crash-free sessions. Default on. */\n sessions?: boolean\n }\n}\n\nexport interface CraftTabBarConfig {\n selection?: {\n /** The selected tab indicator's corner radius in dp; omitted keeps the default. */\n cornerRadius?: number\n /** The selected tab indicator fill as #RRGGBB. */\n color?: string\n }\n}\n\n/** A declared command Craft runs after the native project has been generated. */\nexport interface CraftPostGenerateHook {\n command: string\n args?: string[]\n}\n\n/** The shared health data types (the iOS builder's HealthKit names). */\nexport type HealthConnectType = 'steps' | 'heartRate' | 'activeEnergy' | 'distance' | 'workouts' | 'restingHeartRate'\n | 'heartRateVariability' | 'bodyMass' | 'sleep' | 'mindful' | 'dietaryEnergy' | 'dietaryProtein'\n | 'dietaryCarbohydrates' | 'dietaryFat' | 'bloodGlucose' | 'insulinDelivery'\n\n/**\n * The Health Connect permissions behind each type, for reading and for\n * writing. CraftNativeHealth.kt asks for the same ones; a permission the\n * manifest does not declare is refused without a prompt.\n */\nexport const HEALTH_CONNECT_PERMISSIONS: Record<HealthConnectType, { read: string[], write: string[] }> = {\n steps: { read: ['READ_STEPS'], write: [] },\n heartRate: { read: ['READ_HEART_RATE'], write: [] },\n activeEnergy: { read: ['READ_ACTIVE_CALORIES_BURNED'], write: ['WRITE_ACTIVE_CALORIES_BURNED'] },\n distance: { read: ['READ_DISTANCE'], write: ['WRITE_DISTANCE'] },\n workouts: {\n read: ['READ_EXERCISE', 'READ_HEART_RATE', 'READ_ACTIVE_CALORIES_BURNED', 'READ_DISTANCE'],\n write: ['WRITE_EXERCISE', 'WRITE_ACTIVE_CALORIES_BURNED', 'WRITE_DISTANCE'],\n },\n restingHeartRate: { read: ['READ_RESTING_HEART_RATE'], write: [] },\n heartRateVariability: { read: ['READ_HEART_RATE_VARIABILITY'], write: [] },\n bodyMass: { read: ['READ_WEIGHT'], write: [] },\n sleep: { read: ['READ_SLEEP'], write: [] },\n mindful: { read: ['READ_MINDFULNESS'], write: ['WRITE_MINDFULNESS'] },\n dietaryEnergy: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryProtein: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryCarbohydrates: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryFat: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n bloodGlucose: { read: ['READ_BLOOD_GLUCOSE'], write: [] },\n // Health Connect has no insulin record; asking for it adds nothing.\n insulinDelivery: { read: [], write: [] },\n}\n\nconst DEFAULT_HEALTH_CONNECT = { read: ['steps', 'heartRate', 'activeEnergy', 'distance', 'workouts'], write: ['workouts'] } as const\n\n/** Every `android.permission.health.*` the app's Health Connect types need. */\nexport function healthConnectPermissions(config: Pick<CraftAndroidConfig, 'healthConnect'>): string[] {\n const read = config.healthConnect?.read ?? DEFAULT_HEALTH_CONNECT.read\n const write = config.healthConnect?.write ?? (config.healthConnect ? [] : DEFAULT_HEALTH_CONNECT.write)\n const permissions = new Set<string>()\n for (const type of read) {\n const known = HEALTH_CONNECT_PERMISSIONS[type as HealthConnectType]\n if (!known) throw new Error(`Unknown Health Connect type: ${type}`)\n known.read.forEach(permission => permissions.add(`android.permission.health.${permission}`))\n }\n for (const type of write) {\n const known = HEALTH_CONNECT_PERMISSIONS[type as HealthConnectType]\n if (!known) throw new Error(`Unknown Health Connect type: ${type}`)\n known.write.forEach(permission => permissions.add(`android.permission.health.${permission}`))\n }\n if (config.healthConnect?.background) permissions.add('android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND')\n if (config.healthConnect?.history) permissions.add('android.permission.health.READ_HEALTH_DATA_HISTORY')\n return [...permissions]\n}\n\nexport interface InitOptions {\n name: string\n packageName?: string\n output: string\n config?: Partial<CraftAndroidConfig>\n /**\n * Where to find the Zig runtime's `<abi>/libcraft.so`.\n *\n * `null` means no runtime regardless of the environment; `undefined` falls\n * through to `CRAFT_ANDROID_RUNTIME`. Same shape as the iOS builder's\n * `runtimeDir`.\n */\n runtimeDir?: string | null\n}\n\nexport interface BuildOptions {\n htmlPath?: string\n nativeBundlePath?: string\n /**\n * Native renderer: the app's icons as vectors (`{ viewBox, strokeWidth,\n * icons: { name: svgBody } }`, keyed by Iconify name and SF Symbol), which\n * `<Icon>`, the tab bar and the bar buttons draw. Without it they fall\n * back to the glyphs Android's fonts have.\n */\n iconsPath?: string\n devServer?: string\n output: string\n release?: boolean\n /**\n * An Android App Bundle (`bundleRelease`, `.aab`), what Google Play takes,\n * rather than an APK. Signed with CRAFT_ANDROID_KEYSTORE,\n * CRAFT_ANDROID_KEYSTORE_PASSWORD, CRAFT_ANDROID_KEY_ALIAS and\n * CRAFT_ANDROID_KEY_PASSWORD when they are set.\n */\n bundle?: boolean\n compile?: boolean\n /** Same meaning as `InitOptions.runtimeDir`; refreshes what init installed. */\n runtimeDir?: string | null\n}\n\n/**\n * Run the app's declared generator hook without invoking a shell.\n *\n * A hook gets the generated project as its cwd and explicit metadata so a\n * patch can target the right platform and phase without guessing from paths.\n */\nexport function runPostGenerateHook(\n hook: CraftPostGenerateHook | undefined,\n output: string,\n phase: 'build' = 'build',\n): void {\n if (!hook) return\n if (typeof hook.command !== 'string' || !hook.command.trim())\n throw new Error('Android postGenerate.command must be a non-empty executable')\n if (hook.args !== undefined && (!Array.isArray(hook.args) || hook.args.some(argument => typeof argument !== 'string')))\n throw new Error('Android postGenerate.args must be an array of strings')\n\n const command = [hook.command, ...(hook.args ?? [])]\n let result: ReturnType<typeof Bun.spawnSync>\n try {\n result = Bun.spawnSync(command, {\n cwd: output,\n env: { ...process.env, CRAFT_PROJECT_ROOT: output, CRAFT_PLATFORM: 'android', CRAFT_GENERATE_PHASE: phase },\n stdout: 'inherit',\n stderr: 'pipe',\n })\n }\n catch (error) {\n throw new Error(`Android postGenerate hook could not start in ${output}: ${hook.command}`, { cause: error })\n }\n if (result.exitCode !== 0) {\n const stderr = result.stderr?.toString().trim()\n throw new Error(`Android postGenerate hook failed in ${output} with exit code ${result.exitCode}${stderr ? `: ${stderr}` : ''}`)\n }\n}\n\nexport interface OpenOptions {\n output: string\n}\n\nexport interface RunOptions {\n device?: string\n output: string\n}\n\nconst DEFAULT_CONFIG: Omit<CraftAndroidConfig, 'appName' | 'packageName'> = {\n renderer: 'web',\n version: '1.0.0',\n versionCode: 1,\n darkMode: true,\n backgroundColor: '#0b1712',\n enableSpeechRecognition: false,\n enableAudioRecording: false,\n enableHaptics: false,\n enableShare: false,\n enableCamera: false,\n enableBiometric: false,\n enablePushNotifications: false,\n enableSecureStorage: false,\n enableGeolocation: false,\n enableBackgroundLocation: false,\n enableBluetooth: false,\n enableHeartRate: false,\n enableHealthConnect: false,\n enableHealthServices: false,\n enableWallet: false,\n enableKeepAwake: false,\n enableDeepLinks: false,\n urlSchemes: [],\n appLinks: [],\n trustedOrigins: [],\n minSdk: ANDROID_MIN_SDK,\n compileSdk: 36,\n targetSdk: 35,\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll('\\'', '&apos;')\n}\n\nfunction escapeKotlinString(value: string): string {\n return value\n .replaceAll('\\\\', '\\\\\\\\')\n .replaceAll('\"', '\\\\\"')\n .replaceAll('$', '\\\\$')\n .replaceAll('\\r', '\\\\r')\n .replaceAll('\\n', '\\\\n')\n}\n\nfunction generatedPackageSegment(name: string): string {\n const normalized = name.toLowerCase().replace(/[^a-z0-9_]/g, '')\n if (!normalized) return 'app'\n return /^[a-z_]/.test(normalized) ? normalized : `app${normalized}`\n}\n\nfunction generatedGradleProjectName(name: string): string {\n const invalidCharacters = ['/', '\\\\', ':', '<', '>', '\"', '?', '*', '|']\n const normalized = invalidCharacters.reduce(\n (value, character) => value.replaceAll(character, '-'),\n name,\n ).trim()\n return normalized || 'craft-app'\n}\n\nfunction requireRegularFile(path: string, label: string): void {\n if (!existsSync(path)) throw new Error(`${label} not found: ${path}`)\n if (!statSync(path).isFile()) throw new Error(`${label} must be a file: ${path}`)\n}\n\nfunction containsPath(parent: string, candidate: string): boolean {\n const relativePath = relative(parent, candidate)\n return relativePath === ''\n || (relativePath !== '..' && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath))\n}\n\nfunction validateGoogleServicesFile(path: string, packageName: string): void {\n requireRegularFile(path, 'Google services file')\n\n let document: {\n client?: Array<{\n client_info?: { android_client_info?: { package_name?: string } }\n }>\n }\n try {\n document = JSON.parse(readFileSync(path, 'utf8'))\n }\n catch (error) {\n throw new Error(`Google services file must contain valid JSON: ${path}`, { cause: error })\n }\n\n const matchingClient = document.client?.some((client) => {\n return client.client_info?.android_client_info?.package_name === packageName\n })\n if (!matchingClient) {\n throw new Error(`Google services file has no client for Android package ${packageName}: ${path}`)\n }\n}\n\nfunction androidWebUrl(value: string, field: string): URL {\n let url: URL\n try {\n url = new URL(value)\n }\n catch {\n throw new Error(`Invalid ${field}: ${value}`)\n }\n\n const localDevelopment = url.protocol === 'http:' && LOCAL_DEVELOPMENT_HOSTS.has(url.hostname)\n if ((url.protocol !== 'https:' && !localDevelopment) || url.username || url.password) {\n throw new Error(`${field} must use HTTPS or local HTTP without credentials: ${value}`)\n }\n return url\n}\n\nfunction normalizeAndroidNetworkConfig(config: CraftAndroidConfig): void {\n const schemes = config.urlSchemes?.map(value => value.trim().toLowerCase()) ?? []\n if (schemes.some(value => !/^[a-z][a-z0-9+.-]*$/.test(value))) {\n throw new Error('Android deep-link schemes must be valid URI schemes')\n }\n config.urlSchemes = [...new Set(schemes)]\n config.appLinks = (config.appLinks ?? []).map((link) => {\n const host = link.host.trim().toLowerCase()\n const parsed = new URL(`https://${host}`)\n if (!host || parsed.hostname !== host || parsed.port || parsed.username || parsed.password || parsed.pathname !== '/' || parsed.search || parsed.hash)\n throw new Error('Android App Links need a hostname without a scheme, port or path')\n for (const rule of link.paths ?? []) {\n if (!rule.pattern.startsWith('/') || /[\\x00-\\x1f]/.test(rule.pattern) || (rule.exclude !== undefined && typeof rule.exclude !== 'boolean'))\n throw new Error('Android App Link path rules need an absolute path pattern and a boolean exclude')\n }\n return { ...link, host }\n })\n if (new Set(config.appLinks.map(link => link.host)).size !== config.appLinks.length)\n throw new Error('Android App Link hosts must be unique')\n if (config.enableDeepLinks && config.urlSchemes.length === 0 && config.appLinks.length === 0) {\n throw new Error('Android deep links require at least one URL scheme or an App Link host')\n }\n\n const trustedOrigins = (config.trustedOrigins ?? []).map((value) => {\n return androidWebUrl(value, 'Android trusted origin').origin\n })\n if (config.devServerURL) {\n const devServer = androidWebUrl(config.devServerURL, 'Android dev server URL')\n config.devServerURL = devServer.toString()\n trustedOrigins.push(devServer.origin)\n }\n config.trustedOrigins = [...new Set(trustedOrigins)]\n}\n\nfunction validateAndroidConfig(config: CraftAndroidConfig): void {\n androidMapHost(config.mapProvider)\n if (!config.appName.trim()) throw new Error('Android app name must not be empty')\n if (config.renderer !== undefined && config.renderer !== 'web' && config.renderer !== 'native') {\n throw new Error(`Unknown Android renderer: ${config.renderer}. Expected web or native.`)\n }\n if (config.appearance !== undefined && !['light', 'dark', 'system'].includes(config.appearance)) {\n throw new Error(`Unknown Android appearance: ${config.appearance}. Expected light, dark, or system.`)\n }\n const selection = config.tabBar?.selection\n if (selection?.cornerRadius !== undefined && (!Number.isFinite(selection.cornerRadius) || selection.cornerRadius < 0))\n throw new Error('Android tabBar.selection.cornerRadius must be a finite non-negative number')\n if (selection?.color !== undefined && !/^#[0-9a-f]{6}$/i.test(selection.color))\n throw new Error('Android tabBar.selection.color must be a #RRGGBB color')\n\n const packageSegments = config.packageName.split('.')\n if (packageSegments.length < 2\n || packageSegments.some(segment => !/^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) || KOTLIN_KEYWORDS.has(segment))) {\n throw new Error(`Invalid Android package name: ${config.packageName}`)\n }\n\n if (!/^#(?:[\\dA-F]{3,4}|[\\dA-F]{6}|[\\dA-F]{8})$/i.test(config.backgroundColor ?? '')) {\n throw new Error(`Invalid Android background color: ${config.backgroundColor}`)\n }\n\n if (config.backgroundColorDark !== undefined && !config.backgroundColorDark.match(/^#[\\dA-F]{3,4}$|^#[\\dA-F]{6}$|^#[\\dA-F]{8}$/i)) {\n throw new Error(`Invalid Android dark background color: ${config.backgroundColorDark}`)\n }\n\n if (config.mapsApiKey !== undefined && !config.mapsApiKey.trim()) {\n throw new Error('Android mapsApiKey must not be empty')\n }\n\n for (const [name, value] of [\n ['versionCode', config.versionCode],\n ['minSdk', config.minSdk],\n ['compileSdk', config.compileSdk],\n ['targetSdk', config.targetSdk],\n ] as const) {\n if (!Number.isInteger(value) || Number(value) < 1) {\n throw new Error(`Android ${name} must be a positive integer`)\n }\n }\n\n if (Number(config.minSdk) < ANDROID_MIN_SDK) {\n throw new Error(`Android minSdk must be at least ${ANDROID_MIN_SDK} (Android 8.0) for the Craft runtime`)\n }\n if (config.enableHealthServices && Number(config.minSdk) < ANDROID_HEALTH_SERVICES_MIN_SDK) {\n throw new Error(`Android Health Services requires minSdk at least ${ANDROID_HEALTH_SERVICES_MIN_SDK} (Android 11)`)\n }\n if (Number(config.minSdk) > Number(config.targetSdk)) {\n throw new Error('Android minSdk must not exceed targetSdk')\n }\n if (Number(config.targetSdk) > Number(config.compileSdk)) {\n throw new Error('Android targetSdk must not exceed compileSdk')\n }\n}\n\nfunction normalizeNativeRoutePath(raw: unknown): string | null {\n if (typeof raw !== 'string') return null\n let path = raw\n const cut = path.search(/[?#]/)\n if (cut >= 0) path = path.slice(0, cut)\n if (!path.startsWith('/')) return null\n path = path.replace(/\\/{2,}/g, '/')\n if (path.length > 1 && path.endsWith('/')) path = path.slice(0, -1)\n return path\n}\n\nfunction nativeRouteSegments(path: string): string[] {\n return path === '/' ? [] : path.slice(1).split('/')\n}\n\nfunction matchesNativeRoute(nativeScreens: Record<string, string> | undefined, raw: string): boolean {\n const path = normalizeNativeRoutePath(raw)\n if (path === null) return false\n const parts = nativeRouteSegments(path)\n return Object.entries(nativeScreens ?? {}).some(([pattern, screen]) => {\n if (!screen) return false\n const normalized = normalizeNativeRoutePath(pattern)\n if (normalized === null) return false\n const route = nativeRouteSegments(normalized)\n for (let index = 0; index < route.length; index++) {\n const segment = route[index]\n if (segment === '*') return index === route.length - 1\n if (index >= parts.length) return false\n if (segment.startsWith(':')) {\n if (!parts[index]) return false\n }\n else if (segment !== parts[index]) return false\n }\n return route.length === parts.length\n })\n}\n\nfunction nativeStartPath(config: CraftAndroidConfig): string {\n if (!config.devServerURL) return '/'\n try {\n const url = new URL(config.devServerURL)\n return `${url.pathname || '/'}${url.search}`\n }\n catch {\n return '/'\n }\n}\n\nfunction validateNativeRouteConfig(config: CraftAndroidConfig): void {\n const screens = Object.entries(config.nativeScreens ?? {})\n for (const [pattern, screen] of screens) {\n if (normalizeNativeRoutePath(pattern) !== pattern || /[?#]/.test(pattern))\n throw new Error(`nativeScreens path \"${pattern}\" must be an absolute path with no query, hash or trailing slash.`)\n if (nativeRouteSegments(normalizeNativeRoutePath(pattern) ?? '/').slice(0, -1).includes('*'))\n throw new Error(`nativeScreens path \"${pattern}\" may only end in *.`)\n if (typeof screen !== 'string' || !/^[A-Za-z_$][\\w$-]*$/.test(screen))\n throw new Error(`nativeScreens screen \"${String(screen)}\" for \"${pattern}\" must be a screen name from the native bundle.`)\n }\n\n const ids = new Set<string>()\n for (const tab of config.tabs ?? []) {\n if (!tab || typeof tab.id !== 'string' || !tab.id || typeof tab.title !== 'string' || !tab.title)\n throw new Error('Each tab needs an id (its root path) and a title.')\n if (ids.has(tab.id)) throw new Error(`Tab \"${tab.id}\" is listed twice.`)\n ids.add(tab.id)\n }\n\n if (config.renderer === 'native' && screens.length > 0) {\n for (const id of ids) {\n if (!matchesNativeRoute(config.nativeScreens, id))\n throw new Error(`Tab \"${id}\" is not a nativeScreens path; with renderer: \"native\" every tab must be a native screen.`)\n }\n const start = nativeStartPath(config)\n if (!matchesNativeRoute(config.nativeScreens, start))\n throw new Error(`The start path \"${start}\" (from devServerURL) is not a nativeScreens path; with renderer: \"native\" the app must start on a native screen.`)\n }\n\n if (config.nativeApp !== undefined) {\n if (typeof config.nativeApp !== 'string' || !/^[A-Za-z_$][\\w$-]*$/.test(config.nativeApp))\n throw new Error(`nativeApp \"${String(config.nativeApp)}\" must be a route name from the native bundle.`)\n if (config.renderer !== 'native' && screens.length === 0)\n throw new Error('nativeApp runs in the native bundle; it needs nativeScreens or renderer: \"native\".')\n }\n}\n\nfunction writeAndroidConfig(output: string, config: CraftAndroidConfig): void {\n writeFileSync(join(output, 'craft.config.json'), JSON.stringify(config, null, 2))\n\n // Generator-only paths can reveal the developer machine's directory layout\n // and have no meaning to the installed app. Keep them in the project config\n // but never package them into the APK's assets.\n const runtimeConfig = { ...config }\n delete runtimeConfig.appIconPath\n delete runtimeConfig.notificationIconPath\n delete runtimeConfig.googleServicesFile\n writeFileSync(\n join(output, 'app/src/main/assets/craft.config.json'),\n JSON.stringify(runtimeConfig, null, 2),\n )\n}\n\nexport function syncAndroidWebAssets(source: string, output: string): void {\n const sourcePath = resolve(source)\n if (!existsSync(sourcePath)) throw new Error(`Web asset path not found: ${source}`)\n const sourceStat = statSync(sourcePath)\n if (!sourceStat.isDirectory() && !sourceStat.isFile()) {\n throw new Error(`Web asset path must be a file or directory: ${source}`)\n }\n\n const assetsDir = resolve(output, 'app/src/main/assets')\n if (containsPath(sourcePath, assetsDir) || containsPath(assetsDir, sourcePath)) {\n throw new Error(`Web asset source must not overlap generated asset directory: ${source}`)\n }\n if (sourceStat.isDirectory()) {\n requireRegularFile(join(sourcePath, 'index.html'), 'Web asset directory entry point')\n }\n\n const configPath = join(assetsDir, 'craft.config.json')\n const config = existsSync(configPath) ? readFileSync(configPath) : undefined\n rmSync(assetsDir, { recursive: true, force: true })\n mkdirSync(assetsDir, { recursive: true })\n if (sourceStat.isDirectory()) cpSync(sourcePath, assetsDir, { recursive: true })\n else cpSync(sourcePath, join(assetsDir, 'index.html'))\n if (!existsSync(join(assetsDir, 'index.html'))) throw new Error(`Web asset directory must contain index.html: ${source}`)\n if (config) writeFileSync(configPath, config)\n}\n\nexport function renderAndroidPermissions(config: CraftAndroidConfig): string {\n const permissions = new Set(['android.permission.INTERNET', 'android.permission.ACCESS_NETWORK_STATE'])\n if (config.enableSpeechRecognition || config.enableAudioRecording) permissions.add('android.permission.RECORD_AUDIO')\n if (config.enableCamera) permissions.add('android.permission.CAMERA')\n if (config.enableHaptics) permissions.add('android.permission.VIBRATE')\n if (config.enableBiometric) permissions.add('android.permission.USE_BIOMETRIC')\n if (config.enableGeolocation || config.enableBackgroundLocation) {\n permissions.add('android.permission.ACCESS_FINE_LOCATION')\n permissions.add('android.permission.ACCESS_COARSE_LOCATION')\n }\n if (config.enableBackgroundLocation) {\n permissions.add('android.permission.ACCESS_BACKGROUND_LOCATION')\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_LOCATION')\n }\n if (config.enablePushNotifications) permissions.add('android.permission.POST_NOTIFICATIONS')\n if (config.enableKeepAwake) permissions.add('android.permission.WAKE_LOCK')\n if (config.enableHealthConnect) healthConnectPermissions(config).forEach(permission => permissions.add(permission))\n // A background refresh (WorkManager) after a restart.\n if (config.renderer === 'native' && config.backgroundRefresh?.enabled) permissions.add('android.permission.RECEIVE_BOOT_COMPLETED')\n // A heart-rate recording keeps the process in the foreground while it\n // runs (CraftHeartRateService), as a connectedDevice service.\n if (config.enableHeartRate) {\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE')\n }\n if (config.enableHealthServices) {\n permissions.add('android.permission.BODY_SENSORS')\n permissions.add('android.permission.BODY_SENSORS_BACKGROUND')\n permissions.add('android.permission.health.READ_HEART_RATE')\n permissions.add('android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND')\n permissions.add('android.permission.ACTIVITY_RECOGNITION')\n permissions.add('android.permission.ACCESS_FINE_LOCATION')\n permissions.add('android.permission.ACCESS_COARSE_LOCATION')\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_HEALTH')\n }\n const bluetooth = config.enableBluetooth || config.enableHeartRate ? [\n ' <uses-permission android:name=\"android.permission.BLUETOOTH\" android:maxSdkVersion=\"30\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" android:maxSdkVersion=\"30\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\" android:usesPermissionFlags=\"neverForLocation\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />',\n ...(permissions.has('android.permission.ACCESS_FINE_LOCATION') ? [] : [' <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" android:maxSdkVersion=\"30\" />']),\n ].join('\\n') : ''\n return [bluetooth, ...[...permissions].map(permission => ` <uses-permission android:name=\"${permission}\" />`)].filter(Boolean).join('\\n')\n}\n\n/**\n * The native renderer's own sources: the app around the screens (routes,\n * stores, bars), its services (dialogs, browser, share, push, Health\n * Connect), background refresh, and Firebase messaging when push is on.\n */\nfunction writeNativeShellSources(output: string, packagePath: string, packageName: string, config: CraftAndroidConfig): void {\n const javaDir = join(output, 'app/src/main/java', packagePath)\n const write = (template: string, file: string, replace: (source: string) => string = source => source): void => {\n const source = readFileSync(join(TEMPLATES_DIR, template), 'utf-8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, packageName)\n writeFileSync(join(javaDir, file), replace(source))\n }\n write('CraftBluetooth.kt.template', 'CraftBluetooth.kt')\n write('CraftNativeShell.kt.template', 'CraftNativeShell.kt')\n write('CraftSnapshotFile.kt.template', 'CraftSnapshotFile.kt')\n write('CraftNativeImageCache.kt.template', 'CraftNativeImageCache.kt')\n write('CraftNativeHaptics.kt.template', 'CraftNativeHaptics.kt')\n write('CraftNativeBackground.kt.template', 'CraftNativeBackground.kt')\n write(config.enableHealthConnect ? 'CraftNativeHealth.kt.template' : 'CraftNativeHealthStub.kt.template', 'CraftNativeHealth.kt')\n write(config.enableHealthServices ? 'CraftHealthServices.kt.template' : 'CraftHealthServicesStub.kt.template', 'CraftHealthServices.kt')\n if (config.enableHealthServices) {\n write('CraftHealthServicesService.kt.template', 'CraftHealthServicesService.kt')\n }\n else {\n rmSync(join(javaDir, 'CraftHealthServicesService.kt'), { force: true })\n }\n write('CraftNativeServices.kt.template', 'CraftNativeServices.kt', source => source\n .replace('{{NATIVE_PUSH_IMPORTS}}', config.enablePushNotifications ? 'import com.google.firebase.messaging.FirebaseMessaging' : '')\n .replace('{{NATIVE_WALLET_IMPORTS}}', config.enableWallet ? `import com.google.android.gms.pay.Pay\nimport com.google.android.gms.pay.PayApiAvailabilityStatus\nimport com.google.android.gms.pay.PayClient` : '')\n .replace('{{NATIVE_WALLET_FIELDS}}', config.enableWallet ? ` private var pendingWallet: ((CraftNativeCapabilityResult) -> Unit)? = null\n private val walletRequestCode = 9517` : '')\n .replace('{{NATIVE_WALLET_AVAILABILITY}}', config.enableWallet ? ` val host = activity()\n if (host == null) {\n done(success(false))\n } else {\n Pay.getClient(host).getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES_JWT)\n .addOnSuccessListener { status -> done(success(status == PayApiAvailabilityStatus.AVAILABLE)) }\n .addOnFailureListener { done(success(false)) }\n }` : ` done(success(runCatching {\n context.packageManager.getLaunchIntentForPackage(\"com.google.android.apps.walletnfcrel\") != null\n }.getOrDefault(false)))`)\n .replace('{{NATIVE_WALLET_JWT_ADD}}', config.enableWallet\n ? ' saveWalletJwt(jwt, host, done)'\n : ' done(failure(\"UNSUPPORTED\", \"Android Wallet JWT saves are not enabled\"))')\n .replace('{{NATIVE_WALLET_HELPER}}', config.enableWallet ? ` private fun saveWalletJwt(jwt: String, host: Activity, done: (CraftNativeCapabilityResult) -> Unit) {\n if (pendingWallet != null) return done(failure(\"BUSY\", \"A Google Wallet save is already in progress\"))\n pendingWallet = done\n try {\n Pay.getClient(host).savePassesJwt(jwt, host, walletRequestCode)\n } catch (error: Exception) {\n pendingWallet = null\n done(failure(\"PRESENTATION_FAILED\", error.message ?: \"Google Wallet could not open\"))\n }\n }\n` : '')\n .replace('{{NATIVE_WALLET_RESULT}}', config.enableWallet ? ` if (requestCode == walletRequestCode) {\n val completion = pendingWallet\n pendingWallet = null\n if (completion == null) return true\n when (resultCode) {\n Activity.RESULT_OK -> completion(success(true))\n Activity.RESULT_CANCELED -> completion(success(false))\n PayClient.SavePassesResult.API_UNAVAILABLE -> completion(failure(\"UNAVAILABLE\", \"Google Wallet save is unavailable\"))\n PayClient.SavePassesResult.INTERNAL_ERROR -> completion(failure(\"WALLET_ERROR\", \"Google Wallet returned an internal error\"))\n PayClient.SavePassesResult.SAVE_ERROR -> completion(failure(\"SAVE_ERROR\", data?.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE) ?: \"Google Wallet could not save the pass\"))\n else -> completion(failure(\"WALLET_ERROR\", \"Google Wallet returned an unknown result\"))\n }\n return true\n }\n` : '')\n .replace('{{NATIVE_PUSH_REGISTER}}', config.enablePushNotifications\n ? ` try {\n FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->\n val token = if (task.isSuccessful) task.result else null\n if (token.isNullOrBlank()) done(failure(\"PUSH_UNAVAILABLE\", task.exception?.message ?: \"Firebase Cloud Messaging gave no token\"))\n else {\n context.getSharedPreferences(\"craft-native-push\", Context.MODE_PRIVATE).edit().putString(\"token\", token).apply()\n done(success(token))\n }\n }\n } catch (error: Exception) {\n done(failure(\"PUSH_UNAVAILABLE\", error.message ?: \"Firebase Cloud Messaging is not configured\"))\n }`\n : ' done(failure(\"CAPABILITY_DISABLED\", \"Push notifications are disabled\"))'))\n write('CraftNativeSounds.kt.template', 'CraftNativeSounds.kt')\n if (config.enablePushNotifications) write('CraftNativeMessagingService.kt.template', 'CraftNativeMessagingService.kt')\n else rmSync(join(javaDir, 'CraftNativeMessagingService.kt'), { force: true })\n // Files a screen shares (craft.files' copies, in the cache) go to other apps through this provider.\n mkdirSync(join(output, 'app/src/main/res/xml'), { recursive: true })\n writeFileSync(join(output, 'app/src/main/res/xml/craft_file_paths.xml'), `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n <cache-path name=\"craft-files\" path=\"craft-files/\" />\n <files-path name=\"craft-media\" path=\"craft-media/\" />\n</paths>\n`)\n}\n\n/** What the native renderer adds to the manifest's application element. */\nfunction renderNativeShellManifest(config: CraftAndroidConfig): string {\n const parts = [\n ' <receiver android:name=\".CraftNativeNotificationReceiver\" android:exported=\"false\" />',\n ` <provider\n android:name=\"androidx.core.content.FileProvider\"\n android:authorities=\"${config.packageName}.craftfiles\"\n android:exported=\"false\"\n android:grantUriPermissions=\"true\">\n <meta-data android:name=\"android.support.FILE_PROVIDER_PATHS\" android:resource=\"@xml/craft_file_paths\" />\n </provider>`,\n ]\n if (config.enablePushNotifications) {\n // What Android shows for a push that arrives while the app is in the\n // background, which Firebase draws without the service.\n parts.push(` <service android:name=\".CraftNativeMessagingService\" android:exported=\"false\">\n <intent-filter>\n <action android:name=\"com.google.firebase.MESSAGING_EVENT\" />\n </intent-filter>\n </service>\n <meta-data android:name=\"com.google.firebase.messaging.default_notification_icon\" android:resource=\"@drawable/craft_notification_icon\" />${config.notificationColor ? `\n <meta-data android:name=\"com.google.firebase.messaging.default_notification_color\" android:resource=\"@color/craft_notification_color\" />` : ''}`)\n }\n if (config.enableHealthConnect) {\n // Android 14 and later open the app's privacy policy from Health\n // Connect's permission screen through this alias.\n parts.push(` <activity-alias\n android:name=\"ViewPermissionUsageActivity\"\n android:exported=\"true\"\n android:targetActivity=\".MainActivity\"\n android:permission=\"android.permission.START_VIEW_PERMISSION_USAGE\">\n <intent-filter>\n <action android:name=\"android.intent.action.VIEW_PERMISSION_USAGE\" />\n <category android:name=\"android.intent.category.HEALTH_PERMISSIONS\" />\n </intent-filter>\n </activity-alias>`)\n }\n return parts.join('\\n')\n}\n\nexport function renderAndroidDeepLinks(config: CraftAndroidConfig): string {\n if (!config.enableDeepLinks) return ''\n const schemes = [...new Set(config.urlSchemes?.map(value => value.trim()).filter(value => /^[a-z][a-z0-9+.-]*$/i.test(value)) ?? [])]\n const custom = schemes.map(scheme => ` <intent-filter>\n <action android:name=\"android.intent.action.VIEW\" />\n <category android:name=\"android.intent.category.DEFAULT\" />\n <category android:name=\"android.intent.category.BROWSABLE\" />\n <data android:scheme=\"${scheme}\" />\n </intent-filter>`).join('\\n')\n const verified = (config.appLinks ?? []).map(link => {\n if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i.test(link.host)) throw new Error('Invalid Android App Link host')\n return ` <intent-filter android:autoVerify=\"true\">\n <action android:name=\"android.intent.action.VIEW\" />\n <category android:name=\"android.intent.category.DEFAULT\" />\n <category android:name=\"android.intent.category.BROWSABLE\" />\n <data android:scheme=\"https\" android:host=\"${link.host}\" />\n </intent-filter>`\n }).join('\\n')\n return [custom, verified].filter(Boolean).join('\\n')\n}\n\n/**\n * Initialize a new Android project\n */\n/**\n * The ABI directories a runtime directory is expected to hold.\n *\n * These are Android's own names for the two architectures craft builds, and\n * they are also `zig build build-android-all`'s output layout — `zig-out/android/`\n * already contains `arm64-v8a/libcraft.so` and `x86_64/libcraft.so`, which is\n * exactly the shape `app/src/main/jniLibs/` wants. So the install below is a\n * copy and not a rearrangement.\n *\n * x86_64 is not optional-in-practice: every Android emulator anyone tests on\n * is x86_64, so a runtime shipped for arm64 alone is one that never runs in\n * CI and never runs on a developer's machine either.\n */\nconst RUNTIME_ABIS = ['arm64-v8a', 'x86_64'] as const\n\n/**\n * Where the runtime directory comes from when the caller does not say.\n *\n * The same shape as `CRAFT_BIN` and the iOS builder's `CRAFT_IOS_RUNTIME`: an\n * explicit override for the monorepo dev loop, not a lookup path. Shipping the\n * runtime to real apps means putting these libraries in the pantry package\n * beside the `craft` binary, which is a distribution decision this function\n * does not make.\n */\nexport function resolveRuntimeDir(override?: string | null): string | null {\n if (override === null) return null\n const dir = override ?? process.env.CRAFT_ANDROID_RUNTIME\n if (!dir) return null\n if (!existsSync(dir)) {\n const source = override === undefined ? 'CRAFT_ANDROID_RUNTIME points at' : 'runtimeDir is'\n throw new Error(`${source} ${dir}, which does not exist.`)\n }\n return dir\n}\n\n/**\n * Copy the Zig runtime into the generated project as\n * `app/src/main/jniLibs/<abi>/libcraft.so`.\n *\n * That path is AGP's default `jniLibs.srcDirs`, so nothing in the Gradle\n * templates has to know about it — the library is packaged into the APK and\n * `System.loadLibrary(\"craft\")` finds it because the file is named for the\n * `craft` it asks for.\n *\n * Until this existed, nothing put the library anywhere. `CraftNative` caught\n * the `UnsatisfiedLinkError`, set `isAvailable = false`, and every action fell\n * through to the Kotlin shim — by design, so an app with no runtime still\n * works, which is also why nobody noticed that *every* generated app was in\n * that state and the whole Android half of the Zig bridge had never run.\n *\n * Returns true when a runtime was installed.\n */\nexport function installRuntime(output: string, runtimeDir: string): boolean {\n // Every ABI resolved before anything is written, so a half-populated\n // runtime directory cannot leave a project carrying one architecture and\n // claiming both. A single-ABI APK installs fine and then fails to load on\n // the other kind of device, which is the break that only shows up on\n // somebody else's phone.\n const found = RUNTIME_ABIS.map(abi => ({ abi, source: join(runtimeDir, abi, 'libcraft.so') }))\n .filter(entry => existsSync(entry.source))\n\n if (found.length === 0) {\n throw new Error(\n `${runtimeDir} has no <abi>/libcraft.so for any of ${RUNTIME_ABIS.join(', ')}. `\n + 'Run `zig build build-android-all -Doptimize=ReleaseSafe` in packages/zig and point at its zig-out/android.',\n )\n }\n\n if (found.length < RUNTIME_ABIS.length) {\n const missing = RUNTIME_ABIS.filter(abi => !found.some(entry => entry.abi === abi))\n console.warn(\n ` ⚠ only ${found.map(entry => entry.abi).join(', ')} was found; ${missing.join(', ')} is missing. `\n + 'The app will fall back to the Kotlin shim on those devices.',\n )\n }\n\n const dest = join(output, 'app/src/main/jniLibs')\n // Wiped rather than merged, so an ABI dropped from a later build does not\n // linger in the project as a stale library the APK still ships.\n rmSync(dest, { force: true, recursive: true })\n\n for (const { abi, source } of found) {\n const abiDir = join(dest, abi)\n mkdirSync(abiDir, { recursive: true })\n cpSync(source, join(abiDir, 'libcraft.so'))\n }\n\n return true\n}\n\nexport async function init(options: InitOptions): Promise<void> {\n const { name, packageName, output } = options\n\n console.log(`\\n⚡ Initializing Craft Android project: ${name}`)\n console.log(` Output: ${output}\\n`)\n\n // Generate package name from app name if not provided\n const finalPackageName = packageName || `com.craft.${generatedPackageSegment(name)}`\n const packagePath = finalPackageName.replace(/\\./g, '/')\n\n // Command-level identity always wins over duplicate fields in `config`.\n // Normalize implied capabilities before validation so craft.config.json and\n // the generated Gradle source describe the same effective project.\n // Undefined keeps the default instead of erasing it (see the iOS builder).\n const given = Object.fromEntries(Object.entries(options.config ?? {}).filter(([, value]) => value !== undefined))\n const config: CraftAndroidConfig = {\n ...DEFAULT_CONFIG,\n ...given,\n appName: name,\n packageName: finalPackageName,\n }\n if (config.enableHealthServices && given.minSdk === undefined) config.minSdk = ANDROID_HEALTH_SERVICES_MIN_SDK\n if (config.enableBackgroundLocation) config.enableGeolocation = true\n if (config.enableHealthConnect) {\n config.compileSdk = Math.max(config.compileSdk ?? 36, 36)\n config.enableHealthConnectBackground = Boolean(config.healthConnect?.background)\n config.enableHealthConnectHistory = Boolean(config.healthConnect?.history)\n healthConnectPermissions(config)\n }\n normalizeAndroidNetworkConfig(config)\n validateAndroidConfig(config)\n validateNativeRouteConfig(config)\n if (config.enablePushNotifications && !config.googleServicesFile) {\n throw new Error('Android push notifications require a googleServicesFile')\n }\n if (config.googleServicesFile) validateGoogleServicesFile(config.googleServicesFile, finalPackageName)\n if (config.appIconPath) requireRegularFile(config.appIconPath, 'App icon')\n const appIconExtension = config.appIconPath ? extname(config.appIconPath).toLowerCase() : undefined\n if (config.appIconPath && !['.gif', '.jpg', '.png', '.webp'].includes(appIconExtension ?? '')) {\n throw new Error(`Unsupported Android app icon format: ${appIconExtension || '(none)'}`)\n }\n if (config.notificationIconPath) requireRegularFile(config.notificationIconPath, 'Notification icon')\n const notificationIconExtension = config.notificationIconPath ? extname(config.notificationIconPath).toLowerCase() : undefined\n if (config.notificationIconPath && !['.png', '.xml'].includes(notificationIconExtension ?? '')) {\n throw new Error(`Unsupported Android notification icon format: ${notificationIconExtension || '(none)'} (use a vector drawable .xml or a white-on-transparent .png)`)\n }\n if (config.notificationIconPath && notificationIconExtension === '.xml' && !/<vector[\\s>]/.test(readFileSync(config.notificationIconPath, 'utf8'))) {\n throw new Error('Notification icon .xml must be an Android vector drawable (<vector>)')\n }\n if (config.notificationColor !== undefined && !/^#[0-9a-f]{6}$/i.test(config.notificationColor)) {\n throw new Error(`notificationColor must be #RRGGBB, not ${String(config.notificationColor)}`)\n }\n\n // Create directory structure\n const dirs = [\n output,\n join(output, 'app/src/main/java', packagePath),\n join(output, 'app/src/main/res/layout'),\n join(output, 'app/src/main/res/values'),\n join(output, 'app/src/main/res/values-night'),\n join(output, 'app/src/main/res/drawable'),\n join(output, 'app/src/main/assets'),\n join(output, 'gradle/wrapper'),\n ]\n\n if (existsSync(output) && !statSync(output).isDirectory()) {\n throw new Error(`Android project output must be a directory: ${output}`)\n }\n\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n }\n\n // Create craft.config.json\n writeAndroidConfig(output, config)\n\n const hasGoogleServices = Boolean(config.googleServicesFile)\n if (config.googleServicesFile) {\n cpSync(config.googleServicesFile, join(output, 'app/google-services.json'))\n }\n\n // Copy templates\n const mainActivityTemplate = readFileSync(join(\n TEMPLATES_DIR,\n config.renderer === 'native' ? 'MainActivityNative.kt.template' : 'MainActivity.kt.template',\n ), 'utf-8')\n const mainActivity = mainActivityTemplate\n .replace(/\\{\\{NATIVE_MAP_IMPORTS\\}\\}/g, () => androidMapHost(config.mapProvider).imports)\n .replace(/\\{\\{NATIVE_MAP_HOST\\}\\}/g, () => readFileSync(join(TEMPLATES_DIR, androidMapHost(config.mapProvider).template), 'utf8'))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n\n writeFileSync(join(output, 'app/src/main/java', packagePath, 'MainActivity.kt'), mainActivity)\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftAppLinks.kt'),\n readFileSync(join(TEMPLATES_DIR, 'CraftAppLinks.kt.template'), 'utf8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n // Both renderers: crash reporting does not depend on how screens are drawn.\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftCrashReporter.kt'),\n readFileSync(join(TEMPLATES_DIR, 'CraftCrashReporter.kt.template'), 'utf-8')\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{CRAFT_VERSION\\}\\}/g, CRAFT_ANDROID_VERSION),\n )\n if (config.renderer === 'native') {\n const mutationTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeMutation.kt.template'), 'utf-8')\n const flatListTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeFlatList.kt.template'), 'utf-8')\n const refreshableFlatListTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeRefreshableFlatList.kt.template'), 'utf-8')\n const capabilityTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeCapabilities.kt.template'), 'utf-8')\n const notificationTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeNotificationReceiver.kt.template'), 'utf-8')\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeMutation.kt'),\n mutationTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeFlatList.kt'),\n flatListTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeRefreshableFlatList.kt'),\n refreshableFlatListTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeCapabilities.kt'),\n capabilityTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeNotificationReceiver.kt'),\n notificationTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeNativeShellSources(output, packagePath, finalPackageName, config)\n }\n\n const permissionPolicy = readFileSync(join(TEMPLATES_DIR, 'CraftPermissionPolicy.kt.template'), 'utf8')\n writeFileSync(join(output, 'app/src/main/java', packagePath, 'CraftPermissionPolicy.kt'), permissionPolicy.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName))\n\n // Create CraftBridge.kt\n const craftBridgeTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftBridge.kt.template'), 'utf-8')\n const craftBridge = craftBridgeTemplate\n .replace(/\\{\\{PROMISE_RUNTIME\\}\\}/g, () => renderAndroidPromiseRuntime(' '))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{ENABLE_SPEECH\\}\\}/g, String(Boolean(config.enableSpeechRecognition)))\n .replace(/\\{\\{ENABLE_HAPTICS\\}\\}/g, String(Boolean(config.enableHaptics)))\n .replace(/\\{\\{ENABLE_SHARE\\}\\}/g, String(Boolean(config.enableShare)))\n .replace(/\\{\\{ENABLE_CAMERA\\}\\}/g, String(Boolean(config.enableCamera)))\n .replace(/\\{\\{ENABLE_BIOMETRIC\\}\\}/g, String(Boolean(config.enableBiometric)))\n .replace(/\\{\\{ENABLE_PUSH\\}\\}/g, String(Boolean(config.enablePushNotifications)))\n .replace(/\\{\\{ENABLE_SECURE_STORAGE\\}\\}/g, String(Boolean(config.enableSecureStorage)))\n .replace(/\\{\\{ENABLE_GEOLOCATION\\}\\}/g, String(Boolean(config.enableGeolocation)))\n .replace(/\\{\\{ENABLE_BACKGROUND_LOCATION\\}\\}/g, String(Boolean(config.enableBackgroundLocation)))\n .replace(/\\{\\{ENABLE_KEEP_AWAKE\\}\\}/g, String(Boolean(config.enableKeepAwake)))\n .replace(/\\{\\{ENABLE_DEEP_LINKS\\}\\}/g, String(Boolean(config.enableDeepLinks)))\n .replace(/\\{\\{ENABLE_HEALTH_CONNECT\\}\\}/g, String(Boolean(config.enableHealthConnect)))\n .replace(/\\{\\{ENABLE_HEART_RATE\\}\\}/g, String(Boolean(config.enableHeartRate)))\n .replace(/\\{\\{FIREBASE_IMPORT\\}\\}/g, config.enablePushNotifications ? 'import com.google.firebase.messaging.FirebaseMessaging' : '')\n .replace(/\\{\\{REGISTER_PUSH_IMPLEMENTATION\\}\\}/g, config.enablePushNotifications\n ? `activity.runOnUiThread {\n if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU\n && ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {\n ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 4204)\n }\n try {\n FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->\n val token = if (task.isSuccessful) task.result else null\n val callback = if (token.isNullOrBlank()) \"window._craftPushReject\" else \"window._craftPushResolve\"\n val payload = JSONObject.quote(token ?: task.exception?.message ?: \"Firebase Cloud Messaging is not configured\")\n evaluatePromiseJavascript(\"$callback && $callback($payload)\")\n }\n } catch (error: Exception) {\n val payload = JSONObject.quote(error.message ?: \"Firebase Cloud Messaging is not configured\")\n evaluatePromiseJavascript(\"window._craftPushReject && window._craftPushReject($payload)\")\n }\n }`\n : `evaluatePromiseJavascript(\n \"window._craftPushReject && window._craftPushReject('Push notifications are disabled')\"\n )`)\n // Typed native screens have no WebView bridge or ML surface. Shipping its\n // otherwise unreachable OCR models added ~100 MB of native libraries.\n const bridgeFile = join(output, 'app/src/main/java', packagePath, 'CraftBridge.kt')\n if (config.renderer === 'native') rmSync(bridgeFile, { force: true })\n else writeFileSync(bridgeFile, craftBridge)\n\n // CraftNative goes to a fixed package, not the app's. The prebuilt\n // libcraft.so binds its natives by class name in JNI_OnLoad, and it cannot\n // know a name chosen here — so this one file is deliberately not templated\n // and deliberately not under packagePath.\n let craftNative = readFileSync(join(TEMPLATES_DIR, 'CraftNative.kt.template'), 'utf-8')\n if (config.renderer === 'native') {\n craftNative = craftNative.replace(/^import com\\.google\\.mlkit\\..*\\n/gm, '')\n .replace(/ \\/\\/ CRAFT_WEB_ML_START[\\s\\S]*? \\/\\/ CRAFT_WEB_ML_END/, () =>\n // The fixed JNI holder keeps these callback signatures, even though\n // typed screens do not expose the WebView's machine-learning API.\n ['runImageClassification', 'runObjectDetection', 'runTextRecognition'].map(name =>\n ` @JvmStatic\\n fun ${name}(imageBase64: String) {\\n val (_, reject) = createMlSettlement()\\n reject(\"Machine learning is unavailable in the native renderer\")\\n }`).join('\\n\\n'))\n }\n const nativeDir = join(output, 'app/src/main/java/com/craft/runtime')\n mkdirSync(nativeDir, { recursive: true })\n writeFileSync(join(nativeDir, 'CraftNative.kt'), craftNative)\n // The bridge and native holder both reference the recording store/service,\n // even when the service is not registered in the manifest. Keep these\n // support types in the same fixed package as CraftNative so every generated\n // app compiles regardless of its chosen package name or feature flags.\n const serviceTemplate = readFileSync(join(TEMPLATES_DIR, 'LocationRecordingService.kt.template'), 'utf-8')\n writeFileSync(join(nativeDir, 'LocationRecordingService.kt'), serviceTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName))\n const healthTemplate = readFileSync(join(\n TEMPLATES_DIR,\n config.enableHealthConnect ? 'CraftHealthConnect.kt.template' : 'CraftHealthConnectStub.kt.template',\n ), 'utf-8')\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftHealthConnect.kt'),\n healthTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n // The heart-rate strap service, in every app as iOS has CraftHeartRate.swift\n // in every app: the page's bridge and the native screens' services refer to\n // it. Only `enableHeartRate` registers it, declares its service and asks\n // for Bluetooth.\n for (const [template, file] of [['CraftHeartRateCore.kt.template', 'CraftHeartRateCore.kt'], ['CraftHeartRate.kt.template', 'CraftHeartRate.kt']]) {\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, file!),\n readFileSync(join(TEMPLATES_DIR, template!), 'utf8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n }\n // Create AndroidManifest.xml\n const manifestTemplate = readFileSync(join(TEMPLATES_DIR, 'AndroidManifest.xml.template'), 'utf-8')\n const manifest = manifestTemplate\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n .replace(/\\{\\{PERMISSIONS\\}\\}/g, renderAndroidPermissions(config))\n // Plain HTTP only for a local dev server, or an app that talks to the\n // person's own devices on the LAN (which have no public certificate).\n .replace(/\\{\\{USES_CLEARTEXT\\}\\}/g, config.devServerURL?.startsWith('http://') || config.enableLocalNetwork ? 'true' : 'false')\n .replace(/\\{\\{DEEP_LINK_INTENT_FILTERS\\}\\}/g, renderAndroidDeepLinks(config))\n .replace(/\\{\\{BACKGROUND_SERVICE\\}\\}/g, config.enableBackgroundLocation\n ? ' <service android:name=\"com.craft.runtime.LocationRecordingService\" android:exported=\"false\" android:foregroundServiceType=\"location\" android:stopWithTask=\"false\" />'\n : '')\n .replace(/\\{\\{HEART_RATE_SERVICE\\}\\}/g, config.enableHeartRate\n ? ' <service android:name=\".CraftHeartRateService\" android:exported=\"false\" android:foregroundServiceType=\"connectedDevice\" />'\n : '')\n .replace(/\\{\\{HEALTH_SERVICES_SERVICE\\}\\}/g, config.enableHealthServices\n ? ' <service android:name=\".CraftHealthServicesService\" android:exported=\"false\" android:foregroundServiceType=\"health\" android:stopWithTask=\"false\" />'\n : '')\n .replace(/\\{\\{NATIVE_NOTIFICATION_RECEIVER\\}\\}/g, config.renderer === 'native'\n ? renderNativeShellManifest(config)\n : '')\n // Starts the crash reporter before Application.onCreate, for every way\n // the process starts (CraftCrashReporter.kt). Inert without a key.\n .replace(/\\{\\{CRASH_REPORTER_PROVIDER\\}\\}/g, ` <provider android:name=\".CraftCrashReporterInit\" android:authorities=\"\\${applicationId}.craft-crash\" android:exported=\"false\" android:initOrder=\"1000\" />`)\n .replace(/\\{\\{GOOGLE_MAPS_API_KEY\\}\\}/g, config.mapProvider !== 'maplibre' && config.mapsApiKey\n ? ` <meta-data android:name=\"com.google.android.geo.API_KEY\" android:value=\"${escapeXml(config.mapsApiKey)}\" />`\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_QUERIES\\}\\}/g, config.enableHealthConnect\n ? ' <queries>\\n <package android:name=\"com.google.android.apps.healthdata\" />\\n </queries>'\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_RATIONALE\\}\\}/g, config.enableHealthConnect\n ? ` <intent-filter>\n <action android:name=\"androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE\" />\n </intent-filter>${config.renderer === 'native' ? '' : `\n <intent-filter>\n <action android:name=\"android.intent.action.VIEW_PERMISSION_USAGE\" />\n <category android:name=\"android.intent.category.HEALTH_PERMISSIONS\" />\n </intent-filter>`}`\n : '')\n\n writeFileSync(join(output, 'app/src/main/AndroidManifest.xml'), manifest)\n\n // Create build.gradle.kts (project level)\n const projectGradleTemplate = readFileSync(join(TEMPLATES_DIR, 'build.gradle.kts.project.template'), 'utf-8')\n writeFileSync(join(output, 'build.gradle.kts'), projectGradleTemplate\n .replace(/\\{\\{GOOGLE_SERVICES_PLUGIN\\}\\}/g, hasGoogleServices ? ' id(\"com.google.gms.google-services\") version \"4.4.2\" apply false' : ''))\n\n // Create build.gradle.kts (app level)\n const appGradleTemplate = readFileSync(join(TEMPLATES_DIR, 'build.gradle.kts.app.template'), 'utf-8')\n const appGradle = appGradleTemplate\n .replace(/\\{\\{MACHINE_LEARNING_DEPENDENCIES\\}\\}/g, config.renderer === 'native' ? '' : [\n 'barcode-scanning:17.3.0', 'image-labeling:17.0.9', 'object-detection:17.0.2', 'text-recognition:16.0.1',\n ].map(module => ` implementation(\"com.google.mlkit:${module}\")`).join('\\n'))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{VERSION_NAME\\}\\}/g, escapeKotlinString(config.version || '1.0.0'))\n .replace(/\\{\\{VERSION_CODE\\}\\}/g, String(config.versionCode || 1))\n .replace(/\\{\\{MIN_SDK\\}\\}/g, String(config.minSdk ?? ANDROID_MIN_SDK))\n .replace(/\\{\\{COMPILE_SDK\\}\\}/g, String(config.compileSdk || 36))\n .replace(/\\{\\{TARGET_SDK\\}\\}/g, String(config.targetSdk || 35))\n .replace(/\\{\\{GOOGLE_SERVICES_PLUGIN\\}\\}/g, hasGoogleServices ? ' id(\"com.google.gms.google-services\")' : '')\n .replace(/\\{\\{FIREBASE_MESSAGING_DEPENDENCY\\}\\}/g, config.enablePushNotifications\n ? ' implementation(\"com.google.firebase:firebase-messaging:24.1.0\")'\n : '')\n .replace(/\\{\\{REFRESH_LAYOUT_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ' implementation(\"androidx.swiperefreshlayout:swiperefreshlayout:1.1.0\")'\n : '')\n .replace(/\\{\\{NATIVE_MAP_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ` // Native STX Map overlays and trail routes\\n implementation(\"${androidMapHost(config.mapProvider).dependency}\")`\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_DEPENDENCIES\\}\\}/g, config.enableHealthConnect\n ? ` implementation(\"androidx.health.connect:connect-client:1.1.0\")\n implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1\")`\n : '')\n .replace(/\\{\\{HEALTH_SERVICES_DEPENDENCIES\\}\\}/g, config.enableHealthServices\n ? ' implementation(\"androidx.health:health-services-client:1.1.0\")'\n : '')\n .replace(/\\{\\{WALLET_DEPENDENCY\\}\\}/g, config.enableWallet\n ? ' // Native Google Wallet save flow for signed pass JWTs\\n implementation(\"com.google.android.gms:play-services-pay:16.5.0\")'\n : '')\n .replace(/\\{\\{JAVASCRIPT_ENGINE_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ` implementation(\"androidx.javascriptengine:javascriptengine:1.1.0\")\n // Native background refresh (WorkManager).\n implementation(\"androidx.work:work-runtime-ktx:2.9.1\")`\n : '')\n\n writeFileSync(join(output, 'app/build.gradle.kts'), appGradle)\n const proguardTemplate = readFileSync(join(TEMPLATES_DIR, 'proguard-rules.pro.template'), 'utf-8')\n writeFileSync(\n join(output, 'app/proguard-rules.pro'),\n proguardTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n\n // Create settings.gradle.kts\n const settingsTemplate = readFileSync(join(TEMPLATES_DIR, 'settings.gradle.kts.template'), 'utf-8')\n const settings = settingsTemplate.replace(\n /\\{\\{APP_NAME\\}\\}/g,\n escapeKotlinString(generatedGradleProjectName(name)),\n )\n writeFileSync(join(output, 'settings.gradle.kts'), settings)\n\n // Create gradle.properties\n const gradleProperties = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\nandroid.useAndroidX=true\nkotlin.code.style=official\nandroid.nonTransitiveRClass=true\n`\n writeFileSync(join(output, 'gradle.properties'), gradleProperties)\n\n // Create local.properties placeholder\n writeFileSync(join(output, 'local.properties'), '# SDK location will be set by Android Studio\\n')\n\n // Create gradle wrapper properties\n const gradleWrapperProps = `distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\\\://services.gradle.org/distributions/gradle-8.11.1-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n`\n writeFileSync(join(output, 'gradle/wrapper/gradle-wrapper.properties'), gradleWrapperProps)\n\n // Create res/values files\n const stringsXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"app_name\">${escapeXml(name)}</string>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/strings.xml'), stringsXml)\n\n const colorsXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"primary\">#1a1a2e</color>\n <color name=\"primary_dark\">#16162b</color>\n <color name=\"accent\">#4ade80</color>\n <color name=\"background\">${config.backgroundColor}</color>\n <!-- Transparent is NotificationCompat's COLOR_DEFAULT: the system picks. -->\n <color name=\"craft_notification_color\">${config.notificationColor ?? '#00000000'}</color>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/colors.xml'), colorsXml)\n const darkColorsPath = join(output, 'app/src/main/res/values-night/colors.xml')\n if (config.backgroundColorDark) {\n writeFileSync(darkColorsPath, `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"background\">${config.backgroundColorDark}</color>\n</resources>\n`)\n }\n else {\n rmSync(darkColorsPath, { force: true })\n }\n\n const appIconXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"108dp\"\n android:height=\"108dp\"\n android:viewportWidth=\"108\"\n android:viewportHeight=\"108\">\n <path android:fillColor=\"${config.backgroundColor}\" android:pathData=\"M0,0h108v108h-108z\" />\n <path android:fillColor=\"#10B981\" android:pathData=\"M18,78L42,42l12,18l12,-12l24,30z\" />\n</vector>\n`\n if (config.appIconPath) {\n cpSync(\n config.appIconPath,\n join(output, `app/src/main/res/drawable/craft_app_icon${appIconExtension}`),\n )\n }\n else {\n writeFileSync(join(output, 'app/src/main/res/drawable/craft_app_icon.xml'), appIconXml)\n }\n // Android draws a notification icon's alpha only, so it has its own white\n // glyph: the launcher icon there is a white square.\n for (const extension of ['.png', '.xml']) rmSync(join(output, `app/src/main/res/drawable/craft_notification_icon${extension}`), { force: true })\n if (config.notificationIconPath) {\n cpSync(config.notificationIconPath, join(output, `app/src/main/res/drawable/craft_notification_icon${notificationIconExtension}`))\n }\n else {\n writeFileSync(join(output, 'app/src/main/res/drawable/craft_notification_icon.xml'), `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"24dp\"\n android:height=\"24dp\"\n android:viewportWidth=\"108\"\n android:viewportHeight=\"108\">\n <path android:fillColor=\"#FFFFFFFF\" android:pathData=\"M18,78L42,42l12,18l12,-12l24,30z\" />\n</vector>\n`)\n }\n\n const themesXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <style name=\"Theme.CraftApp\" parent=\"Theme.Material3.DayNight.NoActionBar\">\n <item name=\"android:statusBarColor\">@color/primary_dark</item>\n <item name=\"android:navigationBarColor\">@color/primary</item>\n <item name=\"android:windowBackground\">@color/background</item>\n </style>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/themes.xml'), themesXml)\n\n // Create activity_main.xml\n const activityMainXml = config.renderer === 'native'\n ? `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:id=\"@+id/native_root\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\" />\n`\n : `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\"\n android:fitsSystemWindows=\"true\">\n\n <WebView\n android:id=\"@+id/webview\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\" />\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>\n`\n writeFileSync(join(output, 'app/src/main/res/layout/activity_main.xml'), activityMainXml)\n\n syncNativeFonts(config.nativeFonts, output)\n\n // Create placeholder index.html\n const placeholderHtml = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n <title>${escapeXml(name)}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: 'Roboto', sans-serif;\n background: ${config.backgroundColor};\n color: white;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .container { text-align: center; padding: 2rem; }\n h1 { font-size: 2.5rem; margin-bottom: 1rem; }\n p { opacity: 0.7; }\n .ready { color: #4ade80; font-size: 0.9rem; margin-top: 2rem; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>⚡ ${escapeXml(name)}</h1>\n <p>Built with Craft Android</p>\n <p class=\"ready\" id=\"status\">Waiting for Craft bridge...</p>\n </div>\n <script>\n window.addEventListener('craftReady', (e) => {\n document.getElementById('status').textContent = \\`✓ Craft bridge ready (platform: \\${e.detail.platform})\\`;\n console.log('Craft capabilities:', e.detail.capabilities);\n });\n </script>\n</body>\n</html>`\n\n writeFileSync(join(output, 'app/src/main/assets/index.html'), placeholderHtml)\n\n // The Zig runtime, when one was configured. Absent, the generated app is the\n // Kotlin shim and behaves exactly as it always has — which is the fallback\n // `CraftNative` was written for, not a failure.\n const runtimeDir = resolveRuntimeDir(options.runtimeDir)\n if (runtimeDir) {\n installRuntime(output, runtimeDir)\n console.log(' Installed the Zig runtime from', runtimeDir)\n }\n\n console.log('✅ Project initialized')\n console.log('')\n console.log('Next steps:')\n console.log(` 1. cd ${output}`)\n if (config.renderer === 'native') {\n console.log(' 2. Compile your screen: stx native compile Screen.stx --format bundle --output screen.js')\n console.log(' 3. Run: craft android build --native-bundle screen.js')\n }\n else {\n console.log(' 2. Add your web content to app/src/main/assets/index.html')\n console.log(' 3. Run: craft android build')\n }\n console.log(' 4. Run: craft android open')\n console.log('')\n}\n\n/**\n * Build Android project\n */\nexport async function build(options: BuildOptions): Promise<void> {\n const { htmlPath, nativeBundlePath, devServer, output, release, bundle, compile = true } = options\n\n console.log('\\n📦 Building Craft Android project...')\n\n // Load config\n const configPath = join(output, 'craft.config.json')\n if (!existsSync(configPath)) {\n throw new Error(`No craft.config.json found in ${output}. Run 'craft android init' first.`)\n }\n\n const config: CraftAndroidConfig = JSON.parse(readFileSync(configPath, 'utf-8'))\n validateAndroidConfig(config)\n validateNativeRouteConfig(config)\n\n if (config.renderer === 'native') {\n if (htmlPath || devServer) throw new Error('A native Android screen cannot use --html-path or --dev-server.')\n const destination = join(output, 'app/src/main/assets/native-screen.js')\n const routeDestination = join(output, 'app/src/main/assets/native-screens')\n if (nativeBundlePath) {\n // One file, or a directory of route bundles (stx's routesDir); each\n // replaces the other, since a route's own file wins at runtime.\n if (!existsSync(nativeBundlePath)) throw new Error(`Native bundle not found: ${nativeBundlePath}`)\n if (statSync(nativeBundlePath).isDirectory()) {\n if (resolve(nativeBundlePath) !== resolve(routeDestination)) {\n rmSync(routeDestination, { recursive: true, force: true })\n cpSync(nativeBundlePath, routeDestination, { recursive: true })\n compressNativeSources(routeDestination)\n }\n rmSync(destination, { force: true })\n }\n else {\n if (resolve(nativeBundlePath) !== resolve(destination)) cpSync(nativeBundlePath, destination)\n compressNativeSources(destination)\n rmSync(routeDestination, { recursive: true, force: true })\n }\n }\n const icons = join(output, 'app/src/main/assets/craft-icons.json')\n if (options.iconsPath) {\n requireRegularFile(options.iconsPath, 'Icon table')\n if (resolve(options.iconsPath) !== resolve(icons)) cpSync(options.iconsPath, icons)\n }\n if (!existsSync(destination) && !existsSync(routeDestination)) {\n throw new Error('Native Android mode needs app/src/main/assets/native-screen.js. Compile a .stx screen with `stx native compile` first.')\n }\n }\n else if (nativeBundlePath) {\n throw new Error('--native-bundle requires renderer: \"native\" in craft.config.json.')\n }\n\n // Refresh the runtime the same way the iOS builder does: only for a project\n // that already has one, so `craft android build` in a shim-only project does\n // not quietly acquire a native library it was never generated with.\n if (existsSync(join(output, 'app/src/main/jniLibs'))) {\n const runtimeDir = resolveRuntimeDir(options.runtimeDir)\n if (runtimeDir) {\n installRuntime(output, runtimeDir)\n console.log(' Refreshed the Zig runtime from', runtimeDir)\n }\n else {\n console.log(' Keeping the Zig runtime installed at init (no runtime directory configured)')\n }\n }\n\n // Update dev server URL if provided\n if (devServer) {\n const url = androidWebUrl(devServer, 'Android dev server URL')\n config.devServerURL = url.toString()\n config.trustedOrigins = [...new Set([\n ...(config.trustedOrigins ?? []).map(value => androidWebUrl(value, 'Android trusted origin').origin),\n url.origin,\n ])]\n writeAndroidConfig(output, config)\n console.log(` Dev server: ${devServer}`)\n }\n\n // Copy the complete web application if provided.\n if (htmlPath) {\n syncAndroidWebAssets(htmlPath, output)\n config.hasBundledFallback = Boolean(devServer)\n writeAndroidConfig(output, config)\n console.log(` Synced: ${htmlPath} → assets/`)\n }\n\n syncNativeFonts(config.nativeFonts, output)\n\n runPostGenerateHook(config.postGenerate, output)\n\n if (!compile) return\n\n // Check if gradlew exists\n const gradlewPath = join(output, 'gradlew')\n if (!existsSync(gradlewPath)) {\n console.log(' Generating Gradle wrapper...')\n try {\n await $`cd ${output} && gradle wrapper`.quiet()\n }\n catch (error) {\n throw new Error('Gradle is unavailable. Install Android Studio or Gradle before building Android.', { cause: error })\n }\n }\n\n // Build the project\n const variant = release ? 'Release' : 'Debug'\n const buildType = `${bundle ? 'bundle' : 'assemble'}${variant}`\n console.log(` Building ${release ? 'release' : 'debug'} ${bundle ? 'app bundle' : 'APK'}...`)\n if (release && !process.env.CRAFT_ANDROID_KEYSTORE)\n console.log(' CRAFT_ANDROID_KEYSTORE is not set: the release build is unsigned.')\n\n try {\n await $`cd ${output} && ./gradlew ${buildType}`\n const artifact = bundle\n ? `app/build/outputs/bundle/${variant.toLowerCase()}/app-${variant.toLowerCase()}.aab`\n : release\n ? 'app/build/outputs/apk/release/app-release.apk'\n : 'app/build/outputs/apk/debug/app-debug.apk'\n console.log(`✅ ${bundle ? 'App bundle' : 'APK'} built: ${artifact}`)\n }\ncatch (error) {\n console.error('Build failed. Open in Android Studio for details.')\n throw error\n }\n\n console.log('')\n}\n\n/**\n * Open Android project in Android Studio\n */\nexport async function open(options: OpenOptions): Promise<void> {\n const { output } = options\n\n if (!existsSync(output)) {\n throw new Error(`No Android project found in ${output}. Run 'craft android init' first.`)\n }\n\n console.log(`🚀 Opening Android project in Android Studio...`)\n\n // Try to open with Android Studio\n try {\n // macOS\n await $`open -a \"Android Studio\" ${output}`.quiet()\n }\ncatch {\n try {\n // Linux\n await $`studio ${output}`.quiet()\n }\ncatch {\n console.log('⚠️ Android Studio not found.')\n console.log(' Please open the project manually in Android Studio:')\n console.log(` ${output}`)\n }\n }\n}\n\n/**\n * Run on Android device or emulator\n */\nexport async function run(options: RunOptions): Promise<void> {\n const { device, output } = options\n\n // First build\n await build({ output })\n\n // Install and run\n console.log('📱 Installing and running on device...')\n\n try {\n const apkPath = join(output, 'app/build/outputs/apk/debug/app-debug.apk')\n\n if (device) {\n await $`adb -s ${device} install -r ${apkPath}`\n }\nelse {\n await $`adb install -r ${apkPath}`\n }\n\n // Get package name from config\n const config: CraftAndroidConfig = JSON.parse(\n readFileSync(join(output, 'craft.config.json'), 'utf-8')\n )\n\n // Launch the app\n const launchCmd = `${config.packageName}/.MainActivity`\n if (device) {\n await $`adb -s ${device} shell am start -n ${launchCmd}`\n }\nelse {\n await $`adb shell am start -n ${launchCmd}`\n }\n\n console.log('✅ App launched')\n }\ncatch (error) {\n console.error('Failed to install/run. Make sure:')\n console.error(' 1. ADB is installed and in PATH')\n console.error(' 2. A device/emulator is connected (run: adb devices)')\n throw error\n }\n}\n",
5
+ "import { gzipSync } from 'node:zlib'\n/**\n * Craft Android Builder\n *\n * Generates Android apps with native Craft components and optional WebView content.\n */\n\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs'\n\n/** Store large native source assets compressed; the host decodes each once on demand. */\nexport function compressNativeSources(target: string): void {\n if (statSync(target).isDirectory()) {\n for (const entry of readdirSync(target)) compressNativeSources(join(target, entry))\n return\n }\n if (!/\\.(?:js|json)$/.test(target)) return\n const bytes = readFileSync(target)\n if (bytes.length < 1024 || (bytes[0] === 0x1f && bytes[1] === 0x8b)) return\n const packed = gzipSync(bytes, { level: 9 })\n if (packed.length < bytes.length) writeFileSync(target, packed)\n}\nimport { dirname, extname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport { $ } from 'bun'\nimport { androidMapHost, type AndroidMapProvider } from './native-map.js'\nimport { renderAndroidPromiseRuntime } from './promise-runtime'\n\nexport type { AndroidMapProvider } from './native-map.js'\n/**\n * The builder installs a directory of route bundles (stx's `routesDir`) as\n * well as the one-file bundle, and the app runs each screen from its own\n * route's file. Stacks asks for route bundles only when this is true.\n */\n/** Build-time proof for Stacks capability mappings, including unreleased source builds. */\nexport const nativeSensorCapabilities = ['motionSensors', 'barometer', 'pedometer'] as const\n\nexport const nativeRouteBundles = true\n\n/**\n * The app evaluates stx's shared runtime (`__runtime.js`, stx's\n * `sharedRuntime`) in each screen's context before the route's own file.\n * Stacks asks stx for it only when this is true: a route file built so\n * refuses to run without it.\n */\nexport const nativeRouteRuntime = true\n\n/**\n * The app gives a screen its messages a language at a time (stx's\n * `messages`, `native-screens/__messages/`): the areas its route uses,\n * evaluated ahead of it (an isolate cannot read a file when asked). Stacks leaves the languages\n * out of the screens' code only when this is true.\n */\nexport const nativeMessages = true\n\n/** Providers this published builder can generate as real Android map views. */\nexport const nativeMapProviders = ['google', 'maplibre'] as const\nexport { runKotlinFixture } from './testing.js'\nexport { createAndroidEmulator } from './emulator.js'\nexport type { AndroidEmulatorOptions, AndroidEmulatorSession } from './emulator.js'\n\n/** Package custom fonts and their licenses; removed fonts cannot linger in the app. */\nexport function syncNativeFonts(fonts: CraftAndroidConfig['nativeFonts'], output: string): string[] {\n const destination = join(output, 'app/src/main/assets/NativeFonts')\n const names = new Set<string>()\n const files = Object.entries(fonts ?? {}).map(([family, entry]) => {\n if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(family))\n throw new Error(`Invalid native font PostScript name: ${family}`)\n if (names.has(family.toLowerCase())) throw new Error(`Duplicate native font name: ${family}`)\n names.add(family.toLowerCase())\n if ([entry.src, entry.license].some(file => file && resolve(file).startsWith(resolve(destination) + sep)))\n throw new Error('Native font sources must be outside the generated NativeFonts directory')\n const extension = extname(entry.src).toLowerCase()\n if (!['.ttf', '.otf'].includes(extension) || !existsSync(entry.src) || !statSync(entry.src).isFile())\n throw new Error(`Native font ${family} must reference an existing TTF or OTF file: ${entry.src}`)\n if (entry.license && (!existsSync(entry.license) || !statSync(entry.license).isFile()))\n throw new Error(`Native font license not found: ${entry.license}`)\n return { family, ...entry, filename: `${family}${extension}` }\n })\n rmSync(destination, { recursive: true, force: true })\n if (!files.length) return []\n mkdirSync(destination, { recursive: true })\n for (const file of files) {\n cpSync(file.src, join(destination, file.filename))\n if (file.license) cpSync(file.license, join(destination, `${file.family}.LICENSE.txt`))\n }\n return files.map(file => `NativeFonts/${file.filename}`)\n}\n\nconst TEMPLATES_DIR = join(dirname(import.meta.dir), 'templates')\n\n/**\n * This builder's version, which the crash reporter names as its SDK version.\n * Walks up from here because a bundled build puts this module below the\n * package root.\n */\nfunction resolveCraftAndroidVersion(startDir: string = import.meta.dir): string {\n let directory = resolve(startDir)\n while (true) {\n try {\n const pkg = JSON.parse(readFileSync(join(directory, 'package.json'), 'utf8')) as { name?: unknown, version?: unknown }\n if ((pkg.name === '@craft-native/android' || pkg.name === 'craft-native') && typeof pkg.version === 'string' && pkg.version)\n return pkg.version\n }\n catch {\n // Keep walking.\n }\n const parent = dirname(directory)\n if (parent === directory) return '0.0.0'\n directory = parent\n }\n}\n\nconst CRAFT_ANDROID_VERSION = resolveCraftAndroidVersion()\nconst LOCAL_DEVELOPMENT_HOSTS = new Set(['localhost', '127.0.0.1', '10.0.2.2'])\nconst KOTLIN_KEYWORDS = new Set([\n 'as',\n 'break',\n 'class',\n 'continue',\n 'do',\n 'else',\n 'false',\n 'for',\n 'fun',\n 'if',\n 'in',\n 'interface',\n 'is',\n 'null',\n 'object',\n 'package',\n 'return',\n 'super',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typealias',\n 'typeof',\n 'val',\n 'var',\n 'when',\n 'while',\n])\n\n/** Oldest Android API level supported by the generated Kotlin runtime. */\nexport const ANDROID_MIN_SDK = 26\nconst ANDROID_HEALTH_SERVICES_MIN_SDK = 30\n\nexport interface CraftAndroidConfig {\n /** Bundled font files keyed by their PostScript font name, used as native fontFamily. */\n nativeFonts?: Record<string, { src: string, license?: string }>\n\n appName: string\n packageName: string\n renderer?: 'web' | 'native'\n /** \"system\" follows the device; light/dark pin the generated host. */\n appearance?: 'light' | 'dark' | 'system'\n /** Static native tab-bar styling applied before the page's own tabBar.set call. */\n tabBar?: CraftTabBarConfig\n /** Runs from the generated project root before Gradle compiles the app. */\n postGenerate?: CraftPostGenerateHook\n version?: string\n versionCode?: number\n darkMode?: boolean\n backgroundColor?: string\n backgroundColorDark?: string\n enableSpeechRecognition?: boolean\n enableAudioRecording?: boolean\n enableHaptics?: boolean\n enableShare?: boolean\n enableCamera?: boolean\n enableBiometric?: boolean\n enablePushNotifications?: boolean\n /** Enable native SQLite queries and transactions. Disabled unless explicitly true. */\n enableLocalDatabase?: boolean\n /** Enable native AlarmManager local notification scheduling. Disabled unless explicitly true. */\n enableLocalNotifications?: boolean\n enableSecureStorage?: boolean\n enableGeolocation?: boolean\n enableBackgroundLocation?: boolean\n /** Foreground raw Android sensors on native screens; separate from iOS fused motion. */\n enableMotionSensors?: boolean\n /** Foreground pressure and session-relative altitude; does not enable background recording. */\n enableBarometer?: boolean\n /** Foreground hardware step counters/detectors; requires activity recognition on Android 10+. */\n enablePedometer?: boolean\n enableBluetooth?: boolean\n /**\n * A Bluetooth heart-rate strap, or a watch broadcasting its heart rate (the\n * standard Heart Rate Service), through `craft.heartRate` on a page and the\n * `HeartRate` module on a native screen (CraftHeartRate.kt): scan, connect,\n * live readings as `craftHeartRate` events, and a recording kept natively,\n * in the foreground (a connectedDevice service) while it runs. The iOS\n * builder's flag of the same name.\n */\n enableHeartRate?: boolean\n enableHealthConnect?: boolean\n /** Android Health Services live exercise tracking for native screens. Requires minSdk 30. */\n enableHealthServices?: boolean\n /** Google Wallet save-link or native SDK handoff for native screens. */\n enableWallet?: boolean\n /**\n * The Health Connect data the app reads and writes, by the shared type\n * names (`steps`, `sleep`, `workouts`...). The manifest declares only\n * these, as Play's health permissions review requires; without it, the\n * original set (steps, heart rate, energy, distance, workouts).\n */\n healthConnect?: {\n read?: HealthConnectType[]\n write?: HealthConnectType[]\n /** Read while the app is in the background (a WorkManager refresh): Android 15's READ_HEALTH_DATA_IN_BACKGROUND. */\n background?: boolean\n /** Read further back than the 30 days before the first grant: READ_HEALTH_DATA_HISTORY. */\n history?: boolean\n }\n enableHealthConnectBackground?: boolean\n enableHealthConnectHistory?: boolean\n /** The app's privacy policy, which Health Connect links to from its permission screen. */\n privacyPolicyURL?: string\n enableKeepAwake?: boolean\n enableDeepLinks?: boolean\n /** Reach the person's own devices on the local network over plain HTTP (a Mac companion). */\n enableLocalNetwork?: boolean\n urlSchemes?: string[]\n /** HTTPS hosts owned by the app; path rules are ordered, with `*` matching any path text. */\n /** Ordered path rules: * matches zero or more characters, ? one, and ?* one or more. */\n appLinks?: Array<{ host: string, paths?: Array<{ pattern: string, exclude?: boolean }> }>\n trustedOrigins?: string[]\n appIconPath?: string\n /**\n * The small icon in the status bar and on every notification the app\n * shows, push or local: an Android vector drawable (`.xml`) or a `.png`,\n * white on transparent, since Android draws only its shape. Without one,\n * a white Craft mark. Never the launcher icon, which shows as a white\n * square.\n */\n notificationIconPath?: string\n /** The `#RRGGBB` Android tints the notification icon and app name with. The system's own colour without it. */\n notificationColor?: string\n googleServicesFile?: string\n /** Native map renderer. MapLibre needs no SDK key; Google remains the default for compatibility. */\n mapProvider?: AndroidMapProvider\n /** Google Maps Android SDK key, used only by the Google native map host. */\n mapsApiKey?: string\n devServerURL?: string\n hasBundledFallback?: boolean\n /** Android API level, at least ANDROID_MIN_SDK (26), or 30 with Health Services. */\n minSdk?: number\n compileSdk?: number\n targetSdk?: number\n /**\n * Native renderer: the app's paths and the screen drawing each\n * (`/m/workout/:id` → `Workout`), its tabs, and the bundle route of the\n * script that runs beside the screens. The same keys as the iOS builder.\n */\n nativeScreens?: Record<string, string>\n tabs?: Array<{\n id: string\n title: string\n symbol?: string\n /** Native selected-tab icon overrides, also supported by navigation.setOptions({ tabItem }). */\n selectedSymbol?: string\n selectedIconTint?: string\n selectedIconPulse?: boolean\n }>\n nativeApp?: string\n /**\n * The secure-storage key the signed-in account's token lives under\n * (default `auth.token`). `craft.session` follows it on every native\n * screen, and a change of it is `SESSION_CHANGED { key, token, previous }`.\n */\n sessionTokenKey?: string\n /** Wake the app script every so often (`craftBackgroundRefresh`), through WorkManager. */\n backgroundRefresh?: { enabled?: boolean, minimumIntervalMinutes?: number }\n /**\n * Crash and error reporting to bughq (CraftCrashReporter.kt): uncaught JVM\n * exceptions, ANRs and native crashes (ApplicationExitInfo), uncaught\n * JavaScript errors, and what the page sends through `craft.crashReporter`.\n * Queued on disk and sent when online. Release builds are minified: upload\n * `app/build/outputs/mapping/release/mapping.txt` so bughq can retrace.\n */\n crashReporting?: {\n /** The bughq project's public ingest key. */\n key: string\n /** Default https://bughq.org. */\n host?: string\n /** Default `production`. */\n environment?: string\n /** Default `<versionName>+<versionCode>`, e.g. `1.0.0+41`. */\n release?: string\n /** One session per launch, for crash-free sessions. Default on. */\n sessions?: boolean\n }\n}\n\nexport interface CraftTabBarConfig {\n selection?: {\n /** The selected tab indicator's corner radius in dp; omitted keeps the default. */\n cornerRadius?: number\n /** The selected tab indicator fill as #RRGGBB. */\n color?: string\n }\n}\n\n/** A declared command Craft runs after the native project has been generated. */\nexport interface CraftPostGenerateHook {\n command: string\n args?: string[]\n}\n\n/** The shared health data types (the iOS builder's HealthKit names). */\nexport type HealthConnectType = 'steps' | 'heartRate' | 'activeEnergy' | 'distance' | 'workouts' | 'restingHeartRate'\n | 'heartRateVariability' | 'bodyMass' | 'sleep' | 'mindful' | 'dietaryEnergy' | 'dietaryProtein'\n | 'dietaryCarbohydrates' | 'dietaryFat' | 'bloodGlucose' | 'insulinDelivery'\n\n/**\n * The Health Connect permissions behind each type, for reading and for\n * writing. CraftNativeHealth.kt asks for the same ones; a permission the\n * manifest does not declare is refused without a prompt.\n */\nexport const HEALTH_CONNECT_PERMISSIONS: Record<HealthConnectType, { read: string[], write: string[] }> = {\n steps: { read: ['READ_STEPS'], write: [] },\n heartRate: { read: ['READ_HEART_RATE'], write: [] },\n activeEnergy: { read: ['READ_ACTIVE_CALORIES_BURNED'], write: ['WRITE_ACTIVE_CALORIES_BURNED'] },\n distance: { read: ['READ_DISTANCE'], write: ['WRITE_DISTANCE'] },\n workouts: {\n read: ['READ_EXERCISE', 'READ_HEART_RATE', 'READ_ACTIVE_CALORIES_BURNED', 'READ_DISTANCE'],\n write: ['WRITE_EXERCISE', 'WRITE_ACTIVE_CALORIES_BURNED', 'WRITE_DISTANCE'],\n },\n restingHeartRate: { read: ['READ_RESTING_HEART_RATE'], write: [] },\n heartRateVariability: { read: ['READ_HEART_RATE_VARIABILITY'], write: [] },\n bodyMass: { read: ['READ_WEIGHT'], write: [] },\n sleep: { read: ['READ_SLEEP'], write: [] },\n mindful: { read: ['READ_MINDFULNESS'], write: ['WRITE_MINDFULNESS'] },\n dietaryEnergy: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryProtein: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryCarbohydrates: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n dietaryFat: { read: ['READ_NUTRITION'], write: ['WRITE_NUTRITION'] },\n bloodGlucose: { read: ['READ_BLOOD_GLUCOSE'], write: [] },\n // Health Connect has no insulin record; asking for it adds nothing.\n insulinDelivery: { read: [], write: [] },\n}\n\nconst DEFAULT_HEALTH_CONNECT = { read: ['steps', 'heartRate', 'activeEnergy', 'distance', 'workouts'], write: ['workouts'] } as const\n\n/** Every `android.permission.health.*` the app's Health Connect types need. */\nexport function healthConnectPermissions(config: Pick<CraftAndroidConfig, 'healthConnect'>): string[] {\n const read = config.healthConnect?.read ?? DEFAULT_HEALTH_CONNECT.read\n const write = config.healthConnect?.write ?? (config.healthConnect ? [] : DEFAULT_HEALTH_CONNECT.write)\n const permissions = new Set<string>()\n for (const type of read) {\n const known = HEALTH_CONNECT_PERMISSIONS[type as HealthConnectType]\n if (!known) throw new Error(`Unknown Health Connect type: ${type}`)\n known.read.forEach(permission => permissions.add(`android.permission.health.${permission}`))\n }\n for (const type of write) {\n const known = HEALTH_CONNECT_PERMISSIONS[type as HealthConnectType]\n if (!known) throw new Error(`Unknown Health Connect type: ${type}`)\n known.write.forEach(permission => permissions.add(`android.permission.health.${permission}`))\n }\n if (config.healthConnect?.background) permissions.add('android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND')\n if (config.healthConnect?.history) permissions.add('android.permission.health.READ_HEALTH_DATA_HISTORY')\n return [...permissions]\n}\n\nexport interface InitOptions {\n name: string\n packageName?: string\n output: string\n config?: Partial<CraftAndroidConfig>\n /**\n * Where to find the Zig runtime's `<abi>/libcraft.so`.\n *\n * `null` means no runtime regardless of the environment; `undefined` falls\n * through to `CRAFT_ANDROID_RUNTIME`. Same shape as the iOS builder's\n * `runtimeDir`.\n */\n runtimeDir?: string | null\n}\n\nexport interface BuildOptions {\n htmlPath?: string\n nativeBundlePath?: string\n /**\n * Native renderer: the app's icons as vectors (`{ viewBox, strokeWidth,\n * icons: { name: svgBody } }`, keyed by Iconify name and SF Symbol), which\n * `<Icon>`, the tab bar and the bar buttons draw. Without it they fall\n * back to the glyphs Android's fonts have.\n */\n iconsPath?: string\n devServer?: string\n output: string\n release?: boolean\n /**\n * An Android App Bundle (`bundleRelease`, `.aab`), what Google Play takes,\n * rather than an APK. Signed with CRAFT_ANDROID_KEYSTORE,\n * CRAFT_ANDROID_KEYSTORE_PASSWORD, CRAFT_ANDROID_KEY_ALIAS and\n * CRAFT_ANDROID_KEY_PASSWORD when they are set.\n */\n bundle?: boolean\n compile?: boolean\n /** Same meaning as `InitOptions.runtimeDir`; refreshes what init installed. */\n runtimeDir?: string | null\n}\n\n/**\n * Run the app's declared generator hook without invoking a shell.\n *\n * A hook gets the generated project as its cwd and explicit metadata so a\n * patch can target the right platform and phase without guessing from paths.\n */\nexport function runPostGenerateHook(\n hook: CraftPostGenerateHook | undefined,\n output: string,\n phase: 'build' = 'build',\n): void {\n if (!hook) return\n if (typeof hook.command !== 'string' || !hook.command.trim())\n throw new Error('Android postGenerate.command must be a non-empty executable')\n if (hook.args !== undefined && (!Array.isArray(hook.args) || hook.args.some(argument => typeof argument !== 'string')))\n throw new Error('Android postGenerate.args must be an array of strings')\n\n const command = [hook.command, ...(hook.args ?? [])]\n let result: ReturnType<typeof Bun.spawnSync>\n try {\n result = Bun.spawnSync(command, {\n cwd: output,\n env: { ...process.env, CRAFT_PROJECT_ROOT: output, CRAFT_PLATFORM: 'android', CRAFT_GENERATE_PHASE: phase },\n stdout: 'inherit',\n stderr: 'pipe',\n })\n }\n catch (error) {\n throw new Error(`Android postGenerate hook could not start in ${output}: ${hook.command}`, { cause: error })\n }\n if (result.exitCode !== 0) {\n const stderr = result.stderr?.toString().trim()\n throw new Error(`Android postGenerate hook failed in ${output} with exit code ${result.exitCode}${stderr ? `: ${stderr}` : ''}`)\n }\n}\n\nexport interface OpenOptions {\n output: string\n}\n\nexport interface RunOptions {\n device?: string\n output: string\n}\n\nconst DEFAULT_CONFIG: Omit<CraftAndroidConfig, 'appName' | 'packageName'> = {\n renderer: 'web',\n version: '1.0.0',\n versionCode: 1,\n darkMode: true,\n backgroundColor: '#0b1712',\n enableSpeechRecognition: false,\n enableAudioRecording: false,\n enableHaptics: false,\n enableShare: false,\n enableCamera: false,\n enableBiometric: false,\n enablePushNotifications: false,\n enableSecureStorage: false,\n enableGeolocation: false,\n enableBackgroundLocation: false,\n enableMotionSensors: false,\n enableBarometer: false,\n enablePedometer: false,\n enableBluetooth: false,\n enableHeartRate: false,\n enableHealthConnect: false,\n enableHealthServices: false,\n enableWallet: false,\n enableKeepAwake: false,\n enableDeepLinks: false,\n urlSchemes: [],\n appLinks: [],\n trustedOrigins: [],\n minSdk: ANDROID_MIN_SDK,\n compileSdk: 36,\n targetSdk: 35,\n}\n\nfunction escapeXml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll('\\'', '&apos;')\n}\n\nfunction escapeKotlinString(value: string): string {\n return value\n .replaceAll('\\\\', '\\\\\\\\')\n .replaceAll('\"', '\\\\\"')\n .replaceAll('$', '\\\\$')\n .replaceAll('\\r', '\\\\r')\n .replaceAll('\\n', '\\\\n')\n}\n\nfunction generatedPackageSegment(name: string): string {\n const normalized = name.toLowerCase().replace(/[^a-z0-9_]/g, '')\n if (!normalized) return 'app'\n return /^[a-z_]/.test(normalized) ? normalized : `app${normalized}`\n}\n\nfunction generatedGradleProjectName(name: string): string {\n const invalidCharacters = ['/', '\\\\', ':', '<', '>', '\"', '?', '*', '|']\n const normalized = invalidCharacters.reduce(\n (value, character) => value.replaceAll(character, '-'),\n name,\n ).trim()\n return normalized || 'craft-app'\n}\n\nfunction requireRegularFile(path: string, label: string): void {\n if (!existsSync(path)) throw new Error(`${label} not found: ${path}`)\n if (!statSync(path).isFile()) throw new Error(`${label} must be a file: ${path}`)\n}\n\nfunction containsPath(parent: string, candidate: string): boolean {\n const relativePath = relative(parent, candidate)\n return relativePath === ''\n || (relativePath !== '..' && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath))\n}\n\nfunction validateGoogleServicesFile(path: string, packageName: string): void {\n requireRegularFile(path, 'Google services file')\n\n let document: {\n client?: Array<{\n client_info?: { android_client_info?: { package_name?: string } }\n }>\n }\n try {\n document = JSON.parse(readFileSync(path, 'utf8'))\n }\n catch (error) {\n throw new Error(`Google services file must contain valid JSON: ${path}`, { cause: error })\n }\n\n const matchingClient = document.client?.some((client) => {\n return client.client_info?.android_client_info?.package_name === packageName\n })\n if (!matchingClient) {\n throw new Error(`Google services file has no client for Android package ${packageName}: ${path}`)\n }\n}\n\nfunction androidWebUrl(value: string, field: string): URL {\n let url: URL\n try {\n url = new URL(value)\n }\n catch {\n throw new Error(`Invalid ${field}: ${value}`)\n }\n\n const localDevelopment = url.protocol === 'http:' && LOCAL_DEVELOPMENT_HOSTS.has(url.hostname)\n if ((url.protocol !== 'https:' && !localDevelopment) || url.username || url.password) {\n throw new Error(`${field} must use HTTPS or local HTTP without credentials: ${value}`)\n }\n return url\n}\n\nfunction normalizeAndroidNetworkConfig(config: CraftAndroidConfig): void {\n const schemes = config.urlSchemes?.map(value => value.trim().toLowerCase()) ?? []\n if (schemes.some(value => !/^[a-z][a-z0-9+.-]*$/.test(value))) {\n throw new Error('Android deep-link schemes must be valid URI schemes')\n }\n config.urlSchemes = [...new Set(schemes)]\n config.appLinks = (config.appLinks ?? []).map((link) => {\n const host = link.host.trim().toLowerCase()\n const parsed = new URL(`https://${host}`)\n if (!host || parsed.hostname !== host || parsed.port || parsed.username || parsed.password || parsed.pathname !== '/' || parsed.search || parsed.hash)\n throw new Error('Android App Links need a hostname without a scheme, port or path')\n for (const rule of link.paths ?? []) {\n if (!rule.pattern.startsWith('/') || /[\\x00-\\x1f]/.test(rule.pattern) || (rule.exclude !== undefined && typeof rule.exclude !== 'boolean'))\n throw new Error('Android App Link path rules need an absolute path pattern and a boolean exclude')\n }\n return { ...link, host }\n })\n if (new Set(config.appLinks.map(link => link.host)).size !== config.appLinks.length)\n throw new Error('Android App Link hosts must be unique')\n if (config.enableDeepLinks && config.urlSchemes.length === 0 && config.appLinks.length === 0) {\n throw new Error('Android deep links require at least one URL scheme or an App Link host')\n }\n\n const trustedOrigins = (config.trustedOrigins ?? []).map((value) => {\n return androidWebUrl(value, 'Android trusted origin').origin\n })\n if (config.devServerURL) {\n const devServer = androidWebUrl(config.devServerURL, 'Android dev server URL')\n config.devServerURL = devServer.toString()\n trustedOrigins.push(devServer.origin)\n }\n config.trustedOrigins = [...new Set(trustedOrigins)]\n}\n\nfunction validateAndroidConfig(config: CraftAndroidConfig): void {\n androidMapHost(config.mapProvider)\n if (!config.appName.trim()) throw new Error('Android app name must not be empty')\n if (config.renderer !== undefined && config.renderer !== 'web' && config.renderer !== 'native') {\n throw new Error(`Unknown Android renderer: ${config.renderer}. Expected web or native.`)\n }\n if (config.appearance !== undefined && !['light', 'dark', 'system'].includes(config.appearance)) {\n throw new Error(`Unknown Android appearance: ${config.appearance}. Expected light, dark, or system.`)\n }\n const selection = config.tabBar?.selection\n if (selection?.cornerRadius !== undefined && (!Number.isFinite(selection.cornerRadius) || selection.cornerRadius < 0))\n throw new Error('Android tabBar.selection.cornerRadius must be a finite non-negative number')\n if (selection?.color !== undefined && !/^#[0-9a-f]{6}$/i.test(selection.color))\n throw new Error('Android tabBar.selection.color must be a #RRGGBB color')\n\n const packageSegments = config.packageName.split('.')\n if (packageSegments.length < 2\n || packageSegments.some(segment => !/^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) || KOTLIN_KEYWORDS.has(segment))) {\n throw new Error(`Invalid Android package name: ${config.packageName}`)\n }\n\n if (!/^#(?:[\\dA-F]{3,4}|[\\dA-F]{6}|[\\dA-F]{8})$/i.test(config.backgroundColor ?? '')) {\n throw new Error(`Invalid Android background color: ${config.backgroundColor}`)\n }\n\n if (config.backgroundColorDark !== undefined && !config.backgroundColorDark.match(/^#[\\dA-F]{3,4}$|^#[\\dA-F]{6}$|^#[\\dA-F]{8}$/i)) {\n throw new Error(`Invalid Android dark background color: ${config.backgroundColorDark}`)\n }\n\n if (config.mapsApiKey !== undefined && !config.mapsApiKey.trim()) {\n throw new Error('Android mapsApiKey must not be empty')\n }\n\n for (const [name, value] of [\n ['versionCode', config.versionCode],\n ['minSdk', config.minSdk],\n ['compileSdk', config.compileSdk],\n ['targetSdk', config.targetSdk],\n ] as const) {\n if (!Number.isInteger(value) || Number(value) < 1) {\n throw new Error(`Android ${name} must be a positive integer`)\n }\n }\n\n if (Number(config.minSdk) < ANDROID_MIN_SDK) {\n throw new Error(`Android minSdk must be at least ${ANDROID_MIN_SDK} (Android 8.0) for the Craft runtime`)\n }\n if (config.enableHealthServices && Number(config.minSdk) < ANDROID_HEALTH_SERVICES_MIN_SDK) {\n throw new Error(`Android Health Services requires minSdk at least ${ANDROID_HEALTH_SERVICES_MIN_SDK} (Android 11)`)\n }\n if (Number(config.minSdk) > Number(config.targetSdk)) {\n throw new Error('Android minSdk must not exceed targetSdk')\n }\n if (Number(config.targetSdk) > Number(config.compileSdk)) {\n throw new Error('Android targetSdk must not exceed compileSdk')\n }\n}\n\nfunction normalizeNativeRoutePath(raw: unknown): string | null {\n if (typeof raw !== 'string') return null\n let path = raw\n const cut = path.search(/[?#]/)\n if (cut >= 0) path = path.slice(0, cut)\n if (!path.startsWith('/')) return null\n path = path.replace(/\\/{2,}/g, '/')\n if (path.length > 1 && path.endsWith('/')) path = path.slice(0, -1)\n return path\n}\n\nfunction nativeRouteSegments(path: string): string[] {\n return path === '/' ? [] : path.slice(1).split('/')\n}\n\nfunction matchesNativeRoute(nativeScreens: Record<string, string> | undefined, raw: string): boolean {\n const path = normalizeNativeRoutePath(raw)\n if (path === null) return false\n const parts = nativeRouteSegments(path)\n return Object.entries(nativeScreens ?? {}).some(([pattern, screen]) => {\n if (!screen) return false\n const normalized = normalizeNativeRoutePath(pattern)\n if (normalized === null) return false\n const route = nativeRouteSegments(normalized)\n for (let index = 0; index < route.length; index++) {\n const segment = route[index]\n if (segment === '*') return index === route.length - 1\n if (index >= parts.length) return false\n if (segment.startsWith(':')) {\n if (!parts[index]) return false\n }\n else if (segment !== parts[index]) return false\n }\n return route.length === parts.length\n })\n}\n\nfunction nativeStartPath(config: CraftAndroidConfig): string {\n if (!config.devServerURL) return '/'\n try {\n const url = new URL(config.devServerURL)\n return `${url.pathname || '/'}${url.search}`\n }\n catch {\n return '/'\n }\n}\n\nfunction validateNativeRouteConfig(config: CraftAndroidConfig): void {\n const screens = Object.entries(config.nativeScreens ?? {})\n for (const [pattern, screen] of screens) {\n if (normalizeNativeRoutePath(pattern) !== pattern || /[?#]/.test(pattern))\n throw new Error(`nativeScreens path \"${pattern}\" must be an absolute path with no query, hash or trailing slash.`)\n if (nativeRouteSegments(normalizeNativeRoutePath(pattern) ?? '/').slice(0, -1).includes('*'))\n throw new Error(`nativeScreens path \"${pattern}\" may only end in *.`)\n if (typeof screen !== 'string' || !/^[A-Za-z_$][\\w$-]*$/.test(screen))\n throw new Error(`nativeScreens screen \"${String(screen)}\" for \"${pattern}\" must be a screen name from the native bundle.`)\n }\n\n const ids = new Set<string>()\n for (const tab of config.tabs ?? []) {\n if (!tab || typeof tab.id !== 'string' || !tab.id || typeof tab.title !== 'string' || !tab.title)\n throw new Error('Each tab needs an id (its root path) and a title.')\n if (ids.has(tab.id)) throw new Error(`Tab \"${tab.id}\" is listed twice.`)\n ids.add(tab.id)\n }\n\n if (config.renderer === 'native' && screens.length > 0) {\n for (const id of ids) {\n if (!matchesNativeRoute(config.nativeScreens, id))\n throw new Error(`Tab \"${id}\" is not a nativeScreens path; with renderer: \"native\" every tab must be a native screen.`)\n }\n const start = nativeStartPath(config)\n if (!matchesNativeRoute(config.nativeScreens, start))\n throw new Error(`The start path \"${start}\" (from devServerURL) is not a nativeScreens path; with renderer: \"native\" the app must start on a native screen.`)\n }\n\n if (config.nativeApp !== undefined) {\n if (typeof config.nativeApp !== 'string' || !/^[A-Za-z_$][\\w$-]*$/.test(config.nativeApp))\n throw new Error(`nativeApp \"${String(config.nativeApp)}\" must be a route name from the native bundle.`)\n if (config.renderer !== 'native' && screens.length === 0)\n throw new Error('nativeApp runs in the native bundle; it needs nativeScreens or renderer: \"native\".')\n }\n}\n\nfunction writeAndroidConfig(output: string, config: CraftAndroidConfig): void {\n writeFileSync(join(output, 'craft.config.json'), JSON.stringify(config, null, 2))\n\n // Generator-only paths can reveal the developer machine's directory layout\n // and have no meaning to the installed app. Keep them in the project config\n // but never package them into the APK's assets.\n const runtimeConfig = { ...config }\n delete runtimeConfig.appIconPath\n delete runtimeConfig.notificationIconPath\n delete runtimeConfig.googleServicesFile\n writeFileSync(\n join(output, 'app/src/main/assets/craft.config.json'),\n JSON.stringify(runtimeConfig, null, 2),\n )\n}\n\nexport function syncAndroidWebAssets(source: string, output: string): void {\n const sourcePath = resolve(source)\n if (!existsSync(sourcePath)) throw new Error(`Web asset path not found: ${source}`)\n const sourceStat = statSync(sourcePath)\n if (!sourceStat.isDirectory() && !sourceStat.isFile()) {\n throw new Error(`Web asset path must be a file or directory: ${source}`)\n }\n\n const assetsDir = resolve(output, 'app/src/main/assets')\n if (containsPath(sourcePath, assetsDir) || containsPath(assetsDir, sourcePath)) {\n throw new Error(`Web asset source must not overlap generated asset directory: ${source}`)\n }\n if (sourceStat.isDirectory()) {\n requireRegularFile(join(sourcePath, 'index.html'), 'Web asset directory entry point')\n }\n\n const configPath = join(assetsDir, 'craft.config.json')\n const config = existsSync(configPath) ? readFileSync(configPath) : undefined\n rmSync(assetsDir, { recursive: true, force: true })\n mkdirSync(assetsDir, { recursive: true })\n if (sourceStat.isDirectory()) cpSync(sourcePath, assetsDir, { recursive: true })\n else cpSync(sourcePath, join(assetsDir, 'index.html'))\n if (!existsSync(join(assetsDir, 'index.html'))) throw new Error(`Web asset directory must contain index.html: ${source}`)\n if (config) writeFileSync(configPath, config)\n}\n\nexport function renderAndroidPermissions(config: CraftAndroidConfig): string {\n const permissions = new Set(['android.permission.INTERNET', 'android.permission.ACCESS_NETWORK_STATE'])\n if (config.enableSpeechRecognition || config.enableAudioRecording) permissions.add('android.permission.RECORD_AUDIO')\n if (config.enableCamera) permissions.add('android.permission.CAMERA')\n if (config.enableHaptics) permissions.add('android.permission.VIBRATE')\n if (config.enableBiometric) permissions.add('android.permission.USE_BIOMETRIC')\n if (config.enableGeolocation || config.enableBackgroundLocation) {\n permissions.add('android.permission.ACCESS_FINE_LOCATION')\n permissions.add('android.permission.ACCESS_COARSE_LOCATION')\n }\n if (config.enableBackgroundLocation) {\n permissions.add('android.permission.ACCESS_BACKGROUND_LOCATION')\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_LOCATION')\n }\n if (config.enablePushNotifications) permissions.add('android.permission.POST_NOTIFICATIONS')\n if (config.enableKeepAwake || (config.enableBarometer && config.enableBackgroundLocation)) permissions.add('android.permission.WAKE_LOCK')\n if (config.enableHealthConnect) healthConnectPermissions(config).forEach(permission => permissions.add(permission))\n if (config.enablePedometer) permissions.add('android.permission.ACTIVITY_RECOGNITION')\n if (config.enablePedometer && config.enableHealthServices) permissions.add('android.permission.RECEIVE_BOOT_COMPLETED')\n // A background refresh (WorkManager) after a restart.\n if (config.renderer === 'native' && config.backgroundRefresh?.enabled) permissions.add('android.permission.RECEIVE_BOOT_COMPLETED')\n // A heart-rate recording keeps the process in the foreground while it\n // runs (CraftHeartRateService), as a connectedDevice service.\n if (config.enableHeartRate) {\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE')\n }\n if (config.enableHealthServices) {\n permissions.add('android.permission.BODY_SENSORS')\n permissions.add('android.permission.BODY_SENSORS_BACKGROUND')\n permissions.add('android.permission.health.READ_HEART_RATE')\n permissions.add('android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND')\n permissions.add('android.permission.ACTIVITY_RECOGNITION')\n permissions.add('android.permission.ACCESS_FINE_LOCATION')\n permissions.add('android.permission.ACCESS_COARSE_LOCATION')\n permissions.add('android.permission.FOREGROUND_SERVICE')\n permissions.add('android.permission.FOREGROUND_SERVICE_HEALTH')\n }\n const bluetooth = config.enableBluetooth || config.enableHeartRate ? [\n ' <uses-permission android:name=\"android.permission.BLUETOOTH\" android:maxSdkVersion=\"30\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" android:maxSdkVersion=\"30\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\" android:usesPermissionFlags=\"neverForLocation\" />',\n ' <uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />',\n ...(permissions.has('android.permission.ACCESS_FINE_LOCATION') ? [] : [' <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" android:maxSdkVersion=\"30\" />']),\n ].join('\\n') : ''\n return [bluetooth, ...[...permissions].map(permission => ` <uses-permission android:name=\"${permission}\" />`)].filter(Boolean).join('\\n')\n}\n\n/**\n * The native renderer's own sources: the app around the screens (routes,\n * stores, bars), its services (dialogs, browser, share, push, Health\n * Connect), background refresh, and Firebase messaging when push is on.\n */\nfunction writeNativeShellSources(output: string, packagePath: string, packageName: string, config: CraftAndroidConfig): void {\n const javaDir = join(output, 'app/src/main/java', packagePath)\n const write = (template: string, file: string, replace: (source: string) => string = source => source): void => {\n const source = readFileSync(join(TEMPLATES_DIR, template), 'utf-8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, packageName)\n writeFileSync(join(javaDir, file), replace(source))\n }\n write('CraftBluetooth.kt.template', 'CraftBluetooth.kt')\n write('CraftNativeShell.kt.template', 'CraftNativeShell.kt')\n write('CraftSnapshotFile.kt.template', 'CraftSnapshotFile.kt')\n write('CraftNativeImageCache.kt.template', 'CraftNativeImageCache.kt')\n write('CraftNativeHaptics.kt.template', 'CraftNativeHaptics.kt')\n write('CraftNativeMotion.kt.template', 'CraftNativeMotion.kt')\n write('CraftNativeBackground.kt.template', 'CraftNativeBackground.kt')\n write(config.enableHealthConnect ? 'CraftNativeHealth.kt.template' : 'CraftNativeHealthStub.kt.template', 'CraftNativeHealth.kt')\n write(config.enableHealthServices ? 'CraftHealthServices.kt.template' : 'CraftHealthServicesStub.kt.template', 'CraftHealthServices.kt')\n if (config.enableHealthServices) {\n write('CraftHealthServicesService.kt.template', 'CraftHealthServicesService.kt')\n write('CraftPassiveSteps.kt.template', 'CraftPassiveSteps.kt')\n }\n else {\n rmSync(join(javaDir, 'CraftHealthServicesService.kt'), { force: true })\n rmSync(join(javaDir, 'CraftPassiveSteps.kt'), { force: true })\n }\n write('CraftNativeServices.kt.template', 'CraftNativeServices.kt', source => source\n .replace('{{NATIVE_PUSH_IMPORTS}}', config.enablePushNotifications ? 'import com.google.firebase.messaging.FirebaseMessaging' : '')\n .replace('{{NATIVE_WALLET_IMPORTS}}', config.enableWallet ? `import com.google.android.gms.pay.Pay\nimport com.google.android.gms.pay.PayApiAvailabilityStatus\nimport com.google.android.gms.pay.PayClient` : '')\n .replace('{{NATIVE_WALLET_FIELDS}}', config.enableWallet ? ` private var pendingWallet: ((CraftNativeCapabilityResult) -> Unit)? = null\n private val walletRequestCode = 9517` : '')\n .replace('{{NATIVE_WALLET_AVAILABILITY}}', config.enableWallet ? ` val host = activity()\n if (host == null) {\n done(success(false))\n } else {\n Pay.getClient(host).getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES_JWT)\n .addOnSuccessListener { status -> done(success(status == PayApiAvailabilityStatus.AVAILABLE)) }\n .addOnFailureListener { done(success(false)) }\n }` : ` done(success(runCatching {\n context.packageManager.getLaunchIntentForPackage(\"com.google.android.apps.walletnfcrel\") != null\n }.getOrDefault(false)))`)\n .replace('{{NATIVE_WALLET_JWT_ADD}}', config.enableWallet\n ? ' saveWalletJwt(jwt, host, done)'\n : ' done(failure(\"UNSUPPORTED\", \"Android Wallet JWT saves are not enabled\"))')\n .replace('{{NATIVE_WALLET_HELPER}}', config.enableWallet ? ` private fun saveWalletJwt(jwt: String, host: Activity, done: (CraftNativeCapabilityResult) -> Unit) {\n if (pendingWallet != null) return done(failure(\"BUSY\", \"A Google Wallet save is already in progress\"))\n pendingWallet = done\n try {\n Pay.getClient(host).savePassesJwt(jwt, host, walletRequestCode)\n } catch (error: Exception) {\n pendingWallet = null\n done(failure(\"PRESENTATION_FAILED\", error.message ?: \"Google Wallet could not open\"))\n }\n }\n` : '')\n .replace('{{NATIVE_WALLET_RESULT}}', config.enableWallet ? ` if (requestCode == walletRequestCode) {\n val completion = pendingWallet\n pendingWallet = null\n if (completion == null) return true\n when (resultCode) {\n Activity.RESULT_OK -> completion(success(true))\n Activity.RESULT_CANCELED -> completion(success(false))\n PayClient.SavePassesResult.API_UNAVAILABLE -> completion(failure(\"UNAVAILABLE\", \"Google Wallet save is unavailable\"))\n PayClient.SavePassesResult.INTERNAL_ERROR -> completion(failure(\"WALLET_ERROR\", \"Google Wallet returned an internal error\"))\n PayClient.SavePassesResult.SAVE_ERROR -> completion(failure(\"SAVE_ERROR\", data?.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE) ?: \"Google Wallet could not save the pass\"))\n else -> completion(failure(\"WALLET_ERROR\", \"Google Wallet returned an unknown result\"))\n }\n return true\n }\n` : '')\n .replace('{{NATIVE_PUSH_REGISTER}}', config.enablePushNotifications\n ? ` try {\n FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->\n val token = if (task.isSuccessful) task.result else null\n if (token.isNullOrBlank()) done(failure(\"PUSH_UNAVAILABLE\", task.exception?.message ?: \"Firebase Cloud Messaging gave no token\"))\n else {\n context.getSharedPreferences(\"craft-native-push\", Context.MODE_PRIVATE).edit().putString(\"token\", token).apply()\n done(success(token))\n }\n }\n } catch (error: Exception) {\n done(failure(\"PUSH_UNAVAILABLE\", error.message ?: \"Firebase Cloud Messaging is not configured\"))\n }`\n : ' done(failure(\"CAPABILITY_DISABLED\", \"Push notifications are disabled\"))'))\n write('CraftNativeSounds.kt.template', 'CraftNativeSounds.kt')\n if (config.enablePushNotifications) write('CraftNativeMessagingService.kt.template', 'CraftNativeMessagingService.kt')\n else rmSync(join(javaDir, 'CraftNativeMessagingService.kt'), { force: true })\n // Files a screen shares (craft.files' copies, in the cache) go to other apps through this provider.\n mkdirSync(join(output, 'app/src/main/res/xml'), { recursive: true })\n writeFileSync(join(output, 'app/src/main/res/xml/craft_file_paths.xml'), `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n <cache-path name=\"craft-files\" path=\"craft-files/\" />\n <files-path name=\"craft-media\" path=\"craft-media/\" />\n</paths>\n`)\n}\n\n/** What the native renderer adds to the manifest's application element. */\nfunction renderNativeShellManifest(config: CraftAndroidConfig): string {\n const parts = [\n ' <receiver android:name=\".CraftNativeNotificationReceiver\" android:exported=\"false\" />',\n ` <provider\n android:name=\"androidx.core.content.FileProvider\"\n android:authorities=\"${config.packageName}.craftfiles\"\n android:exported=\"false\"\n android:grantUriPermissions=\"true\">\n <meta-data android:name=\"android.support.FILE_PROVIDER_PATHS\" android:resource=\"@xml/craft_file_paths\" />\n </provider>`,\n ]\n if (config.enablePushNotifications) {\n // What Android shows for a push that arrives while the app is in the\n // background, which Firebase draws without the service.\n parts.push(` <service android:name=\".CraftNativeMessagingService\" android:exported=\"false\">\n <intent-filter>\n <action android:name=\"com.google.firebase.MESSAGING_EVENT\" />\n </intent-filter>\n </service>\n <meta-data android:name=\"com.google.firebase.messaging.default_notification_icon\" android:resource=\"@drawable/craft_notification_icon\" />${config.notificationColor ? `\n <meta-data android:name=\"com.google.firebase.messaging.default_notification_color\" android:resource=\"@color/craft_notification_color\" />` : ''}`)\n }\n if (config.enableHealthConnect) {\n // Android 14 and later open the app's privacy policy from Health\n // Connect's permission screen through this alias.\n parts.push(` <activity-alias\n android:name=\"ViewPermissionUsageActivity\"\n android:exported=\"true\"\n android:targetActivity=\".MainActivity\"\n android:permission=\"android.permission.START_VIEW_PERMISSION_USAGE\">\n <intent-filter>\n <action android:name=\"android.intent.action.VIEW_PERMISSION_USAGE\" />\n <category android:name=\"android.intent.category.HEALTH_PERMISSIONS\" />\n </intent-filter>\n </activity-alias>`)\n }\n return parts.join('\\n')\n}\n\nexport function renderAndroidDeepLinks(config: CraftAndroidConfig): string {\n if (!config.enableDeepLinks) return ''\n const schemes = [...new Set(config.urlSchemes?.map(value => value.trim()).filter(value => /^[a-z][a-z0-9+.-]*$/i.test(value)) ?? [])]\n const custom = schemes.map(scheme => ` <intent-filter>\n <action android:name=\"android.intent.action.VIEW\" />\n <category android:name=\"android.intent.category.DEFAULT\" />\n <category android:name=\"android.intent.category.BROWSABLE\" />\n <data android:scheme=\"${scheme}\" />\n </intent-filter>`).join('\\n')\n const verified = (config.appLinks ?? []).map(link => {\n if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i.test(link.host)) throw new Error('Invalid Android App Link host')\n return ` <intent-filter android:autoVerify=\"true\">\n <action android:name=\"android.intent.action.VIEW\" />\n <category android:name=\"android.intent.category.DEFAULT\" />\n <category android:name=\"android.intent.category.BROWSABLE\" />\n <data android:scheme=\"https\" android:host=\"${link.host}\" />\n </intent-filter>`\n }).join('\\n')\n return [custom, verified].filter(Boolean).join('\\n')\n}\n\n/**\n * Initialize a new Android project\n */\n/**\n * The ABI directories a runtime directory is expected to hold.\n *\n * These are Android's own names for the two architectures craft builds, and\n * they are also `zig build build-android-all`'s output layout — `zig-out/android/`\n * already contains `arm64-v8a/libcraft.so` and `x86_64/libcraft.so`, which is\n * exactly the shape `app/src/main/jniLibs/` wants. So the install below is a\n * copy and not a rearrangement.\n *\n * x86_64 is not optional-in-practice: every Android emulator anyone tests on\n * is x86_64, so a runtime shipped for arm64 alone is one that never runs in\n * CI and never runs on a developer's machine either.\n */\nconst RUNTIME_ABIS = ['arm64-v8a', 'x86_64'] as const\n\n/**\n * Where the runtime directory comes from when the caller does not say.\n *\n * The same shape as `CRAFT_BIN` and the iOS builder's `CRAFT_IOS_RUNTIME`: an\n * explicit override for the monorepo dev loop, not a lookup path. Shipping the\n * runtime to real apps means putting these libraries in the pantry package\n * beside the `craft` binary, which is a distribution decision this function\n * does not make.\n */\nexport function resolveRuntimeDir(override?: string | null): string | null {\n if (override === null) return null\n const dir = override ?? process.env.CRAFT_ANDROID_RUNTIME\n if (!dir) return null\n if (!existsSync(dir)) {\n const source = override === undefined ? 'CRAFT_ANDROID_RUNTIME points at' : 'runtimeDir is'\n throw new Error(`${source} ${dir}, which does not exist.`)\n }\n return dir\n}\n\n/**\n * Copy the Zig runtime into the generated project as\n * `app/src/main/jniLibs/<abi>/libcraft.so`.\n *\n * That path is AGP's default `jniLibs.srcDirs`, so nothing in the Gradle\n * templates has to know about it — the library is packaged into the APK and\n * `System.loadLibrary(\"craft\")` finds it because the file is named for the\n * `craft` it asks for.\n *\n * Until this existed, nothing put the library anywhere. `CraftNative` caught\n * the `UnsatisfiedLinkError`, set `isAvailable = false`, and every action fell\n * through to the Kotlin shim — by design, so an app with no runtime still\n * works, which is also why nobody noticed that *every* generated app was in\n * that state and the whole Android half of the Zig bridge had never run.\n *\n * Returns true when a runtime was installed.\n */\nexport function installRuntime(output: string, runtimeDir: string): boolean {\n // Every ABI resolved before anything is written, so a half-populated\n // runtime directory cannot leave a project carrying one architecture and\n // claiming both. A single-ABI APK installs fine and then fails to load on\n // the other kind of device, which is the break that only shows up on\n // somebody else's phone.\n const found = RUNTIME_ABIS.map(abi => ({ abi, source: join(runtimeDir, abi, 'libcraft.so') }))\n .filter(entry => existsSync(entry.source))\n\n if (found.length === 0) {\n throw new Error(\n `${runtimeDir} has no <abi>/libcraft.so for any of ${RUNTIME_ABIS.join(', ')}. `\n + 'Run `zig build build-android-all -Doptimize=ReleaseSafe` in packages/zig and point at its zig-out/android.',\n )\n }\n\n if (found.length < RUNTIME_ABIS.length) {\n const missing = RUNTIME_ABIS.filter(abi => !found.some(entry => entry.abi === abi))\n console.warn(\n ` ⚠ only ${found.map(entry => entry.abi).join(', ')} was found; ${missing.join(', ')} is missing. `\n + 'The app will fall back to the Kotlin shim on those devices.',\n )\n }\n\n const dest = join(output, 'app/src/main/jniLibs')\n // Wiped rather than merged, so an ABI dropped from a later build does not\n // linger in the project as a stale library the APK still ships.\n rmSync(dest, { force: true, recursive: true })\n\n for (const { abi, source } of found) {\n const abiDir = join(dest, abi)\n mkdirSync(abiDir, { recursive: true })\n cpSync(source, join(abiDir, 'libcraft.so'))\n }\n\n return true\n}\n\nexport async function init(options: InitOptions): Promise<void> {\n const { name, packageName, output } = options\n\n console.log(`\\n⚡ Initializing Craft Android project: ${name}`)\n console.log(` Output: ${output}\\n`)\n\n // Generate package name from app name if not provided\n const finalPackageName = packageName || `com.craft.${generatedPackageSegment(name)}`\n const packagePath = finalPackageName.replace(/\\./g, '/')\n\n // Command-level identity always wins over duplicate fields in `config`.\n // Normalize implied capabilities before validation so craft.config.json and\n // the generated Gradle source describe the same effective project.\n // Undefined keeps the default instead of erasing it (see the iOS builder).\n const given = Object.fromEntries(Object.entries(options.config ?? {}).filter(([, value]) => value !== undefined))\n const config: CraftAndroidConfig = {\n ...DEFAULT_CONFIG,\n ...given,\n appName: name,\n packageName: finalPackageName,\n }\n if (config.enableHealthServices && given.minSdk === undefined) config.minSdk = ANDROID_HEALTH_SERVICES_MIN_SDK\n if (config.enableBackgroundLocation) config.enableGeolocation = true\n if (config.enableHealthConnect) {\n config.compileSdk = Math.max(config.compileSdk ?? 36, 36)\n config.enableHealthConnectBackground = Boolean(config.healthConnect?.background)\n config.enableHealthConnectHistory = Boolean(config.healthConnect?.history)\n healthConnectPermissions(config)\n }\n normalizeAndroidNetworkConfig(config)\n validateAndroidConfig(config)\n validateNativeRouteConfig(config)\n if (config.enablePushNotifications && !config.googleServicesFile) {\n throw new Error('Android push notifications require a googleServicesFile')\n }\n if (config.googleServicesFile) validateGoogleServicesFile(config.googleServicesFile, finalPackageName)\n if (config.appIconPath) requireRegularFile(config.appIconPath, 'App icon')\n const appIconExtension = config.appIconPath ? extname(config.appIconPath).toLowerCase() : undefined\n if (config.appIconPath && !['.gif', '.jpg', '.png', '.webp'].includes(appIconExtension ?? '')) {\n throw new Error(`Unsupported Android app icon format: ${appIconExtension || '(none)'}`)\n }\n if (config.notificationIconPath) requireRegularFile(config.notificationIconPath, 'Notification icon')\n const notificationIconExtension = config.notificationIconPath ? extname(config.notificationIconPath).toLowerCase() : undefined\n if (config.notificationIconPath && !['.png', '.xml'].includes(notificationIconExtension ?? '')) {\n throw new Error(`Unsupported Android notification icon format: ${notificationIconExtension || '(none)'} (use a vector drawable .xml or a white-on-transparent .png)`)\n }\n if (config.notificationIconPath && notificationIconExtension === '.xml' && !/<vector[\\s>]/.test(readFileSync(config.notificationIconPath, 'utf8'))) {\n throw new Error('Notification icon .xml must be an Android vector drawable (<vector>)')\n }\n if (config.notificationColor !== undefined && !/^#[0-9a-f]{6}$/i.test(config.notificationColor)) {\n throw new Error(`notificationColor must be #RRGGBB, not ${String(config.notificationColor)}`)\n }\n\n // Create directory structure\n const dirs = [\n output,\n join(output, 'app/src/main/java', packagePath),\n join(output, 'app/src/main/res/layout'),\n join(output, 'app/src/main/res/values'),\n join(output, 'app/src/main/res/values-night'),\n join(output, 'app/src/main/res/drawable'),\n join(output, 'app/src/main/assets'),\n join(output, 'gradle/wrapper'),\n ]\n\n if (existsSync(output) && !statSync(output).isDirectory()) {\n throw new Error(`Android project output must be a directory: ${output}`)\n }\n\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n }\n\n // Create craft.config.json\n writeAndroidConfig(output, config)\n\n const hasGoogleServices = Boolean(config.googleServicesFile)\n if (config.googleServicesFile) {\n cpSync(config.googleServicesFile, join(output, 'app/google-services.json'))\n }\n\n // Copy templates\n const mainActivityTemplate = readFileSync(join(\n TEMPLATES_DIR,\n config.renderer === 'native' ? 'MainActivityNative.kt.template' : 'MainActivity.kt.template',\n ), 'utf-8')\n const mainActivity = mainActivityTemplate\n .replace(/\\{\\{NATIVE_MAP_IMPORTS\\}\\}/g, () => androidMapHost(config.mapProvider).imports)\n .replace(/\\{\\{NATIVE_MAP_HOST\\}\\}/g, () => readFileSync(join(TEMPLATES_DIR, androidMapHost(config.mapProvider).template), 'utf8'))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n\n writeFileSync(join(output, 'app/src/main/java', packagePath, 'MainActivity.kt'), mainActivity)\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftAppLinks.kt'),\n readFileSync(join(TEMPLATES_DIR, 'CraftAppLinks.kt.template'), 'utf8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n // Both renderers: crash reporting does not depend on how screens are drawn.\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftCrashReporter.kt'),\n readFileSync(join(TEMPLATES_DIR, 'CraftCrashReporter.kt.template'), 'utf-8')\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{CRAFT_VERSION\\}\\}/g, CRAFT_ANDROID_VERSION),\n )\n if (config.renderer === 'native') {\n const mutationTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeMutation.kt.template'), 'utf-8')\n const flatListTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeFlatList.kt.template'), 'utf-8')\n const refreshableFlatListTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeRefreshableFlatList.kt.template'), 'utf-8')\n const capabilityTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeCapabilities.kt.template'), 'utf-8')\n const notificationTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftNativeNotificationReceiver.kt.template'), 'utf-8')\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeMutation.kt'),\n mutationTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeFlatList.kt'),\n flatListTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeRefreshableFlatList.kt'),\n refreshableFlatListTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeCapabilities.kt'),\n capabilityTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftNativeNotificationReceiver.kt'),\n notificationTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n writeNativeShellSources(output, packagePath, finalPackageName, config)\n }\n\n const permissionPolicy = readFileSync(join(TEMPLATES_DIR, 'CraftPermissionPolicy.kt.template'), 'utf8')\n writeFileSync(join(output, 'app/src/main/java', packagePath, 'CraftPermissionPolicy.kt'), permissionPolicy.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName))\n\n // Create CraftBridge.kt\n const craftBridgeTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftBridge.kt.template'), 'utf-8')\n const craftBridge = craftBridgeTemplate\n .replace(/\\{\\{PROMISE_RUNTIME\\}\\}/g, () => renderAndroidPromiseRuntime(' '))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{ENABLE_SPEECH\\}\\}/g, String(Boolean(config.enableSpeechRecognition)))\n .replace(/\\{\\{ENABLE_HAPTICS\\}\\}/g, String(Boolean(config.enableHaptics)))\n .replace(/\\{\\{ENABLE_SHARE\\}\\}/g, String(Boolean(config.enableShare)))\n .replace(/\\{\\{ENABLE_CAMERA\\}\\}/g, String(Boolean(config.enableCamera)))\n .replace(/\\{\\{ENABLE_BIOMETRIC\\}\\}/g, String(Boolean(config.enableBiometric)))\n .replace(/\\{\\{ENABLE_PUSH\\}\\}/g, String(Boolean(config.enablePushNotifications)))\n .replace(/\\{\\{ENABLE_SECURE_STORAGE\\}\\}/g, String(Boolean(config.enableSecureStorage)))\n .replace(/\\{\\{ENABLE_GEOLOCATION\\}\\}/g, String(Boolean(config.enableGeolocation)))\n .replace(/\\{\\{ENABLE_BACKGROUND_LOCATION\\}\\}/g, String(Boolean(config.enableBackgroundLocation)))\n .replace(/\\{\\{ENABLE_KEEP_AWAKE\\}\\}/g, String(Boolean(config.enableKeepAwake)))\n .replace(/\\{\\{ENABLE_DEEP_LINKS\\}\\}/g, String(Boolean(config.enableDeepLinks)))\n .replace(/\\{\\{ENABLE_HEALTH_CONNECT\\}\\}/g, String(Boolean(config.enableHealthConnect)))\n .replace(/\\{\\{ENABLE_HEART_RATE\\}\\}/g, String(Boolean(config.enableHeartRate)))\n .replace(/\\{\\{FIREBASE_IMPORT\\}\\}/g, config.enablePushNotifications ? 'import com.google.firebase.messaging.FirebaseMessaging' : '')\n .replace(/\\{\\{REGISTER_PUSH_IMPLEMENTATION\\}\\}/g, config.enablePushNotifications\n ? `activity.runOnUiThread {\n if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU\n && ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {\n ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 4204)\n }\n try {\n FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->\n val token = if (task.isSuccessful) task.result else null\n val callback = if (token.isNullOrBlank()) \"window._craftPushReject\" else \"window._craftPushResolve\"\n val payload = JSONObject.quote(token ?: task.exception?.message ?: \"Firebase Cloud Messaging is not configured\")\n evaluatePromiseJavascript(\"$callback && $callback($payload)\")\n }\n } catch (error: Exception) {\n val payload = JSONObject.quote(error.message ?: \"Firebase Cloud Messaging is not configured\")\n evaluatePromiseJavascript(\"window._craftPushReject && window._craftPushReject($payload)\")\n }\n }`\n : `evaluatePromiseJavascript(\n \"window._craftPushReject && window._craftPushReject('Push notifications are disabled')\"\n )`)\n // Typed native screens have no WebView bridge or ML surface. Shipping its\n // otherwise unreachable OCR models added ~100 MB of native libraries.\n const bridgeFile = join(output, 'app/src/main/java', packagePath, 'CraftBridge.kt')\n if (config.renderer === 'native') rmSync(bridgeFile, { force: true })\n else writeFileSync(bridgeFile, craftBridge)\n\n // CraftNative goes to a fixed package, not the app's. The prebuilt\n // libcraft.so binds its natives by class name in JNI_OnLoad, and it cannot\n // know a name chosen here — so this one file is deliberately not templated\n // and deliberately not under packagePath.\n let craftNative = readFileSync(join(TEMPLATES_DIR, 'CraftNative.kt.template'), 'utf-8')\n if (config.renderer === 'native') {\n craftNative = craftNative.replace(/^import com\\.google\\.mlkit\\..*\\n/gm, '')\n .replace(/ \\/\\/ CRAFT_WEB_ML_START[\\s\\S]*? \\/\\/ CRAFT_WEB_ML_END/, () =>\n // The fixed JNI holder keeps these callback signatures, even though\n // typed screens do not expose the WebView's machine-learning API.\n ['runImageClassification', 'runObjectDetection', 'runTextRecognition'].map(name =>\n ` @JvmStatic\\n fun ${name}(imageBase64: String) {\\n val (_, reject) = createMlSettlement()\\n reject(\"Machine learning is unavailable in the native renderer\")\\n }`).join('\\n\\n'))\n }\n const nativeDir = join(output, 'app/src/main/java/com/craft/runtime')\n mkdirSync(nativeDir, { recursive: true })\n writeFileSync(join(nativeDir, 'CraftNative.kt'), craftNative)\n // The bridge and native holder both reference the recording store/service,\n // even when the service is not registered in the manifest. Keep these\n // support types in the same fixed package as CraftNative so every generated\n // app compiles regardless of its chosen package name or feature flags.\n writeFileSync(join(nativeDir, 'CraftRecordingPressure.kt'), readFileSync(join(TEMPLATES_DIR, 'CraftRecordingPressure.kt.template'), 'utf-8'))\n const serviceTemplate = readFileSync(join(TEMPLATES_DIR, 'LocationRecordingService.kt.template'), 'utf-8')\n writeFileSync(join(nativeDir, 'LocationRecordingService.kt'), serviceTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName))\n const healthTemplate = readFileSync(join(\n TEMPLATES_DIR,\n config.enableHealthConnect ? 'CraftHealthConnect.kt.template' : 'CraftHealthConnectStub.kt.template',\n ), 'utf-8')\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, 'CraftHealthConnect.kt'),\n healthTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n // The heart-rate strap service, in every app as iOS has CraftHeartRate.swift\n // in every app: the page's bridge and the native screens' services refer to\n // it. Only `enableHeartRate` registers it, declares its service and asks\n // for Bluetooth.\n for (const [template, file] of [['CraftHeartRateCore.kt.template', 'CraftHeartRateCore.kt'], ['CraftHeartRate.kt.template', 'CraftHeartRate.kt']]) {\n writeFileSync(\n join(output, 'app/src/main/java', packagePath, file!),\n readFileSync(join(TEMPLATES_DIR, template!), 'utf8').replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n }\n // Create AndroidManifest.xml\n const manifestTemplate = readFileSync(join(TEMPLATES_DIR, 'AndroidManifest.xml.template'), 'utf-8')\n const manifest = manifestTemplate\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n .replace(/\\{\\{PERMISSIONS\\}\\}/g, renderAndroidPermissions(config))\n // Plain HTTP only for a local dev server, or an app that talks to the\n // person's own devices on the LAN (which have no public certificate).\n .replace(/\\{\\{USES_CLEARTEXT\\}\\}/g, config.devServerURL?.startsWith('http://') || config.enableLocalNetwork ? 'true' : 'false')\n .replace(/\\{\\{DEEP_LINK_INTENT_FILTERS\\}\\}/g, renderAndroidDeepLinks(config))\n .replace(/\\{\\{BACKGROUND_SERVICE\\}\\}/g, config.enableBackgroundLocation\n ? ' <service android:name=\"com.craft.runtime.LocationRecordingService\" android:exported=\"false\" android:foregroundServiceType=\"location\" android:stopWithTask=\"false\" />'\n : '')\n .replace(/\\{\\{HEART_RATE_SERVICE\\}\\}/g, config.enableHeartRate\n ? ' <service android:name=\".CraftHeartRateService\" android:exported=\"false\" android:foregroundServiceType=\"connectedDevice\" />'\n : '')\n .replace(/\\{\\{HEALTH_SERVICES_SERVICE\\}\\}/g, config.enableHealthServices\n ? ' <service android:name=\".CraftHealthServicesService\" android:exported=\"false\" android:foregroundServiceType=\"health\" android:stopWithTask=\"false\" />'\n + (config.enablePedometer ? '\\n <service android:name=\".CraftPassiveStepsService\" android:exported=\"true\" android:permission=\"com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING\" />\\n <receiver android:name=\".CraftPassiveStepsBootReceiver\" android:exported=\"true\"><intent-filter><action android:name=\"android.intent.action.BOOT_COMPLETED\" /></intent-filter></receiver>' : '')\n : '')\n .replace(/\\{\\{NATIVE_NOTIFICATION_RECEIVER\\}\\}/g, config.renderer === 'native'\n ? renderNativeShellManifest(config)\n : '')\n // Starts the crash reporter before Application.onCreate, for every way\n // the process starts (CraftCrashReporter.kt). Inert without a key.\n .replace(/\\{\\{CRASH_REPORTER_PROVIDER\\}\\}/g, ` <provider android:name=\".CraftCrashReporterInit\" android:authorities=\"\\${applicationId}.craft-crash\" android:exported=\"false\" android:initOrder=\"1000\" />`)\n .replace(/\\{\\{GOOGLE_MAPS_API_KEY\\}\\}/g, config.mapProvider !== 'maplibre' && config.mapsApiKey\n ? ` <meta-data android:name=\"com.google.android.geo.API_KEY\" android:value=\"${escapeXml(config.mapsApiKey)}\" />`\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_QUERIES\\}\\}/g, config.enableHealthConnect\n ? ' <queries>\\n <package android:name=\"com.google.android.apps.healthdata\" />\\n </queries>'\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_RATIONALE\\}\\}/g, config.enableHealthConnect\n ? ` <intent-filter>\n <action android:name=\"androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE\" />\n </intent-filter>${config.renderer === 'native' ? '' : `\n <intent-filter>\n <action android:name=\"android.intent.action.VIEW_PERMISSION_USAGE\" />\n <category android:name=\"android.intent.category.HEALTH_PERMISSIONS\" />\n </intent-filter>`}`\n : '')\n\n writeFileSync(join(output, 'app/src/main/AndroidManifest.xml'), manifest)\n\n // Create build.gradle.kts (project level)\n const projectGradleTemplate = readFileSync(join(TEMPLATES_DIR, 'build.gradle.kts.project.template'), 'utf-8')\n writeFileSync(join(output, 'build.gradle.kts'), projectGradleTemplate\n .replace(/\\{\\{GOOGLE_SERVICES_PLUGIN\\}\\}/g, hasGoogleServices ? ' id(\"com.google.gms.google-services\") version \"4.4.2\" apply false' : ''))\n\n // Create build.gradle.kts (app level)\n const appGradleTemplate = readFileSync(join(TEMPLATES_DIR, 'build.gradle.kts.app.template'), 'utf-8')\n const appGradle = appGradleTemplate\n .replace(/\\{\\{MACHINE_LEARNING_DEPENDENCIES\\}\\}/g, config.renderer === 'native' ? '' : [\n 'barcode-scanning:17.3.0', 'image-labeling:17.0.9', 'object-detection:17.0.2', 'text-recognition:16.0.1',\n ].map(module => ` implementation(\"com.google.mlkit:${module}\")`).join('\\n'))\n .replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName)\n .replace(/\\{\\{VERSION_NAME\\}\\}/g, escapeKotlinString(config.version || '1.0.0'))\n .replace(/\\{\\{VERSION_CODE\\}\\}/g, String(config.versionCode || 1))\n .replace(/\\{\\{MIN_SDK\\}\\}/g, String(config.minSdk ?? ANDROID_MIN_SDK))\n .replace(/\\{\\{COMPILE_SDK\\}\\}/g, String(config.compileSdk || 36))\n .replace(/\\{\\{TARGET_SDK\\}\\}/g, String(config.targetSdk || 35))\n .replace(/\\{\\{GOOGLE_SERVICES_PLUGIN\\}\\}/g, hasGoogleServices ? ' id(\"com.google.gms.google-services\")' : '')\n .replace(/\\{\\{FIREBASE_MESSAGING_DEPENDENCY\\}\\}/g, config.enablePushNotifications\n ? ' implementation(\"com.google.firebase:firebase-messaging:24.1.0\")'\n : '')\n .replace(/\\{\\{REFRESH_LAYOUT_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ' implementation(\"androidx.swiperefreshlayout:swiperefreshlayout:1.1.0\")'\n : '')\n .replace(/\\{\\{NATIVE_MAP_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ` // Native STX Map overlays and trail routes\\n implementation(\"${androidMapHost(config.mapProvider).dependency}\")`\n : '')\n .replace(/\\{\\{HEALTH_CONNECT_DEPENDENCIES\\}\\}/g, config.enableHealthConnect\n ? ` implementation(\"androidx.health.connect:connect-client:1.1.0\")\n implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1\")`\n : '')\n .replace(/\\{\\{HEALTH_SERVICES_DEPENDENCIES\\}\\}/g, config.enableHealthServices\n ? ' implementation(\"androidx.health:health-services-client:1.1.0\")'\n : '')\n .replace(/\\{\\{WALLET_DEPENDENCY\\}\\}/g, config.enableWallet\n ? ' // Native Google Wallet save flow for signed pass JWTs\\n implementation(\"com.google.android.gms:play-services-pay:16.5.0\")'\n : '')\n .replace(/\\{\\{JAVASCRIPT_ENGINE_DEPENDENCY\\}\\}/g, config.renderer === 'native'\n ? ` implementation(\"androidx.javascriptengine:javascriptengine:1.1.0\")\n // Native background refresh (WorkManager).\n implementation(\"androidx.work:work-runtime-ktx:2.9.1\")`\n : '')\n\n writeFileSync(join(output, 'app/build.gradle.kts'), appGradle)\n const proguardTemplate = readFileSync(join(TEMPLATES_DIR, 'proguard-rules.pro.template'), 'utf-8')\n writeFileSync(\n join(output, 'app/proguard-rules.pro'),\n proguardTemplate.replace(/\\{\\{PACKAGE_NAME\\}\\}/g, finalPackageName),\n )\n\n // Create settings.gradle.kts\n const settingsTemplate = readFileSync(join(TEMPLATES_DIR, 'settings.gradle.kts.template'), 'utf-8')\n const settings = settingsTemplate.replace(\n /\\{\\{APP_NAME\\}\\}/g,\n escapeKotlinString(generatedGradleProjectName(name)),\n )\n writeFileSync(join(output, 'settings.gradle.kts'), settings)\n\n // Create gradle.properties\n const gradleProperties = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\nandroid.useAndroidX=true\nkotlin.code.style=official\nandroid.nonTransitiveRClass=true\n`\n writeFileSync(join(output, 'gradle.properties'), gradleProperties)\n\n // Create local.properties placeholder\n writeFileSync(join(output, 'local.properties'), '# SDK location will be set by Android Studio\\n')\n\n // Create gradle wrapper properties\n const gradleWrapperProps = `distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\\\://services.gradle.org/distributions/gradle-8.11.1-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n`\n writeFileSync(join(output, 'gradle/wrapper/gradle-wrapper.properties'), gradleWrapperProps)\n\n // Create res/values files\n const stringsXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"app_name\">${escapeXml(name)}</string>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/strings.xml'), stringsXml)\n\n const colorsXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"primary\">#1a1a2e</color>\n <color name=\"primary_dark\">#16162b</color>\n <color name=\"accent\">#4ade80</color>\n <color name=\"background\">${config.backgroundColor}</color>\n <!-- Transparent is NotificationCompat's COLOR_DEFAULT: the system picks. -->\n <color name=\"craft_notification_color\">${config.notificationColor ?? '#00000000'}</color>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/colors.xml'), colorsXml)\n const darkColorsPath = join(output, 'app/src/main/res/values-night/colors.xml')\n if (config.backgroundColorDark) {\n writeFileSync(darkColorsPath, `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"background\">${config.backgroundColorDark}</color>\n</resources>\n`)\n }\n else {\n rmSync(darkColorsPath, { force: true })\n }\n\n const appIconXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"108dp\"\n android:height=\"108dp\"\n android:viewportWidth=\"108\"\n android:viewportHeight=\"108\">\n <path android:fillColor=\"${config.backgroundColor}\" android:pathData=\"M0,0h108v108h-108z\" />\n <path android:fillColor=\"#10B981\" android:pathData=\"M18,78L42,42l12,18l12,-12l24,30z\" />\n</vector>\n`\n if (config.appIconPath) {\n cpSync(\n config.appIconPath,\n join(output, `app/src/main/res/drawable/craft_app_icon${appIconExtension}`),\n )\n }\n else {\n writeFileSync(join(output, 'app/src/main/res/drawable/craft_app_icon.xml'), appIconXml)\n }\n // Android draws a notification icon's alpha only, so it has its own white\n // glyph: the launcher icon there is a white square.\n for (const extension of ['.png', '.xml']) rmSync(join(output, `app/src/main/res/drawable/craft_notification_icon${extension}`), { force: true })\n if (config.notificationIconPath) {\n cpSync(config.notificationIconPath, join(output, `app/src/main/res/drawable/craft_notification_icon${notificationIconExtension}`))\n }\n else {\n writeFileSync(join(output, 'app/src/main/res/drawable/craft_notification_icon.xml'), `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"24dp\"\n android:height=\"24dp\"\n android:viewportWidth=\"108\"\n android:viewportHeight=\"108\">\n <path android:fillColor=\"#FFFFFFFF\" android:pathData=\"M18,78L42,42l12,18l12,-12l24,30z\" />\n</vector>\n`)\n }\n\n const themesXml = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <style name=\"Theme.CraftApp\" parent=\"Theme.Material3.DayNight.NoActionBar\">\n <item name=\"android:statusBarColor\">@color/primary_dark</item>\n <item name=\"android:navigationBarColor\">@color/primary</item>\n <item name=\"android:windowBackground\">@color/background</item>\n </style>\n</resources>\n`\n writeFileSync(join(output, 'app/src/main/res/values/themes.xml'), themesXml)\n\n // Create activity_main.xml\n const activityMainXml = config.renderer === 'native'\n ? `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:id=\"@+id/native_root\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\" />\n`\n : `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout\n xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\"\n android:fitsSystemWindows=\"true\">\n\n <WebView\n android:id=\"@+id/webview\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\" />\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>\n`\n writeFileSync(join(output, 'app/src/main/res/layout/activity_main.xml'), activityMainXml)\n\n syncNativeFonts(config.nativeFonts, output)\n\n // Create placeholder index.html\n const placeholderHtml = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n <title>${escapeXml(name)}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: 'Roboto', sans-serif;\n background: ${config.backgroundColor};\n color: white;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n .container { text-align: center; padding: 2rem; }\n h1 { font-size: 2.5rem; margin-bottom: 1rem; }\n p { opacity: 0.7; }\n .ready { color: #4ade80; font-size: 0.9rem; margin-top: 2rem; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>⚡ ${escapeXml(name)}</h1>\n <p>Built with Craft Android</p>\n <p class=\"ready\" id=\"status\">Waiting for Craft bridge...</p>\n </div>\n <script>\n window.addEventListener('craftReady', (e) => {\n document.getElementById('status').textContent = \\`✓ Craft bridge ready (platform: \\${e.detail.platform})\\`;\n console.log('Craft capabilities:', e.detail.capabilities);\n });\n </script>\n</body>\n</html>`\n\n writeFileSync(join(output, 'app/src/main/assets/index.html'), placeholderHtml)\n\n // The Zig runtime, when one was configured. Absent, the generated app is the\n // Kotlin shim and behaves exactly as it always has — which is the fallback\n // `CraftNative` was written for, not a failure.\n const runtimeDir = resolveRuntimeDir(options.runtimeDir)\n if (runtimeDir) {\n installRuntime(output, runtimeDir)\n console.log(' Installed the Zig runtime from', runtimeDir)\n }\n\n console.log('✅ Project initialized')\n console.log('')\n console.log('Next steps:')\n console.log(` 1. cd ${output}`)\n if (config.renderer === 'native') {\n console.log(' 2. Compile your screen: stx native compile Screen.stx --format bundle --output screen.js')\n console.log(' 3. Run: craft android build --native-bundle screen.js')\n }\n else {\n console.log(' 2. Add your web content to app/src/main/assets/index.html')\n console.log(' 3. Run: craft android build')\n }\n console.log(' 4. Run: craft android open')\n console.log('')\n}\n\n/**\n * Build Android project\n */\nexport async function build(options: BuildOptions): Promise<void> {\n const { htmlPath, nativeBundlePath, devServer, output, release, bundle, compile = true } = options\n\n console.log('\\n📦 Building Craft Android project...')\n\n // Load config\n const configPath = join(output, 'craft.config.json')\n if (!existsSync(configPath)) {\n throw new Error(`No craft.config.json found in ${output}. Run 'craft android init' first.`)\n }\n\n const config: CraftAndroidConfig = JSON.parse(readFileSync(configPath, 'utf-8'))\n validateAndroidConfig(config)\n validateNativeRouteConfig(config)\n\n if (config.renderer === 'native') {\n if (htmlPath || devServer) throw new Error('A native Android screen cannot use --html-path or --dev-server.')\n const destination = join(output, 'app/src/main/assets/native-screen.js')\n const routeDestination = join(output, 'app/src/main/assets/native-screens')\n if (nativeBundlePath) {\n // One file, or a directory of route bundles (stx's routesDir); each\n // replaces the other, since a route's own file wins at runtime.\n if (!existsSync(nativeBundlePath)) throw new Error(`Native bundle not found: ${nativeBundlePath}`)\n if (statSync(nativeBundlePath).isDirectory()) {\n if (resolve(nativeBundlePath) !== resolve(routeDestination)) {\n rmSync(routeDestination, { recursive: true, force: true })\n cpSync(nativeBundlePath, routeDestination, { recursive: true })\n compressNativeSources(routeDestination)\n }\n rmSync(destination, { force: true })\n }\n else {\n if (resolve(nativeBundlePath) !== resolve(destination)) cpSync(nativeBundlePath, destination)\n compressNativeSources(destination)\n rmSync(routeDestination, { recursive: true, force: true })\n }\n }\n const icons = join(output, 'app/src/main/assets/craft-icons.json')\n if (options.iconsPath) {\n requireRegularFile(options.iconsPath, 'Icon table')\n if (resolve(options.iconsPath) !== resolve(icons)) cpSync(options.iconsPath, icons)\n }\n if (!existsSync(destination) && !existsSync(routeDestination)) {\n throw new Error('Native Android mode needs app/src/main/assets/native-screen.js. Compile a .stx screen with `stx native compile` first.')\n }\n }\n else if (nativeBundlePath) {\n throw new Error('--native-bundle requires renderer: \"native\" in craft.config.json.')\n }\n\n // Refresh the runtime the same way the iOS builder does: only for a project\n // that already has one, so `craft android build` in a shim-only project does\n // not quietly acquire a native library it was never generated with.\n if (existsSync(join(output, 'app/src/main/jniLibs'))) {\n const runtimeDir = resolveRuntimeDir(options.runtimeDir)\n if (runtimeDir) {\n installRuntime(output, runtimeDir)\n console.log(' Refreshed the Zig runtime from', runtimeDir)\n }\n else {\n console.log(' Keeping the Zig runtime installed at init (no runtime directory configured)')\n }\n }\n\n // Update dev server URL if provided\n if (devServer) {\n const url = androidWebUrl(devServer, 'Android dev server URL')\n config.devServerURL = url.toString()\n config.trustedOrigins = [...new Set([\n ...(config.trustedOrigins ?? []).map(value => androidWebUrl(value, 'Android trusted origin').origin),\n url.origin,\n ])]\n writeAndroidConfig(output, config)\n console.log(` Dev server: ${devServer}`)\n }\n\n // Copy the complete web application if provided.\n if (htmlPath) {\n syncAndroidWebAssets(htmlPath, output)\n config.hasBundledFallback = Boolean(devServer)\n writeAndroidConfig(output, config)\n console.log(` Synced: ${htmlPath} → assets/`)\n }\n\n syncNativeFonts(config.nativeFonts, output)\n\n runPostGenerateHook(config.postGenerate, output)\n\n if (!compile) return\n\n // Check if gradlew exists\n const gradlewPath = join(output, 'gradlew')\n if (!existsSync(gradlewPath)) {\n console.log(' Generating Gradle wrapper...')\n try {\n await $`cd ${output} && gradle wrapper`.quiet()\n }\n catch (error) {\n throw new Error('Gradle is unavailable. Install Android Studio or Gradle before building Android.', { cause: error })\n }\n }\n\n // Build the project\n const variant = release ? 'Release' : 'Debug'\n const buildType = `${bundle ? 'bundle' : 'assemble'}${variant}`\n console.log(` Building ${release ? 'release' : 'debug'} ${bundle ? 'app bundle' : 'APK'}...`)\n if (release && !process.env.CRAFT_ANDROID_KEYSTORE)\n console.log(' CRAFT_ANDROID_KEYSTORE is not set: the release build is unsigned.')\n\n try {\n await $`cd ${output} && ./gradlew ${buildType}`\n const artifact = bundle\n ? `app/build/outputs/bundle/${variant.toLowerCase()}/app-${variant.toLowerCase()}.aab`\n : release\n ? 'app/build/outputs/apk/release/app-release.apk'\n : 'app/build/outputs/apk/debug/app-debug.apk'\n console.log(`✅ ${bundle ? 'App bundle' : 'APK'} built: ${artifact}`)\n }\ncatch (error) {\n console.error('Build failed. Open in Android Studio for details.')\n throw error\n }\n\n console.log('')\n}\n\n/**\n * Open Android project in Android Studio\n */\nexport async function open(options: OpenOptions): Promise<void> {\n const { output } = options\n\n if (!existsSync(output)) {\n throw new Error(`No Android project found in ${output}. Run 'craft android init' first.`)\n }\n\n console.log(`🚀 Opening Android project in Android Studio...`)\n\n // Try to open with Android Studio\n try {\n // macOS\n await $`open -a \"Android Studio\" ${output}`.quiet()\n }\ncatch {\n try {\n // Linux\n await $`studio ${output}`.quiet()\n }\ncatch {\n console.log('⚠️ Android Studio not found.')\n console.log(' Please open the project manually in Android Studio:')\n console.log(` ${output}`)\n }\n }\n}\n\n/**\n * Run on Android device or emulator\n */\nexport async function run(options: RunOptions): Promise<void> {\n const { device, output } = options\n\n // First build\n await build({ output })\n\n // Install and run\n console.log('📱 Installing and running on device...')\n\n try {\n const apkPath = join(output, 'app/build/outputs/apk/debug/app-debug.apk')\n\n if (device) {\n await $`adb -s ${device} install -r ${apkPath}`\n }\nelse {\n await $`adb install -r ${apkPath}`\n }\n\n // Get package name from config\n const config: CraftAndroidConfig = JSON.parse(\n readFileSync(join(output, 'craft.config.json'), 'utf-8')\n )\n\n // Launch the app\n const launchCmd = `${config.packageName}/.MainActivity`\n if (device) {\n await $`adb -s ${device} shell am start -n ${launchCmd}`\n }\nelse {\n await $`adb shell am start -n ${launchCmd}`\n }\n\n console.log('✅ App launched')\n }\ncatch (error) {\n console.error('Failed to install/run. Make sure:')\n console.error(' 1. ADB is installed and in PATH')\n console.error(' 2. A device/emulator is connected (run: adb devices)')\n throw error\n }\n}\n",
6
6
  "/** Build-time native map selection. Both providers are native Android views. */\nexport type AndroidMapProvider = 'google' | 'maplibre'\n\nexport function androidMapHost(provider: AndroidMapProvider = 'google'): { template: string, imports: string, dependency: string } {\n if (provider === 'google') return {\n template: 'CraftNativeMapGoogle.kt.template',\n imports: `import com.google.android.gms.maps.CameraUpdateFactory\nimport com.google.android.gms.maps.GoogleMap\nimport com.google.android.gms.maps.MapView\nimport com.google.android.gms.maps.OnMapReadyCallback\nimport com.google.android.gms.maps.model.BitmapDescriptorFactory\nimport com.google.android.gms.maps.model.LatLng\nimport com.google.android.gms.maps.model.LatLngBounds\nimport com.google.android.gms.maps.model.Marker\nimport com.google.android.gms.maps.model.MarkerOptions\nimport com.google.android.gms.maps.model.Polygon\nimport com.google.android.gms.maps.model.PolygonOptions\nimport com.google.android.gms.maps.model.Polyline\nimport com.google.android.gms.maps.model.PolylineOptions`,\n dependency: 'com.google.android.gms:play-services-maps:18.2.0',\n }\n if (provider === 'maplibre') return {\n template: 'CraftNativeMapLibre.kt.template',\n imports: `import org.maplibre.android.MapLibre\nimport org.maplibre.android.camera.CameraPosition\nimport org.maplibre.android.camera.CameraUpdateFactory\nimport org.maplibre.android.geometry.LatLng\nimport org.maplibre.android.geometry.LatLngBounds\nimport org.maplibre.android.location.LocationComponentActivationOptions\nimport org.maplibre.android.maps.MapLibreMap\nimport org.maplibre.android.maps.MapView\nimport org.maplibre.android.maps.OnMapReadyCallback\nimport org.maplibre.android.maps.Style\nimport org.maplibre.android.style.expressions.Expression\nimport org.maplibre.android.style.layers.CircleLayer\nimport org.maplibre.android.style.layers.FillLayer\nimport org.maplibre.android.style.layers.LineLayer\nimport org.maplibre.android.style.layers.SymbolLayer\nimport org.maplibre.android.style.layers.PropertyFactory.*\nimport org.maplibre.android.style.sources.GeoJsonSource`,\n dependency: 'org.maplibre.gl:android-sdk:13.7.1',\n }\n throw new Error(`Unknown Android native map provider: ${provider}. Expected google or maplibre.`)\n}\n",
7
7
  "const ANDROID_PROMISE_RUNTIME = `\nif (window.__craftRejectPendingPromises) {\n window.__craftRejectPendingPromises('Android bridge reinitialized');\n}\nif (window.__craftRejectPermissionRequests) {\n window.__craftRejectPermissionRequests('Android bridge reinitialized');\n}\nwindow.__craftPromiseRuntimeClosed = false;\nwindow.__craftPendingPromises = Object.create(null);\nwindow.__craftPromise = function(channel, resolveName, rejectName, invoke, timeoutMs, timeoutError) {\n if (window.__craftPromiseRuntimeClosed) {\n return Promise.reject(new Error('Android bridge is closed'));\n }\n if (window.__craftPendingPromises[channel]) {\n return Promise.reject(new Error('A '.concat(channel, ' request is already in progress')));\n }\n\n return new Promise(function(resolve, reject) {\n var entry = {settled: false, timer: null, settle: null};\n var resolveCallback;\n var rejectCallback;\n\n entry.settle = function(succeeded, value) {\n if (entry.settled || window.__craftPendingPromises[channel] !== entry) return;\n entry.settled = true;\n if (entry.timer !== null) clearTimeout(entry.timer);\n if (window[resolveName] === resolveCallback) window[resolveName] = null;\n if (window[rejectName] === rejectCallback) window[rejectName] = null;\n delete window.__craftPendingPromises[channel];\n if (succeeded) resolve(value);\n else reject(value);\n };\n\n resolveCallback = function(value) {\n entry.settle(true, value);\n };\n rejectCallback = function(error) {\n entry.settle(false, error);\n };\n window[resolveName] = resolveCallback;\n window[rejectName] = rejectCallback;\n window.__craftPendingPromises[channel] = entry;\n\n if (timeoutMs > 0) {\n entry.timer = setTimeout(function() {\n entry.settle(false, timeoutError || new Error(channel.concat(' request timed out')));\n }, timeoutMs);\n }\n\n try {\n invoke();\n }\n catch (error) {\n entry.settle(false, error);\n }\n });\n};\n\nwindow.__craftRejectPendingPromises = function(message) {\n window.__craftPromiseRuntimeClosed = true;\n Object.keys(window.__craftPendingPromises).forEach(function(channel) {\n var entry = window.__craftPendingPromises[channel];\n if (entry) entry.settle(false, new Error(message || 'Android bridge closed'));\n });\n};\n`\n\nexport function renderAndroidPromiseRuntime(indent = ''): string {\n return ANDROID_PROMISE_RUNTIME\n .trim()\n .split('\\n')\n .map(line => `${indent}${line}`)\n .join('\\n')\n}\n\nexport { ANDROID_PROMISE_RUNTIME }\n",
8
8
  "/** Compile and execute a native Kotlin fixture with Gradle's dependency resolver. */\nimport { readFileSync } from 'node:fs'\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\n/** Uses the Android builder's Kotlin version, including its transitive compiler dependencies. */\nexport async function runKotlinFixture(source: string): Promise<void> {\n const gradle = Bun.which('gradle')\n if (!gradle) throw new Error('Gradle is required to run native Kotlin fixtures')\n const template = readFileSync(join(dirname(import.meta.dir), 'templates/build.gradle.kts.project.template'), 'utf8')\n const version = template.match(/id\\(\"org.jetbrains.kotlin.android\"\\) version \"([\\d.]+)\"/)?.[1]\n if (!version) throw new Error('The Android builder Kotlin version is missing')\n const directory = await mkdtemp(join(tmpdir(), 'craft-kotlin-fixture-'))\n try {\n await writeFile(join(directory, 'Fixture.kt'), source)\n await writeFile(join(directory, 'settings.gradle'), \"rootProject.name = 'craft-kotlin-fixture'\\n\")\n await writeFile(join(directory, 'gradle.properties'), 'org.gradle.jvmargs=-Xmx512m\\n')\n await writeFile(join(directory, 'build.gradle'), `\nrepositories { mavenCentral() }\nconfigurations {\n kotlinCompiler\n kotlinRuntime\n}\ndependencies {\n kotlinCompiler 'org.jetbrains.kotlin:kotlin-compiler-embeddable:${version}'\n kotlinRuntime 'org.jetbrains.kotlin:kotlin-stdlib:${version}'\n}\ntasks.register('compileFixture', JavaExec) {\n classpath = configurations.kotlinCompiler\n mainClass = 'org.jetbrains.kotlin.cli.jvm.K2JVMCompiler'\n args '-no-stdlib', '-no-reflect', '-classpath', configurations.kotlinRuntime.asPath,\n '-d', layout.buildDirectory.dir('classes').get().asFile.absolutePath,\n file('Fixture.kt').absolutePath\n}\ntasks.register('runFixture', JavaExec) {\n dependsOn 'compileFixture'\n classpath = files(layout.buildDirectory.dir('classes')) + configurations.kotlinRuntime\n mainClass = 'FixtureKt'\n}\n`)\n const child = Bun.spawn([gradle, '--no-daemon', '--console=plain', '--max-workers=2', 'runFixture'], {\n cwd: directory,\n stdout: 'inherit',\n stderr: 'inherit',\n })\n const code = await child.exited\n if (code !== 0) throw new Error(`Native Kotlin fixture failed with exit code ${code}`)\n }\n finally {\n await rm(directory, { recursive: true, force: true })\n }\n}\n",
9
9
  "import { appendFileSync, closeSync, mkdirSync, mkdtempSync, openSync, rmSync } from 'node:fs'\nimport { availableParallelism, cpus, tmpdir, totalmem } from 'node:os'\nimport { basename, isAbsolute, join, resolve } from 'node:path'\nimport { setTimeout as delay } from 'node:timers/promises'\n\nexport interface AndroidEmulatorOptions {\n sdkRoot: string\n sdkmanager: string\n avdmanager: string\n image: string\n acceleration: 'hardware' | 'software'\n artifactsDirectory: string\n temporaryDirectory?: string\n port?: number\n acceptLicenses?: boolean\n /** Defaults to 10 minutes; hardware is capped there, software cold provisioning at 20 minutes. */\n bootTimeoutMs?: number\n /** Requested guest RAM, 1536–8192 MB (Android emulator limits); defaults to 2048. */\n memoryMb?: number\n /** Requested guest CPU count, 1–8; defaults to 2. */\n virtualCpus?: number\n env?: Record<string, string | undefined>\n /** Cancels provisioning, boot and the owned session without touching other devices. */\n signal?: AbortSignal\n}\n\nexport interface AndroidEmulatorSession {\n serial: string\n adb: string\n env: Record<string, string | undefined>\n /** Stops only this session's process and removes only its disposable AVD. */\n dispose: () => Promise<void>\n /** First disposal result, including cancellation. A failure stays recorded even if dispose() later retries successfully. */\n closed: Promise<void>\n}\n\n/** Provision and own a real Android emulator on a macOS or Linux SDK host. */\nexport async function createAndroidEmulator(options: AndroidEmulatorOptions): Promise<AndroidEmulatorSession> {\n options.signal?.throwIfAborted()\n if (!['darwin', 'linux'].includes(process.platform)) throw new Error('Android emulator sessions require macOS or Linux')\n if (!['hardware', 'software'].includes(options.acceleration)) throw new Error('Select hardware or software Android emulation explicitly')\n if (![options.sdkmanager, options.avdmanager].every(isAbsolute)) throw new Error('Select absolute Android command-line tool paths')\n const abi = process.arch === 'arm64' ? 'arm64-v8a' : process.arch === 'x64' ? 'x86_64' : undefined\n if (!abi || !/^system-images;android-\\d+;[^;\\s]+;[^;\\s]+$/.test(options.image) || !options.image.endsWith(`;${abi}`))\n throw new Error('The Android system image must match the host architecture')\n if (options.acceleration === 'software' && process.arch !== 'x64')\n throw new Error('Android software emulation requires an x86_64 host and system image')\n const bootTimeoutMs = options.bootTimeoutMs ?? 600_000\n const requiresPlayStore = options.image.split(';')[2] === 'google_apis_playstore'\n const maximumBootTimeoutMs = options.acceleration === 'software' ? 1_200_000 : 600_000\n if (!Number.isSafeInteger(bootTimeoutMs) || bootTimeoutMs < 1000 || bootTimeoutMs > maximumBootTimeoutMs)\n throw new Error(`Android bootTimeoutMs must be an integer between 1000 and ${maximumBootTimeoutMs} milliseconds`)\n const memoryMb = options.memoryMb ?? 2048\n if (!Number.isSafeInteger(memoryMb) || memoryMb < 1536 || memoryMb > 8192)\n throw new Error('Android memoryMb must be an integer between 1536 and 8192 megabytes')\n const virtualCpus = options.virtualCpus ?? 2\n if (!Number.isSafeInteger(virtualCpus) || virtualCpus < 1 || virtualCpus > 8)\n throw new Error('Android virtualCpus must be an integer between 1 and 8')\n const port = options.port ?? 5558\n if (!Number.isInteger(port) || port < 5554 || port > 5682 || port % 2 !== 0) throw new Error('Android console ports must be even and between 5554 and 5682')\n const sdk = resolve(options.sdkRoot)\n const artifacts = resolve(options.artifactsDirectory)\n const temporary = options.temporaryDirectory ?? tmpdir()\n mkdirSync(artifacts, { recursive: true })\n mkdirSync(temporary, { recursive: true })\n const owned = mkdtempSync(join(temporary, 'craft-android-emulator-'))\n const name = basename(owned)\n const serial = `emulator-${port}`\n const env: Record<string, string | undefined> = {\n ...process.env, ...options.env,\n ANDROID_HOME: sdk,\n ANDROID_SDK_ROOT: sdk,\n ANDROID_SDK_HOME: owned,\n ANDROID_USER_HOME: join(owned, '.android'),\n ANDROID_EMULATOR_HOME: join(owned, '.android'),\n ANDROID_AVD_HOME: join(owned, 'avd'),\n ANDROID_SERIAL: serial,\n // avdmanager uses this location to resolve --package against sdkRoot,\n // even when Pantry installed the command-line tools in a separate prefix.\n AVDMANAGER_OPTS: `'-Dcom.android.sdkmanager.toolsdir=${join(sdk, 'cmdline-tools/latest')}'`,\n }\n const adb = join(sdk, 'platform-tools/adb')\n const executable = join(sdk, 'emulator/emulator')\n let child: ReturnType<typeof Bun.spawn> | undefined\n let log: number | undefined\n let sequence = 0\n let disposal: Promise<void> | undefined\n let bootStartedAt = 0\n let cpuStart = 0\n let idleStart = 0\n let identity: Record<string, unknown> | undefined\n interface OwnedProcess {\n process: ReturnType<typeof Bun.spawn>\n graceMs: number\n output?: Promise<PromiseSettledResult<string>[]>\n stdout?: string\n closing?: Promise<void>\n }\n const processes = new Set<OwnedProcess>()\n let resolveClosed!: () => void\n let rejectClosed!: (error: unknown) => void\n const closed = new Promise<void>((resolve, reject) => { resolveClosed = resolve; rejectClosed = reject })\n // Cancellation can finish before a caller receives its session. Retain the\n // rejection for callers of `closed` without an unhandled background error.\n void closed.catch(() => {})\n async function recordBootResult(status: 'booted' | 'failed', endedAt = Date.now()): Promise<void> {\n if (!identity) return\n const cpuEnd = cpus()\n const totalDeltaMs = cpuEnd.reduce((total, cpu) => total + Object.values(cpu.times).reduce((sum, value) => sum + value, 0), 0) - cpuStart\n const idleDeltaMs = cpuEnd.reduce((total, cpu) => total + cpu.times.idle, 0) - idleStart\n await Bun.write(join(artifacts, 'android-emulator.json'), JSON.stringify({\n ...identity, status, [status === 'booted' ? 'bootedAt' : 'failedAt']: new Date(endedAt).toISOString(),\n bootElapsedMs: endedAt - bootStartedAt,\n hostCpuInterval: { totalDeltaMs, idleDeltaMs, busyDeltaMs: totalDeltaMs - idleDeltaMs },\n }, null, 2) + '\\n')\n }\n function groupExists(pid: number): boolean {\n try { process.kill(-pid, 0); return true }\n catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false\n if ((error as NodeJS.ErrnoException).code === 'EPERM') return true\n throw error\n }\n }\n function signalGroup(pid: number, signal: NodeJS.Signals): void {\n try { process.kill(-pid, signal) }\n catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ESRCH') throw error }\n }\n async function disposeGroup(pid: number, graceMs: number): Promise<unknown[]> {\n const errors: unknown[] = []\n if (!groupExists(pid)) return errors\n let termSent = false\n try { signalGroup(pid, 'SIGTERM'); termSent = true } catch (error) { errors.push(error) }\n if (termSent) {\n const grace = performance.now() + graceMs\n while (groupExists(pid) && performance.now() < grace) await Bun.sleep(10)\n }\n if (!groupExists(pid)) return errors\n try { signalGroup(pid, 'SIGKILL') } catch (error) { errors.push(error) }\n const deadline = performance.now() + 1000\n while (groupExists(pid) && performance.now() < deadline) await Bun.sleep(10)\n if (groupExists(pid)) throw new AggregateError([...errors, new Error(`Owned Android process group ${pid} remained after disposal`)], `Android cleanup failed; private registry retained at ${owned}`)\n return errors\n }\n function closeProcess(record: OwnedProcess): Promise<void> {\n if (record.closing) return record.closing\n const attempt = (async () => {\n const errors = await disposeGroup(record.process.pid, record.graceMs)\n await record.process.exited\n if (record.output) {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n const output = await Promise.race([\n record.output,\n new Promise<null>((resolve) => { timer = setTimeout(() => resolve(null), 1000) }),\n ])\n if (!output) throw new Error(`Owned Android command pipes did not close; private registry retained at ${owned}`)\n for (const stream of output) if (stream.status === 'rejected') errors.push(stream.reason)\n record.stdout = output[0]?.status === 'fulfilled' ? output[0].value : ''\n }\n finally { if (timer) clearTimeout(timer) }\n }\n processes.delete(record)\n if (errors.length) throw new AggregateError(errors, 'Owned Android process cleanup encountered an error')\n })()\n record.closing = attempt\n void attempt.catch(() => { if (record.closing === attempt) record.closing = undefined })\n return attempt\n }\n async function run(args: string[], input?: string, timeout = 900_000, allowFailure = false): Promise<{ code: number, stdout: string }> {\n options.signal?.throwIfAborted()\n const startedAt = new Date().toISOString()\n const command = Bun.spawn(args, { env, detached: true, stdin: input === undefined ? 'ignore' : new TextEncoder().encode(input), stdout: 'pipe', stderr: 'pipe' })\n const record: OwnedProcess = { process: command, graceMs: 250, output: Promise.allSettled([new Response(command.stdout).text(), new Response(command.stderr).text()]) }\n processes.add(record)\n let stop!: (reason: 'aborted' | 'timeout') => void\n const stopping = new Promise<'aborted' | 'timeout'>((resolve) => { stop = resolve })\n const onCommandAbort = (): void => stop('aborted')\n const timer = setTimeout(() => stop('timeout'), timeout)\n options.signal?.addEventListener('abort', onCommandAbort, { once: true })\n try {\n if (options.signal?.aborted) stop('aborted')\n const result = await Promise.race([command.exited, stopping])\n // Reap every owned descendant before waiting for pipe EOF or returning.\n await closeProcess(record)\n const code = await command.exited\n const output = await record.output!\n const stdout = record.stdout ?? ''\n const stderr = output[1]?.status === 'fulfilled' ? output[1].value : ''\n const timedOut = result === 'timeout'\n appendFileSync(join(artifacts, 'device-commands.jsonl'), JSON.stringify({ sequence: ++sequence, startedAt, finishedAt: new Date().toISOString(), args, code, stdout, stderr, timedOut, commandGroupDisposed: true }) + '\\n')\n options.signal?.throwIfAborted()\n if (timedOut && !allowFailure) throw new Error(`${basename(args[0]!)} timed out; inspect ${artifacts}`)\n if (code !== 0 && !allowFailure) throw new Error(`${basename(args[0]!)} failed with exit ${code}; inspect ${artifacts}`)\n // Readiness probes retry transient timeouts within the original boot\n // deadline. Even a process handling TERM with exit zero is not ready.\n return { code: timedOut ? code || 1 : code, stdout }\n }\n finally {\n clearTimeout(timer)\n options.signal?.removeEventListener('abort', onCommandAbort)\n }\n }\n const dispose = (): Promise<void> => {\n if (disposal) return disposal\n const attempt = (async () => {\n const results = await Promise.allSettled([...processes].map(closeProcess))\n const errors = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected').map(result => result.reason)\n try {\n if (!processes.size) {\n options.signal?.removeEventListener('abort', onAbort)\n if (log !== undefined) { closeSync(log); log = undefined }\n rmSync(owned, { recursive: true, force: true })\n }\n else errors.push(new Error(`Owned Android processes remain; private registry retained at ${owned}`))\n }\n catch (error) { errors.push(error) }\n if (errors.length) throw new AggregateError(errors, `Android emulator disposal failed; inspect ${artifacts}`)\n })().then(resolveClosed, (error) => { rejectClosed(error); throw error })\n disposal = attempt\n // Share concurrent/successful disposal, but let a caller retry after the\n // OS permits signaling again. `closed` retains the first failure.\n void attempt.catch(() => { if (disposal === attempt) disposal = undefined })\n return attempt\n }\n const onAbort = (): void => { void dispose().catch(() => {}) }\n options.signal?.addEventListener('abort', onAbort, { once: true })\n try {\n mkdirSync(env.ANDROID_AVD_HOME!, { recursive: true })\n mkdirSync(env.ANDROID_USER_HOME!, { recursive: true })\n if (options.acceptLicenses) await run([options.sdkmanager, `--sdk_root=${sdk}`, '--licenses'], 'y\\n'.repeat(100))\n // Preserve the vendor download URL and exception details in the command\n // artifact when SDK provisioning fails before an emulator can start.\n await run([options.sdkmanager, `--sdk_root=${sdk}`, '--verbose', 'platform-tools', 'emulator'], options.acceptLicenses ? 'y\\n'.repeat(100) : undefined)\n const acceleration = await run([executable, '-accel-check'], undefined, 30_000, true)\n if (options.acceleration === 'hardware' && acceleration.code !== 0)\n throw new Error(`Android hardware acceleration is unavailable; inspect ${artifacts}`)\n await run([options.sdkmanager, `--sdk_root=${sdk}`, '--verbose', options.image], options.acceptLicenses ? 'y\\n'.repeat(100) : undefined)\n const devices = (await run([adb, 'devices'], undefined, 10_000)).stdout\n if (devices.split('\\n').some(line => line.startsWith(`${serial}\\t`))) throw new Error(`${serial} is already in use`)\n await run([options.avdmanager, 'create', 'avd', '--name', name, '--package', options.image, '--device', 'pixel_6'], 'no\\n')\n log = openSync(join(artifacts, 'emulator.log'), 'w')\n bootStartedAt = Date.now()\n const hostCpus = cpus()\n cpuStart = hostCpus.reduce((total, cpu) => total + Object.values(cpu.times).reduce((sum, value) => sum + value, 0), 0)\n idleStart = hostCpus.reduce((total, cpu) => total + cpu.times.idle, 0)\n child = Bun.spawn([executable, '-avd', name, '-port', String(port), '-no-window', '-no-snapshot', '-no-audio', '-no-boot-anim', '-gpu', 'software', '-memory', String(memoryMb), '-cores', String(virtualCpus), '-accel', options.acceleration === 'software' ? 'off' : 'on'], { env, detached: true, stdout: log, stderr: log })\n // Keep the established ten-second guest shutdown budget, and own every\n // descendant before the caller can cancel or receive the session.\n processes.add({ process: child, graceMs: 10_000 })\n if (options.signal?.aborted) onAbort()\n identity = {\n image: options.image, acceleration: options.acceleration, accelerationProbeExitCode: acceleration.code,\n bootTimeoutMs, bootStartedAt: new Date(bootStartedAt).toISOString(),\n host: { cpuModel: hostCpus[0]?.model, logicalCpus: hostCpus.length, availableParallelism: availableParallelism(), memoryBytes: totalmem() },\n virtualCpus, memoryMb, serial, avdDirectory: env.ANDROID_AVD_HOME, emulatorPid: child.pid,\n }\n await Bun.write(join(artifacts, 'android-emulator.json'), JSON.stringify(identity, null, 2) + '\\n')\n const deadline = bootStartedAt + bootTimeoutMs\n const probeTimeout = (): number => Math.max(1, Math.min(10_000, deadline - Date.now()))\n let connected = false\n let lastReconnectAt = 0\n while (Date.now() < deadline && child.exitCode === null) {\n options.signal?.throwIfAborted()\n let booted = false\n // Nonzero ADB exits are expected while services initialize. Filesystem,\n // logging and process-launch errors must remain fatal and visible.\n const connection = await run([adb, 'devices'], undefined, probeTimeout(), true)\n const state = connection.stdout.split(/\\r?\\n/).find(line => line.startsWith(`${serial}\\t`))?.split(/\\s+/)[1]\n // A cold boot can restart adbd after its initial connection. Recover the\n // owned stale transport without restarting the shared server or touching\n // other devices. A never-connected guest still needs to finish booting.\n if (connection.code === 0 && state === 'offline' && connected && Date.now() - lastReconnectAt >= 30_000 && Date.now() < deadline) {\n lastReconnectAt = Date.now()\n await run([adb, '-s', serial, 'reconnect'], undefined, probeTimeout(), true)\n }\n if (connection.code === 0 && state === 'device') {\n connected = true\n const completion = await run([adb, '-s', serial, 'shell', 'getprop', 'sys.boot_completed'], undefined, probeTimeout(), true)\n if (completion.code === 0 && completion.stdout.trim() === '1') {\n // boot_completed can precede SettingsProvider and System UI readiness.\n const settings = await run([adb, '-s', serial, 'shell', 'settings', 'get', 'global', 'animator_duration_scale'], undefined, probeTimeout(), true)\n const packages = await run([adb, '-s', serial, 'shell', 'pm', 'path', 'android'], undefined, probeTimeout(), true)\n // A stock Play image can expose the framework package and HOME while\n // first-boot provisioning is still registering its bundled apps.\n const playStore = requiresPlayStore\n ? await run([adb, '-s', serial, 'shell', 'pm', 'path', 'com.android.vending'], undefined, probeTimeout(), true)\n : undefined\n const systemUi = await run([adb, '-s', serial, 'shell', 'pidof', 'com.android.systemui'], undefined, probeTimeout(), true)\n // Native acceptance must be able to observe platform crashes before\n // launching any app. boot_completed/System UI can precede logd's ADB\n // event stream. Require a complete history read so a partial transport\n // read cannot admit the device before its first health check.\n const events = await run([adb, '-s', serial, 'logcat', '-b', 'events', '-d', '-v', 'threadtime'], undefined, probeTimeout(), true)\n if (events.code === 0 && /^\\S+\\s+\\S+\\s+\\d+\\s+\\d+\\s+[A-Z]\\s+am_(?:anr|crash)\\s*:/m.test(events.stdout))\n throw new Error(`Android emulator reported a platform ANR or crash during boot; inspect ${artifacts}`)\n // AOSP's first boot can report all those services ready while its\n // automatic SDK setup activity still owns HOME. Launching HOME then\n // opens that transient activity; after it finishes UI automation has\n // AOSP and stock Play first boots can report those services ready\n // while their automatic SDK setup activity still owns HOME. Launching\n // HOME then opens that transient activity; after it finishes UI automation has\n // no foreground root. Wait for the real HOME destination instead of\n // modifying device setup or relaxing native acceptance.\n const home = await run([adb, '-s', serial, 'shell', 'cmd', 'package', 'resolve-activity', '--brief', '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.HOME'], undefined, probeTimeout(), true)\n const homeActivity = home.stdout.trim().split(/\\r?\\n/).at(-1) ?? ''\n const temporaryHome = homeActivity.startsWith('com.android.sdksetup/')\n || homeActivity.startsWith('com.google.android.googlesdksetup/')\n || /^com\\.android\\.settings\\/(?:\\.|com\\.android\\.settings\\.)FallbackHome$/.test(homeActivity)\n || /^android\\/.*(?:Resolver|Chooser)Activity$/.test(homeActivity)\n // Resolving HOME can precede its first input window during cold\n // provisioning. Hand off only once the launcher actually has focus.\n const windows = await run([adb, '-s', serial, 'shell', 'dumpsys', 'window'], undefined, probeTimeout(), true)\n const focusedPackage = windows.stdout.match(/^\\s*mCurrentFocus\\s*=\\s*Window\\{[^}\\r\\n]*\\bu\\d+\\s+([\\w.]+)\\//m)?.[1]\n booted = settings.code === 0 && packages.code === 0 && systemUi.code === 0 && events.code === 0\n && /^package:\\/\\S+/m.test(packages.stdout) && /^\\d+(?:\\s+\\d+)*$/.test(systemUi.stdout.trim())\n && (!requiresPlayStore || (playStore?.code === 0 && /^package:\\/\\S+/m.test(playStore.stdout)))\n && home.code === 0 && /^[\\w.]+\\/[\\w.$]+$/.test(homeActivity) && !temporaryHome\n && windows.code === 0 && focusedPackage === homeActivity.split('/')[0]\n }\n }\n const checkedAt = Date.now()\n if (booted && checkedAt <= deadline) {\n await recordBootResult('booted', checkedAt)\n options.signal?.throwIfAborted()\n return { serial, adb, env, dispose, closed }\n }\n await delay(Math.min(2000, Math.max(0, deadline - Date.now())), undefined, { signal: options.signal })\n }\n options.signal?.throwIfAborted()\n if (child.exitCode !== null) throw new Error(`The owned Android emulator exited with code ${child.exitCode} before boot; inspect ${join(artifacts, 'emulator.log')}`)\n throw new Error(`The owned Android emulator did not boot within ${bootTimeoutMs}ms; inspect ${artifacts}`)\n }\n catch (error) {\n // Node's abortable timer wraps signal.reason in AbortError.cause. Keep\n // the caller's exact reason for ordinary cancellation at every phase.\n const timerAborted = options.signal?.aborted && error instanceof Error && error.name === 'AbortError' && error.cause === options.signal.reason\n const failure = timerAborted ? options.signal!.reason : options.signal?.aborted && error !== options.signal.reason\n ? new AggregateError([options.signal.reason, error], `Android emulator setup failed: ${String(options.signal.reason)}`)\n : error\n if (child) {\n try { await recordBootResult('failed') }\n catch (diagnostic) { console.error(`Could not retain emulator boot timing: ${diagnostic}`) }\n for (const args of [['logcat', '-d', '-b', 'all'], ['shell', 'getprop'], ['shell', 'dumpsys', 'activity', 'processes']]) {\n try { await run([adb, '-s', serial, ...args], undefined, 10_000, true) }\n catch { /* The emulator log remains available if ADB has disconnected. */ }\n }\n }\n try { await dispose() }\n catch (cleanup) { throw new AggregateError([failure, cleanup], 'Android emulator setup and cleanup failed') }\n throw failure\n }\n}\n"
10
10
  ],
11
- "mappings": "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",
12
- "debugId": "6765F03CB34C0C1D64756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "4DE134DA887683DE64756E2164756E21",
13
13
  "names": []
14
14
  }