1820 lines
53 KiB
Rust
1820 lines
53 KiB
Rust
//! Unified manifest configuration for cross-platform app packaging.
|
|
//!
|
|
//! This module provides configuration structs for permissions and platform-specific
|
|
//! manifest customization. Permissions declared here are automatically mapped to
|
|
//! platform-specific identifiers (AndroidManifest.xml, Info.plist, etc.)
|
|
//!
|
|
//! ## JSON Schema Generation
|
|
//!
|
|
//! Generate a JSON schema for IDE autocomplete:
|
|
//! ```bash
|
|
//! dx config --schema > dioxus-schema.json
|
|
//! ```
|
|
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
// ============================================================================
|
|
// Unified Permissions
|
|
// ============================================================================
|
|
|
|
/// Unified permission configuration that maps to platform-specific identifiers.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [permissions]
|
|
/// location = { precision = "fine", description = "Track your runs" }
|
|
/// camera = { description = "Take photos for your profile" }
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct PermissionsConfig {
|
|
/// Location permission with precision level.
|
|
/// Maps to ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION on Android,
|
|
/// NSLocationWhenInUseUsageDescription on iOS/macOS.
|
|
#[serde(default)]
|
|
pub location: Option<LocationPermission>,
|
|
|
|
/// Camera access permission.
|
|
#[serde(default)]
|
|
pub camera: Option<SimplePermission>,
|
|
|
|
/// Microphone access permission.
|
|
#[serde(default)]
|
|
pub microphone: Option<SimplePermission>,
|
|
|
|
/// Push notifications permission.
|
|
#[serde(default)]
|
|
pub notifications: Option<SimplePermission>,
|
|
|
|
/// Photo library access.
|
|
#[serde(default)]
|
|
pub photos: Option<StoragePermission>,
|
|
|
|
/// Bluetooth connectivity.
|
|
#[serde(default)]
|
|
pub bluetooth: Option<SimplePermission>,
|
|
|
|
/// Background location updates.
|
|
#[serde(default, rename = "background-location")]
|
|
pub background_location: Option<SimplePermission>,
|
|
|
|
/// Contacts access.
|
|
#[serde(default)]
|
|
pub contacts: Option<StoragePermission>,
|
|
|
|
/// Calendar access.
|
|
#[serde(default)]
|
|
pub calendar: Option<StoragePermission>,
|
|
|
|
/// Biometric authentication (Face ID, fingerprint).
|
|
#[serde(default)]
|
|
pub biometrics: Option<SimplePermission>,
|
|
|
|
/// NFC access.
|
|
#[serde(default)]
|
|
pub nfc: Option<SimplePermission>,
|
|
|
|
/// Motion and fitness data.
|
|
#[serde(default)]
|
|
pub motion: Option<SimplePermission>,
|
|
|
|
/// Health data access.
|
|
#[serde(default)]
|
|
pub health: Option<StoragePermission>,
|
|
|
|
/// Speech recognition.
|
|
#[serde(default)]
|
|
pub speech: Option<SimplePermission>,
|
|
|
|
/// Media library access.
|
|
#[serde(default, rename = "media-library")]
|
|
pub media_library: Option<SimplePermission>,
|
|
|
|
/// Siri integration (iOS only).
|
|
#[serde(default)]
|
|
pub siri: Option<SimplePermission>,
|
|
|
|
/// HomeKit integration (iOS only).
|
|
#[serde(default)]
|
|
pub homekit: Option<SimplePermission>,
|
|
|
|
/// Local network access.
|
|
#[serde(default, rename = "local-network")]
|
|
pub local_network: Option<SimplePermission>,
|
|
|
|
/// Nearby Wi-Fi devices (Android).
|
|
#[serde(default, rename = "nearby-wifi")]
|
|
pub nearby_wifi: Option<SimplePermission>,
|
|
}
|
|
|
|
/// Simple permission with just a description.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct SimplePermission {
|
|
/// User-facing description shown in permission dialogs.
|
|
pub description: String,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Unified Deep Linking
|
|
// ============================================================================
|
|
|
|
/// Unified deep linking configuration.
|
|
///
|
|
/// This provides a cross-platform interface for URL schemes and universal/app links.
|
|
/// Platform-specific overrides can be configured in `[ios]` and `[android]` sections.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [deep_links]
|
|
/// schemes = ["myapp", "com.example.myapp"]
|
|
/// hosts = ["example.com", "*.example.com"]
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct DeepLinkConfig {
|
|
/// Custom URL schemes (e.g., "myapp" for myapp://path).
|
|
/// Maps to CFBundleURLSchemes on iOS/macOS and intent-filter on Android.
|
|
#[serde(default)]
|
|
pub schemes: Vec<String>,
|
|
|
|
/// Universal link / App link hosts (e.g., "example.com").
|
|
/// Maps to Associated Domains on iOS and App Links on Android.
|
|
/// Supports wildcards like "*.example.com".
|
|
#[serde(default)]
|
|
pub hosts: Vec<String>,
|
|
|
|
/// Path patterns for universal/app links (e.g., "/app/*", "/share/*").
|
|
/// If empty, all paths are matched.
|
|
#[serde(default)]
|
|
pub paths: Vec<String>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Unified Background Modes
|
|
// ============================================================================
|
|
|
|
/// Unified background execution configuration.
|
|
///
|
|
/// This provides a cross-platform interface for background capabilities.
|
|
/// Platform-specific overrides can be configured in `[ios]` and `[android]` sections.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [background]
|
|
/// location = true
|
|
/// audio = true
|
|
/// fetch = true
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct BackgroundConfig {
|
|
/// Background location updates.
|
|
/// iOS: UIBackgroundModes "location"
|
|
/// Android: ACCESS_BACKGROUND_LOCATION permission
|
|
#[serde(default)]
|
|
pub location: bool,
|
|
|
|
/// Background audio playback.
|
|
/// iOS: UIBackgroundModes "audio"
|
|
/// Android: FOREGROUND_SERVICE_MEDIA_PLAYBACK
|
|
#[serde(default)]
|
|
pub audio: bool,
|
|
|
|
/// Background data fetch.
|
|
/// iOS: UIBackgroundModes "fetch"
|
|
/// Android: WorkManager or foreground service
|
|
#[serde(default)]
|
|
pub fetch: bool,
|
|
|
|
/// Remote push notifications.
|
|
/// iOS: UIBackgroundModes "remote-notification"
|
|
/// Android: Firebase Cloud Messaging
|
|
#[serde(default, rename = "remote-notifications")]
|
|
pub remote_notifications: bool,
|
|
|
|
/// VoIP calls.
|
|
/// iOS: UIBackgroundModes "voip"
|
|
/// Android: FOREGROUND_SERVICE_PHONE_CALL
|
|
#[serde(default)]
|
|
pub voip: bool,
|
|
|
|
/// Bluetooth LE accessories.
|
|
/// iOS: UIBackgroundModes "bluetooth-central" and "bluetooth-peripheral"
|
|
/// Android: FOREGROUND_SERVICE_CONNECTED_DEVICE
|
|
#[serde(default)]
|
|
pub bluetooth: bool,
|
|
|
|
/// External accessory communication.
|
|
/// iOS: UIBackgroundModes "external-accessory"
|
|
#[serde(default, rename = "external-accessory")]
|
|
pub external_accessory: bool,
|
|
|
|
/// Background processing tasks.
|
|
/// iOS: UIBackgroundModes "processing"
|
|
/// Android: WorkManager
|
|
#[serde(default)]
|
|
pub processing: bool,
|
|
}
|
|
|
|
/// Location permission with precision control.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct LocationPermission {
|
|
/// Precision level: "fine" (GPS) or "coarse" (network-based).
|
|
#[serde(default)]
|
|
pub precision: LocationPrecision,
|
|
|
|
/// User-facing description shown in permission dialogs.
|
|
pub description: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, JsonSchema)]
|
|
pub enum LocationPrecision {
|
|
#[default]
|
|
#[serde(rename = "fine")]
|
|
Fine,
|
|
#[serde(rename = "coarse")]
|
|
Coarse,
|
|
}
|
|
|
|
/// Storage permission with access level control.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct StoragePermission {
|
|
/// Access level: "read", "write", or "read-write".
|
|
#[serde(default)]
|
|
pub access: StorageAccess,
|
|
|
|
/// User-facing description shown in permission dialogs.
|
|
pub description: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, JsonSchema)]
|
|
pub enum StorageAccess {
|
|
#[serde(rename = "read")]
|
|
Read,
|
|
#[serde(rename = "write")]
|
|
Write,
|
|
#[default]
|
|
#[serde(rename = "read-write")]
|
|
ReadWrite,
|
|
}
|
|
|
|
/// Raw platform permission entry.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct RawPermission {
|
|
pub description: String,
|
|
}
|
|
|
|
// ============================================================================
|
|
// iOS Configuration
|
|
// ============================================================================
|
|
|
|
/// iOS-specific configuration.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [ios]
|
|
/// deployment_target = "15.0"
|
|
/// identifier = "com.example.myapp.ios" # Override bundle.identifier for iOS
|
|
///
|
|
/// [ios.entitlements]
|
|
/// app-groups = ["group.com.example.app"]
|
|
///
|
|
/// [ios.plist]
|
|
/// UIBackgroundModes = ["location", "fetch"]
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct IosConfig {
|
|
// === Bundle settings (override [bundle] section) ===
|
|
/// The app's identifier (e.g., "com.example.myapp").
|
|
/// Overrides `bundle.identifier` for iOS builds.
|
|
#[serde(default)]
|
|
pub identifier: Option<String>,
|
|
|
|
/// The app's publisher.
|
|
/// Overrides `bundle.publisher` for iOS builds.
|
|
#[serde(default)]
|
|
pub publisher: Option<String>,
|
|
|
|
/// Icons for the app.
|
|
/// Overrides `bundle.icon` for iOS builds.
|
|
#[serde(default)]
|
|
pub icon: Option<Vec<String>>,
|
|
|
|
/// Additional resources to bundle.
|
|
/// Overrides `bundle.resources` for iOS builds.
|
|
#[serde(default)]
|
|
pub resources: Option<Vec<String>>,
|
|
|
|
/// Copyright notice.
|
|
/// Overrides `bundle.copyright` for iOS builds.
|
|
#[serde(default)]
|
|
pub copyright: Option<String>,
|
|
|
|
/// App category.
|
|
/// Overrides `bundle.category` for iOS builds.
|
|
#[serde(default)]
|
|
pub category: Option<String>,
|
|
|
|
/// Short description.
|
|
/// Overrides `bundle.short_description` for iOS builds.
|
|
#[serde(default)]
|
|
pub short_description: Option<String>,
|
|
|
|
/// Long description.
|
|
/// Overrides `bundle.long_description` for iOS builds.
|
|
#[serde(default)]
|
|
pub long_description: Option<String>,
|
|
|
|
// === iOS-specific settings ===
|
|
/// The bundle version string (CFBundleVersion).
|
|
///
|
|
/// This is the machine-readable build number that must increase with every upload
|
|
/// to App Store Connect. Can be overridden per-build with `--bundle-version` or the
|
|
/// `DX_BUNDLE_VERSION` environment variable. Defaults to the crate version.
|
|
#[serde(default)]
|
|
pub bundle_version: Option<String>,
|
|
|
|
/// Minimum iOS deployment target (e.g., "15.0").
|
|
#[serde(default)]
|
|
pub deployment_target: Option<String>,
|
|
|
|
/// Path to custom Info.plist to merge with generated.
|
|
#[serde(default)]
|
|
pub info_plist: Option<PathBuf>,
|
|
|
|
/// iOS entitlements configuration.
|
|
#[serde(default)]
|
|
pub entitlements: IosEntitlements,
|
|
|
|
/// Additional Info.plist keys to merge.
|
|
#[serde(default)]
|
|
pub plist: HashMap<String, serde_json::Value>,
|
|
|
|
/// Raw XML injection points.
|
|
#[serde(default)]
|
|
pub raw: IosRawConfig,
|
|
|
|
// === Platform-specific overrides (extend unified config) ===
|
|
/// Additional URL schemes beyond unified `[deep_links]`.schemes.
|
|
/// These are merged with the unified schemes.
|
|
#[serde(default)]
|
|
pub url_schemes: Vec<String>,
|
|
|
|
/// Additional background modes beyond unified `[background]`.
|
|
/// Valid values: "audio", "location", "voip", "fetch", "remote-notification",
|
|
/// "newsstand-content", "external-accessory", "bluetooth-central",
|
|
/// "bluetooth-peripheral", "processing"
|
|
#[serde(default)]
|
|
pub background_modes: Vec<String>,
|
|
|
|
/// Document types the app can open.
|
|
#[serde(default)]
|
|
pub document_types: Vec<IosDocumentType>,
|
|
|
|
/// Exported type identifiers (custom UTIs).
|
|
#[serde(default)]
|
|
pub exported_type_identifiers: Vec<IosTypeIdentifier>,
|
|
|
|
/// Imported type identifiers.
|
|
#[serde(default)]
|
|
pub imported_type_identifiers: Vec<IosTypeIdentifier>,
|
|
|
|
/// Widget extensions to compile and bundle.
|
|
/// Each entry defines a Swift-based widget extension (.appex) that will be
|
|
/// compiled and installed into the app's PlugIns folder.
|
|
#[serde(default)]
|
|
pub widget_extensions: Vec<WidgetExtensionConfig>,
|
|
}
|
|
|
|
/// Configuration for an iOS Widget Extension.
|
|
///
|
|
/// Widget extensions are compiled as Swift executables and bundled as .appex
|
|
/// bundles in the app's PlugIns folder.
|
|
///
|
|
/// Example in Dioxus.toml:
|
|
/// ```toml
|
|
/// [[ios.widget_extensions]]
|
|
/// source = "src/ios/widget"
|
|
/// display_name = "Location Widget"
|
|
/// bundle_id_suffix = "location-widget"
|
|
/// deployment_target = "16.2"
|
|
/// module_name = "GeolocationPlugin"
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct WidgetExtensionConfig {
|
|
/// Path to the Swift package source directory (relative to project root).
|
|
pub source: String,
|
|
|
|
/// Display name for the widget (shown in system UI).
|
|
pub display_name: String,
|
|
|
|
/// Bundle ID suffix appended to the app's bundle identifier.
|
|
/// For example, if the app is "com.example.app" and suffix is "location-widget",
|
|
/// the widget bundle ID will be "com.example.app.location-widget".
|
|
pub bundle_id_suffix: String,
|
|
|
|
/// Minimum deployment target (e.g., "16.2").
|
|
/// Defaults to the app's iOS deployment target if not specified.
|
|
#[serde(default)]
|
|
pub deployment_target: Option<String>,
|
|
|
|
/// Swift module name for the widget.
|
|
/// This MUST match the module name used by the main app's Swift plugin
|
|
/// for ActivityKit type matching to work.
|
|
pub module_name: String,
|
|
}
|
|
|
|
/// iOS document type declaration.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct IosDocumentType {
|
|
/// Document type name.
|
|
pub name: String,
|
|
|
|
/// File extensions (e.g., ["txt", "md"]).
|
|
#[serde(default)]
|
|
pub extensions: Vec<String>,
|
|
|
|
/// MIME types.
|
|
#[serde(default)]
|
|
pub mime_types: Vec<String>,
|
|
|
|
/// UTI types.
|
|
#[serde(default)]
|
|
pub types: Vec<String>,
|
|
|
|
/// Icon file name.
|
|
#[serde(default)]
|
|
pub icon: Option<String>,
|
|
|
|
/// Role: "Editor", "Viewer", "Shell", or "None".
|
|
#[serde(default)]
|
|
pub role: Option<String>,
|
|
}
|
|
|
|
/// iOS Uniform Type Identifier declaration.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct IosTypeIdentifier {
|
|
/// UTI identifier (e.g., "com.example.myformat").
|
|
pub identifier: String,
|
|
|
|
/// Human-readable description.
|
|
#[serde(default)]
|
|
pub description: Option<String>,
|
|
|
|
/// Conforms to these UTIs.
|
|
#[serde(default)]
|
|
pub conforms_to: Vec<String>,
|
|
|
|
/// File extensions.
|
|
#[serde(default)]
|
|
pub extensions: Vec<String>,
|
|
|
|
/// MIME types.
|
|
#[serde(default)]
|
|
pub mime_types: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct IosEntitlements {
|
|
/// App groups for shared data.
|
|
#[serde(default, rename = "app-groups")]
|
|
pub app_groups: Vec<String>,
|
|
|
|
/// Push notification environment: "development" or "production".
|
|
#[serde(default, rename = "aps-environment")]
|
|
pub aps_environment: Option<String>,
|
|
|
|
/// Associated domains for universal links.
|
|
#[serde(default, rename = "associated-domains")]
|
|
pub associated_domains: Vec<String>,
|
|
|
|
/// Enable iCloud container support.
|
|
#[serde(default)]
|
|
pub icloud: bool,
|
|
|
|
/// Keychain access groups.
|
|
#[serde(default, rename = "keychain-access-groups")]
|
|
pub keychain_access_groups: Vec<String>,
|
|
|
|
/// Enable Apple Pay.
|
|
#[serde(default, rename = "apple-pay")]
|
|
pub apple_pay: bool,
|
|
|
|
/// Enable HealthKit.
|
|
#[serde(default)]
|
|
pub healthkit: bool,
|
|
|
|
/// Enable HomeKit.
|
|
#[serde(default)]
|
|
pub homekit: bool,
|
|
|
|
/// Additional entitlements.
|
|
#[serde(flatten)]
|
|
pub additional: HashMap<String, serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct IosRawConfig {
|
|
/// Raw XML to inject into Info.plist.
|
|
#[serde(default)]
|
|
pub info_plist: Option<String>,
|
|
|
|
/// Raw XML to inject into entitlements.plist.
|
|
#[serde(default)]
|
|
pub entitlements: Option<String>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Android Configuration
|
|
// ============================================================================
|
|
|
|
/// Android-specific configuration.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [android]
|
|
/// min_sdk = 24
|
|
/// target_sdk = 34
|
|
/// identifier = "com.example.myapp.android" # Override bundle.identifier for Android
|
|
/// features = ["android.hardware.location.gps"]
|
|
///
|
|
/// # Android signing configuration (previously in [bundle.android])
|
|
/// [android.signing]
|
|
/// jks_file = "keystore.jks"
|
|
/// jks_password = "password"
|
|
/// key_alias = "mykey"
|
|
/// key_password = "keypassword"
|
|
///
|
|
/// [android.permissions]
|
|
/// "android.permission.FOREGROUND_SERVICE" = { description = "Background service" }
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct AndroidConfig {
|
|
// === Bundle settings (override [bundle] section) ===
|
|
/// The app's identifier (e.g., "com.example.myapp").
|
|
/// Overrides `bundle.identifier` for Android builds.
|
|
#[serde(default)]
|
|
pub identifier: Option<String>,
|
|
|
|
/// The app's publisher.
|
|
/// Overrides `bundle.publisher` for Android builds.
|
|
#[serde(default)]
|
|
pub publisher: Option<String>,
|
|
|
|
/// Icons for the app.
|
|
/// Overrides `bundle.icon` for Android builds.
|
|
#[serde(default)]
|
|
pub icon: Option<Vec<String>>,
|
|
|
|
/// Additional resources to bundle.
|
|
/// Overrides `bundle.resources` for Android builds.
|
|
#[serde(default)]
|
|
pub resources: Option<Vec<String>>,
|
|
|
|
/// Copyright notice.
|
|
/// Overrides `bundle.copyright` for Android builds.
|
|
#[serde(default)]
|
|
pub copyright: Option<String>,
|
|
|
|
/// App category.
|
|
/// Overrides `bundle.category` for Android builds.
|
|
#[serde(default)]
|
|
pub category: Option<String>,
|
|
|
|
/// Short description.
|
|
/// Overrides `bundle.short_description` for Android builds.
|
|
#[serde(default)]
|
|
pub short_description: Option<String>,
|
|
|
|
/// Long description.
|
|
/// Overrides `bundle.long_description` for Android builds.
|
|
#[serde(default)]
|
|
pub long_description: Option<String>,
|
|
|
|
// === Android signing settings (previously in bundle.android) ===
|
|
/// Android signing configuration for release builds.
|
|
/// This replaces the deprecated `[bundle.android]` section.
|
|
#[serde(default)]
|
|
pub signing: Option<AndroidSigningConfig>,
|
|
|
|
// === Android-specific settings ===
|
|
/// The version code used for `versionCode` in the generated Gradle project.
|
|
///
|
|
/// Must be between 1 and 2100000000 (the Google Play Store maximum).
|
|
///
|
|
/// Can be overridden per-build with `--version-code` or the `DX_ANDROID_VERSION_CODE`
|
|
/// environment variable. If unset, it is derived from the crate version as
|
|
/// `major * 1000000 + minor * 1000 + patch`.
|
|
#[serde(default)]
|
|
pub version_code: Option<u32>,
|
|
|
|
/// Minimum SDK version.
|
|
#[serde(default)]
|
|
pub min_sdk: Option<u32>,
|
|
|
|
/// Target SDK version.
|
|
#[serde(default)]
|
|
pub target_sdk: Option<u32>,
|
|
|
|
/// Compile SDK version.
|
|
#[serde(default)]
|
|
pub compile_sdk: Option<u32>,
|
|
|
|
/// Native library name loaded by NativeActivity (without `lib` prefix and `.so` extension).
|
|
/// Defaults to `"main"` (i.e. `libmain.so`). Override if you need a custom library name.
|
|
#[serde(default)]
|
|
pub lib_name: Option<String>,
|
|
|
|
/// Hardware/software features required.
|
|
#[serde(default)]
|
|
pub features: Vec<String>,
|
|
|
|
/// Path to custom AndroidManifest.xml to merge.
|
|
#[serde(default)]
|
|
pub manifest: Option<PathBuf>,
|
|
|
|
/// Gradle dependencies to add.
|
|
#[serde(default)]
|
|
pub gradle_dependencies: Vec<String>,
|
|
|
|
/// Gradle plugins to apply.
|
|
#[serde(default)]
|
|
pub gradle_plugins: Vec<String>,
|
|
|
|
/// ProGuard rule files.
|
|
#[serde(default)]
|
|
pub proguard_rules: Vec<PathBuf>,
|
|
|
|
/// Additional Android permissions not in unified config.
|
|
#[serde(default)]
|
|
pub permissions: HashMap<String, RawPermission>,
|
|
|
|
/// Raw XML injection points.
|
|
#[serde(default)]
|
|
pub raw: AndroidRawConfig,
|
|
|
|
/// Application-level config.
|
|
#[serde(default)]
|
|
pub application: AndroidApplicationConfig,
|
|
|
|
// === Platform-specific overrides (extend unified config) ===
|
|
/// Additional URL schemes beyond unified `[deep_links]`.schemes.
|
|
/// These are merged with the unified schemes.
|
|
#[serde(default)]
|
|
pub url_schemes: Vec<String>,
|
|
|
|
/// Intent filters for deep linking.
|
|
/// These extend the unified `[deep_links]` configuration with Android-specific options.
|
|
#[serde(default)]
|
|
pub intent_filters: Vec<AndroidIntentFilter>,
|
|
|
|
/// Foreground service types for background operations.
|
|
/// Valid values: "camera", "connectedDevice", "dataSync", "health", "location",
|
|
/// "mediaPlayback", "mediaProjection", "microphone", "phoneCall", "remoteMessaging",
|
|
/// "shortService", "specialUse", "systemExempted"
|
|
#[serde(default)]
|
|
pub foreground_service_types: Vec<String>,
|
|
|
|
/// Queries for package visibility (required for Android 11+).
|
|
/// Specify packages or intents your app needs to query.
|
|
#[serde(default)]
|
|
pub queries: AndroidQueries,
|
|
}
|
|
|
|
/// Android signing configuration for release builds.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct AndroidSigningConfig {
|
|
/// Path to the Java keystore file.
|
|
pub jks_file: PathBuf,
|
|
|
|
/// Password for the keystore.
|
|
pub jks_password: String,
|
|
|
|
/// Alias of the key in the keystore.
|
|
pub key_alias: String,
|
|
|
|
/// Password for the key.
|
|
pub key_password: String,
|
|
}
|
|
|
|
/// Android intent filter for deep linking.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct AndroidIntentFilter {
|
|
/// Actions (e.g., "android.intent.action.VIEW").
|
|
#[serde(default)]
|
|
pub actions: Vec<String>,
|
|
|
|
/// Categories (e.g., "android.intent.category.DEFAULT", "android.intent.category.BROWSABLE").
|
|
#[serde(default)]
|
|
pub categories: Vec<String>,
|
|
|
|
/// Data specifications.
|
|
#[serde(default)]
|
|
pub data: Vec<AndroidIntentData>,
|
|
|
|
/// Auto-verify for App Links (requires HTTPS and assetlinks.json).
|
|
#[serde(default)]
|
|
pub auto_verify: bool,
|
|
}
|
|
|
|
/// Android intent data specification.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct AndroidIntentData {
|
|
/// URL scheme (e.g., "https", "myapp").
|
|
#[serde(default)]
|
|
pub scheme: Option<String>,
|
|
|
|
/// Host (e.g., "example.com").
|
|
#[serde(default)]
|
|
pub host: Option<String>,
|
|
|
|
/// Port number.
|
|
#[serde(default)]
|
|
pub port: Option<String>,
|
|
|
|
/// Path (exact match).
|
|
#[serde(default)]
|
|
pub path: Option<String>,
|
|
|
|
/// Path prefix.
|
|
#[serde(default)]
|
|
pub path_prefix: Option<String>,
|
|
|
|
/// Path pattern (with wildcards).
|
|
#[serde(default)]
|
|
pub path_pattern: Option<String>,
|
|
|
|
/// MIME type.
|
|
#[serde(default)]
|
|
pub mime_type: Option<String>,
|
|
}
|
|
|
|
/// Android package visibility queries.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct AndroidQueries {
|
|
/// Package names to query.
|
|
#[serde(default)]
|
|
pub packages: Vec<String>,
|
|
|
|
/// Intent actions to query.
|
|
#[serde(default)]
|
|
pub intents: Vec<AndroidQueryIntent>,
|
|
}
|
|
|
|
/// Android query intent specification.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct AndroidQueryIntent {
|
|
/// Action (e.g., "android.intent.action.SEND").
|
|
pub action: String,
|
|
|
|
/// Data scheme (e.g., "mailto").
|
|
#[serde(default)]
|
|
pub scheme: Option<String>,
|
|
|
|
/// MIME type (e.g., "text/plain").
|
|
#[serde(default)]
|
|
pub mime_type: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct AndroidRawConfig {
|
|
/// Raw XML to inject into manifest (after permissions).
|
|
#[serde(default)]
|
|
pub manifest: Option<String>,
|
|
|
|
/// Raw attributes for `<application>` element.
|
|
#[serde(default)]
|
|
pub application_attrs: Option<String>,
|
|
|
|
/// Raw XML inside `<application>` element.
|
|
#[serde(default)]
|
|
pub application: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct AndroidApplicationConfig {
|
|
/// Enable cleartext (HTTP) traffic.
|
|
#[serde(default)]
|
|
pub uses_cleartext_traffic: Option<bool>,
|
|
|
|
/// Application theme.
|
|
#[serde(default)]
|
|
pub theme: Option<String>,
|
|
|
|
/// RTL layout support.
|
|
#[serde(default)]
|
|
pub supports_rtl: Option<bool>,
|
|
|
|
/// Enable large heap.
|
|
#[serde(default)]
|
|
pub large_heap: Option<bool>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// macOS Configuration
|
|
// ============================================================================
|
|
|
|
/// macOS-specific configuration.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [macos]
|
|
/// minimum_system_version = "11.0"
|
|
/// identifier = "com.example.myapp.macos" # Override bundle.identifier for macOS
|
|
///
|
|
/// # macOS signing (previously in [bundle.macos])
|
|
/// signing_identity = "Developer ID Application: My Company"
|
|
/// provider_short_name = "MYCOMPANY"
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct MacosConfig {
|
|
// === Bundle settings (override [bundle] section) ===
|
|
/// The app's identifier (e.g., "com.example.myapp").
|
|
/// Overrides `bundle.identifier` for macOS builds.
|
|
#[serde(default)]
|
|
pub identifier: Option<String>,
|
|
|
|
/// The app's publisher.
|
|
/// Overrides `bundle.publisher` for macOS builds.
|
|
#[serde(default)]
|
|
pub publisher: Option<String>,
|
|
|
|
/// Icons for the app.
|
|
/// Overrides `bundle.icon` for macOS builds.
|
|
#[serde(default)]
|
|
pub icon: Option<Vec<String>>,
|
|
|
|
/// Additional resources to bundle.
|
|
/// Overrides `bundle.resources` for macOS builds.
|
|
#[serde(default)]
|
|
pub resources: Option<Vec<String>>,
|
|
|
|
/// Copyright notice.
|
|
/// Overrides `bundle.copyright` for macOS builds.
|
|
#[serde(default)]
|
|
pub copyright: Option<String>,
|
|
|
|
/// Short description.
|
|
/// Overrides `bundle.short_description` for macOS builds.
|
|
#[serde(default)]
|
|
pub short_description: Option<String>,
|
|
|
|
/// Long description.
|
|
/// Overrides `bundle.long_description` for macOS builds.
|
|
#[serde(default)]
|
|
pub long_description: Option<String>,
|
|
|
|
// === macOS bundle settings (previously in bundle.macos) ===
|
|
/// The bundle version string (CFBundleVersion).
|
|
#[serde(default)]
|
|
pub bundle_version: Option<String>,
|
|
|
|
/// The bundle short version string (CFBundleShortVersionString).
|
|
#[serde(default)]
|
|
pub bundle_name: Option<String>,
|
|
|
|
/// The signing identity to use for code signing.
|
|
/// E.g., "Developer ID Application: My Company (TEAMID)"
|
|
#[serde(default)]
|
|
pub signing_identity: Option<String>,
|
|
|
|
/// The provider short name for notarization.
|
|
#[serde(default)]
|
|
pub provider_short_name: Option<String>,
|
|
|
|
/// Path to custom entitlements file for code signing.
|
|
/// This overrides the generated entitlements.
|
|
#[serde(default)]
|
|
pub entitlements_file: Option<String>,
|
|
|
|
/// Exception domain for App Transport Security.
|
|
#[serde(default)]
|
|
pub exception_domain: Option<String>,
|
|
|
|
/// License file to include in DMG.
|
|
#[serde(default)]
|
|
pub license: Option<String>,
|
|
|
|
/// Preserve the hardened runtime version flag.
|
|
/// Setting this to false is useful when using an ad-hoc signature.
|
|
#[serde(default)]
|
|
pub hardened_runtime: Option<bool>,
|
|
|
|
/// Additional files to include in the app bundle.
|
|
/// Maps the path in the Contents directory to the source file path.
|
|
#[serde(default)]
|
|
pub files: HashMap<PathBuf, PathBuf>,
|
|
|
|
// === macOS-specific settings ===
|
|
/// Minimum macOS version (e.g., "11.0").
|
|
#[serde(default)]
|
|
pub minimum_system_version: Option<String>,
|
|
|
|
/// Path to custom Info.plist.
|
|
#[serde(default)]
|
|
pub info_plist: Option<PathBuf>,
|
|
|
|
/// Frameworks to embed.
|
|
#[serde(default)]
|
|
pub frameworks: Vec<String>,
|
|
|
|
/// macOS entitlements.
|
|
#[serde(default)]
|
|
pub entitlements: MacosEntitlements,
|
|
|
|
/// Additional Info.plist keys.
|
|
#[serde(default)]
|
|
pub plist: HashMap<String, serde_json::Value>,
|
|
|
|
/// Raw injection points.
|
|
#[serde(default)]
|
|
pub raw: MacosRawConfig,
|
|
|
|
// === Platform-specific overrides (extend unified config) ===
|
|
/// Additional URL schemes beyond unified `[deep_links]`.schemes.
|
|
/// These are merged with the unified schemes.
|
|
#[serde(default)]
|
|
pub url_schemes: Vec<String>,
|
|
|
|
/// Document types the app can open (uses same format as iOS).
|
|
#[serde(default)]
|
|
pub document_types: Vec<IosDocumentType>,
|
|
|
|
/// Exported type identifiers (custom UTIs).
|
|
#[serde(default)]
|
|
pub exported_type_identifiers: Vec<IosTypeIdentifier>,
|
|
|
|
/// Imported type identifiers.
|
|
#[serde(default)]
|
|
pub imported_type_identifiers: Vec<IosTypeIdentifier>,
|
|
|
|
/// App category for the Mac App Store.
|
|
/// E.g., "public.app-category.productivity"
|
|
#[serde(default)]
|
|
pub category: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct MacosEntitlements {
|
|
/// Enable App Sandbox.
|
|
#[serde(default, rename = "app-sandbox")]
|
|
pub app_sandbox: Option<bool>,
|
|
|
|
/// User-selected file access (read-write).
|
|
#[serde(default, rename = "files-user-selected")]
|
|
pub files_user_selected: Option<bool>,
|
|
|
|
/// User-selected file access (read-only).
|
|
#[serde(default, rename = "files-user-selected-readonly")]
|
|
pub files_user_selected_readonly: Option<bool>,
|
|
|
|
/// Outgoing network connections.
|
|
#[serde(default, rename = "network-client")]
|
|
pub network_client: Option<bool>,
|
|
|
|
/// Incoming network connections.
|
|
#[serde(default, rename = "network-server")]
|
|
pub network_server: Option<bool>,
|
|
|
|
/// Camera access.
|
|
#[serde(default)]
|
|
pub camera: Option<bool>,
|
|
|
|
/// Microphone access.
|
|
#[serde(default)]
|
|
pub microphone: Option<bool>,
|
|
|
|
/// USB access.
|
|
#[serde(default)]
|
|
pub usb: Option<bool>,
|
|
|
|
/// Bluetooth access.
|
|
#[serde(default)]
|
|
pub bluetooth: Option<bool>,
|
|
|
|
/// Printing.
|
|
#[serde(default)]
|
|
pub print: Option<bool>,
|
|
|
|
/// Location services.
|
|
#[serde(default)]
|
|
pub location: Option<bool>,
|
|
|
|
/// Address book access.
|
|
#[serde(default)]
|
|
pub addressbook: Option<bool>,
|
|
|
|
/// Calendars access.
|
|
#[serde(default)]
|
|
pub calendars: Option<bool>,
|
|
|
|
/// Disable library validation.
|
|
#[serde(default, rename = "disable-library-validation")]
|
|
pub disable_library_validation: Option<bool>,
|
|
|
|
/// Allow JIT.
|
|
#[serde(default, rename = "allow-jit")]
|
|
pub allow_jit: Option<bool>,
|
|
|
|
/// Allow unsigned executable memory.
|
|
#[serde(default, rename = "allow-unsigned-executable-memory")]
|
|
pub allow_unsigned_executable_memory: Option<bool>,
|
|
|
|
/// Additional entitlements.
|
|
#[serde(flatten)]
|
|
pub additional: HashMap<String, serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct MacosRawConfig {
|
|
/// Raw XML to inject into Info.plist.
|
|
#[serde(default)]
|
|
pub info_plist: Option<String>,
|
|
|
|
/// Raw XML to inject into entitlements.plist.
|
|
#[serde(default)]
|
|
pub entitlements: Option<String>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Windows Configuration
|
|
// ============================================================================
|
|
|
|
/// Windows-specific configuration.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [windows]
|
|
/// identifier = "com.example.myapp.windows" # Override bundle.identifier for Windows
|
|
///
|
|
/// # Windows installer settings (previously in [bundle.windows])
|
|
/// [windows.nsis]
|
|
/// install_mode = "PerMachine"
|
|
///
|
|
/// [windows.wix]
|
|
/// language = [["en-US", null]]
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct WindowsConfig {
|
|
// === Bundle settings (override [bundle] section) ===
|
|
/// The app's identifier (e.g., "com.example.myapp").
|
|
/// Overrides `bundle.identifier` for Windows builds.
|
|
#[serde(default)]
|
|
pub identifier: Option<String>,
|
|
|
|
/// The app's publisher.
|
|
/// Overrides `bundle.publisher` for Windows builds.
|
|
#[serde(default)]
|
|
pub publisher: Option<String>,
|
|
|
|
/// Icons for the app.
|
|
/// Overrides `bundle.icon` for Windows builds.
|
|
#[serde(default)]
|
|
pub icon: Option<Vec<String>>,
|
|
|
|
/// Additional resources to bundle.
|
|
/// Overrides `bundle.resources` for Windows builds.
|
|
#[serde(default)]
|
|
pub resources: Option<Vec<String>>,
|
|
|
|
/// Copyright notice.
|
|
/// Overrides `bundle.copyright` for Windows builds.
|
|
#[serde(default)]
|
|
pub copyright: Option<String>,
|
|
|
|
/// App category.
|
|
/// Overrides `bundle.category` for Windows builds.
|
|
#[serde(default)]
|
|
pub category: Option<String>,
|
|
|
|
/// Short description.
|
|
/// Overrides `bundle.short_description` for Windows builds.
|
|
#[serde(default)]
|
|
pub short_description: Option<String>,
|
|
|
|
/// Long description.
|
|
/// Overrides `bundle.long_description` for Windows builds.
|
|
#[serde(default)]
|
|
pub long_description: Option<String>,
|
|
|
|
// === Windows bundle settings (previously in bundle.windows) ===
|
|
/// Digest algorithm for code signing.
|
|
#[serde(default)]
|
|
pub digest_algorithm: Option<String>,
|
|
|
|
/// Certificate thumbprint for code signing.
|
|
#[serde(default)]
|
|
pub certificate_thumbprint: Option<String>,
|
|
|
|
/// Timestamp server URL for code signing.
|
|
#[serde(default)]
|
|
pub timestamp_url: Option<String>,
|
|
|
|
/// Use TSP (RFC 3161) timestamp.
|
|
#[serde(default)]
|
|
pub tsp: Option<bool>,
|
|
|
|
/// WiX installer settings.
|
|
#[serde(default)]
|
|
pub wix: Option<WindowsWixSettings>,
|
|
|
|
/// NSIS installer settings.
|
|
#[serde(default)]
|
|
pub nsis: Option<WindowsNsisSettings>,
|
|
|
|
/// Path to custom Windows icon.
|
|
#[serde(default)]
|
|
pub icon_path: Option<PathBuf>,
|
|
|
|
/// WebView2 installation mode.
|
|
#[serde(default)]
|
|
pub webview_install_mode: Option<WindowsWebviewInstallMode>,
|
|
|
|
/// Allow downgrades when installing.
|
|
#[serde(default)]
|
|
pub allow_downgrades: Option<bool>,
|
|
|
|
/// Custom sign command.
|
|
#[serde(default)]
|
|
pub sign_command: Option<WindowsSignCommand>,
|
|
|
|
// === Windows-specific settings ===
|
|
/// UWP/MSIX capabilities.
|
|
#[serde(default)]
|
|
pub capabilities: Vec<String>,
|
|
|
|
/// Restricted capabilities.
|
|
#[serde(default)]
|
|
pub restricted_capabilities: Vec<String>,
|
|
|
|
/// Device capabilities.
|
|
#[serde(default)]
|
|
pub device_capabilities: Vec<String>,
|
|
}
|
|
|
|
/// WiX installer settings.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct WindowsWixSettings {
|
|
/// Languages and their locale paths.
|
|
#[serde(default)]
|
|
pub language: Vec<(String, Option<PathBuf>)>,
|
|
|
|
/// Path to custom WiX template.
|
|
#[serde(default)]
|
|
pub template: Option<PathBuf>,
|
|
|
|
/// WiX fragment files to include.
|
|
#[serde(default)]
|
|
pub fragment_paths: Vec<PathBuf>,
|
|
|
|
/// Component group references.
|
|
#[serde(default)]
|
|
pub component_group_refs: Vec<String>,
|
|
|
|
/// Component references.
|
|
#[serde(default)]
|
|
pub component_refs: Vec<String>,
|
|
|
|
/// Feature group references.
|
|
#[serde(default)]
|
|
pub feature_group_refs: Vec<String>,
|
|
|
|
/// Feature references.
|
|
#[serde(default)]
|
|
pub feature_refs: Vec<String>,
|
|
|
|
/// Merge module references.
|
|
#[serde(default)]
|
|
pub merge_refs: Vec<String>,
|
|
|
|
/// Skip WebView2 installation.
|
|
#[serde(default)]
|
|
pub skip_webview_install: Option<bool>,
|
|
|
|
/// License file path.
|
|
#[serde(default)]
|
|
pub license: Option<PathBuf>,
|
|
|
|
/// Enable elevated update task.
|
|
#[serde(default)]
|
|
pub enable_elevated_update_task: Option<bool>,
|
|
|
|
/// Banner image path.
|
|
#[serde(default)]
|
|
pub banner_path: Option<PathBuf>,
|
|
|
|
/// Dialog image path.
|
|
#[serde(default)]
|
|
pub dialog_image_path: Option<PathBuf>,
|
|
|
|
/// FIPS compliant mode.
|
|
#[serde(default)]
|
|
pub fips_compliant: Option<bool>,
|
|
|
|
/// MSI version string.
|
|
#[serde(default)]
|
|
pub version: Option<String>,
|
|
|
|
/// MSI upgrade code (GUID).
|
|
#[serde(default)]
|
|
#[schemars(with = "Option<String>")]
|
|
pub upgrade_code: Option<uuid::Uuid>,
|
|
}
|
|
|
|
/// NSIS installer settings.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct WindowsNsisSettings {
|
|
/// Path to custom NSIS template.
|
|
#[serde(default)]
|
|
pub template: Option<PathBuf>,
|
|
|
|
/// License file path.
|
|
#[serde(default)]
|
|
pub license: Option<PathBuf>,
|
|
|
|
/// Header image path.
|
|
#[serde(default)]
|
|
pub header_image: Option<PathBuf>,
|
|
|
|
/// Sidebar image path.
|
|
#[serde(default)]
|
|
pub sidebar_image: Option<PathBuf>,
|
|
|
|
/// Installer icon path.
|
|
#[serde(default)]
|
|
pub installer_icon: Option<PathBuf>,
|
|
|
|
/// Installation mode: "CurrentUser", "PerMachine", or "Both".
|
|
#[serde(default)]
|
|
pub install_mode: Option<String>,
|
|
|
|
/// Languages to include.
|
|
#[serde(default)]
|
|
pub languages: Option<Vec<String>>,
|
|
|
|
/// Custom language files.
|
|
#[serde(default)]
|
|
pub custom_language_files: Option<HashMap<String, PathBuf>>,
|
|
|
|
/// Display language selector.
|
|
#[serde(default)]
|
|
pub display_language_selector: Option<bool>,
|
|
|
|
/// Start menu folder name.
|
|
#[serde(default)]
|
|
pub start_menu_folder: Option<String>,
|
|
|
|
/// Installer hooks script path.
|
|
#[serde(default)]
|
|
pub installer_hooks: Option<PathBuf>,
|
|
|
|
/// Minimum WebView2 version required.
|
|
#[serde(default)]
|
|
pub minimum_webview2_version: Option<String>,
|
|
}
|
|
|
|
/// WebView2 installation mode.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
#[serde(tag = "type")]
|
|
pub enum WindowsWebviewInstallMode {
|
|
/// Skip WebView2 installation.
|
|
Skip,
|
|
/// Download bootstrapper.
|
|
DownloadBootstrapper {
|
|
#[serde(default)]
|
|
silent: bool,
|
|
},
|
|
/// Embed bootstrapper.
|
|
EmbedBootstrapper {
|
|
#[serde(default)]
|
|
silent: bool,
|
|
},
|
|
/// Use offline installer.
|
|
OfflineInstaller {
|
|
#[serde(default)]
|
|
silent: bool,
|
|
},
|
|
/// Use fixed runtime from path.
|
|
FixedRuntime { path: PathBuf },
|
|
}
|
|
|
|
/// Custom sign command for Windows code signing.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
pub struct WindowsSignCommand {
|
|
/// The command to run.
|
|
pub cmd: String,
|
|
/// Command arguments. Use "%1" as placeholder for binary path.
|
|
pub args: Vec<String>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Linux Configuration
|
|
// ============================================================================
|
|
|
|
/// Linux-specific configuration.
|
|
///
|
|
/// Example:
|
|
/// ```toml
|
|
/// [linux]
|
|
/// identifier = "com.example.myapp.linux" # Override bundle.identifier for Linux
|
|
/// categories = ["Utility"]
|
|
///
|
|
/// # Debian package settings (previously in [bundle.deb])
|
|
/// [linux.deb]
|
|
/// depends = ["libwebkit2gtk-4.0-37"]
|
|
/// section = "utils"
|
|
/// ```
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct LinuxConfig {
|
|
// === Bundle settings (override [bundle] section) ===
|
|
/// The app's identifier (e.g., "com.example.myapp").
|
|
/// Overrides `bundle.identifier` for Linux builds.
|
|
#[serde(default)]
|
|
pub identifier: Option<String>,
|
|
|
|
/// The app's publisher.
|
|
/// Overrides `bundle.publisher` for Linux builds.
|
|
#[serde(default)]
|
|
pub publisher: Option<String>,
|
|
|
|
/// Icons for the app.
|
|
/// Overrides `bundle.icon` for Linux builds.
|
|
#[serde(default)]
|
|
pub icon: Option<Vec<String>>,
|
|
|
|
/// Additional resources to bundle.
|
|
/// Overrides `bundle.resources` for Linux builds.
|
|
#[serde(default)]
|
|
pub resources: Option<Vec<String>>,
|
|
|
|
/// Copyright notice.
|
|
/// Overrides `bundle.copyright` for Linux builds.
|
|
#[serde(default)]
|
|
pub copyright: Option<String>,
|
|
|
|
/// App category.
|
|
/// Overrides `bundle.category` for Linux builds.
|
|
#[serde(default)]
|
|
pub category: Option<String>,
|
|
|
|
/// Short description.
|
|
/// Overrides `bundle.short_description` for Linux builds.
|
|
#[serde(default)]
|
|
pub short_description: Option<String>,
|
|
|
|
/// Long description.
|
|
/// Overrides `bundle.long_description` for Linux builds.
|
|
#[serde(default)]
|
|
pub long_description: Option<String>,
|
|
|
|
// === Debian package settings (previously in bundle.deb) ===
|
|
/// Debian-specific package settings.
|
|
#[serde(default)]
|
|
pub deb: Option<LinuxDebSettings>,
|
|
|
|
// === Linux-specific settings ===
|
|
/// Flatpak sandbox permissions.
|
|
#[serde(default)]
|
|
pub flatpak_permissions: Vec<String>,
|
|
|
|
/// D-Bus interfaces to access.
|
|
#[serde(default)]
|
|
pub dbus_access: Vec<String>,
|
|
|
|
/// Desktop entry categories.
|
|
#[serde(default)]
|
|
pub categories: Vec<String>,
|
|
|
|
/// Desktop entry keywords.
|
|
#[serde(default)]
|
|
pub keywords: Vec<String>,
|
|
|
|
/// MIME types the app can handle.
|
|
#[serde(default)]
|
|
pub mime_types: Vec<String>,
|
|
}
|
|
|
|
/// Debian package settings.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
|
|
pub struct LinuxDebSettings {
|
|
/// Package dependencies.
|
|
#[serde(default)]
|
|
pub depends: Option<Vec<String>>,
|
|
|
|
/// Recommended packages.
|
|
#[serde(default)]
|
|
pub recommends: Option<Vec<String>>,
|
|
|
|
/// Packages this provides.
|
|
#[serde(default)]
|
|
pub provides: Option<Vec<String>>,
|
|
|
|
/// Package conflicts.
|
|
#[serde(default)]
|
|
pub conflicts: Option<Vec<String>>,
|
|
|
|
/// Packages this replaces.
|
|
#[serde(default)]
|
|
pub replaces: Option<Vec<String>>,
|
|
|
|
/// Additional files to include. Maps package path to source path.
|
|
#[serde(default)]
|
|
pub files: HashMap<PathBuf, PathBuf>,
|
|
|
|
/// Path to custom desktop template.
|
|
#[serde(default)]
|
|
pub desktop_template: Option<PathBuf>,
|
|
|
|
/// Debian section (e.g., "utils", "web").
|
|
#[serde(default)]
|
|
pub section: Option<String>,
|
|
|
|
/// Package priority ("required", "important", "standard", "optional", "extra").
|
|
#[serde(default)]
|
|
pub priority: Option<String>,
|
|
|
|
/// Path to changelog file.
|
|
#[serde(default)]
|
|
pub changelog: Option<PathBuf>,
|
|
|
|
/// Pre-install script path.
|
|
#[serde(default)]
|
|
pub pre_install_script: Option<PathBuf>,
|
|
|
|
/// Post-install script path.
|
|
#[serde(default)]
|
|
pub post_install_script: Option<PathBuf>,
|
|
|
|
/// Pre-remove script path.
|
|
#[serde(default)]
|
|
pub pre_remove_script: Option<PathBuf>,
|
|
|
|
/// Post-remove script path.
|
|
#[serde(default)]
|
|
pub post_remove_script: Option<PathBuf>,
|
|
}
|
|
|
|
// ============================================================================
|
|
// Schema Generation
|
|
// ============================================================================
|
|
|
|
/// Generate a JSON schema for the complete Dioxus.toml configuration.
|
|
///
|
|
/// This can be used for IDE autocomplete when editing Dioxus.toml files.
|
|
/// The schema includes all configuration: application, web, bundle, permissions,
|
|
/// platform-specific settings, and more.
|
|
///
|
|
/// Note: Default values are stripped and allOf wrappers simplified to prevent
|
|
/// stack overflow in some TOML LSP implementations (e.g., Taplo's WASM build).
|
|
pub fn generate_manifest_schema() -> schemars::schema::RootSchema {
|
|
let mut schema = schemars::schema_for!(super::DioxusConfig);
|
|
|
|
// Simplify schema to prevent Taplo WASM LSP stack overflow.
|
|
// 1. Strip default values (large nested objects cause issues)
|
|
// 2. Simplify allOf wrappers around single $refs
|
|
simplify_schema(&mut schema.schema);
|
|
for def in schema.definitions.values_mut() {
|
|
if let schemars::schema::Schema::Object(obj) = def {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
|
|
schema
|
|
}
|
|
|
|
/// Recursively simplify a schema object for LSP compatibility.
|
|
/// - Removes default values (large nested objects cause stack overflow)
|
|
/// - Simplifies `allOf: [$ref]` to just `$ref` (reduces recursion depth)
|
|
fn simplify_schema(schema: &mut schemars::schema::SchemaObject) {
|
|
// Remove the default value from this schema
|
|
schema.metadata().default = None;
|
|
|
|
// Simplify allOf with single $ref: { allOf: [{ $ref: "..." }] } -> { $ref: "..." }
|
|
let mut ref_to_promote = None;
|
|
if let Some(subschemas) = &schema.subschemas {
|
|
if let Some(all_of) = &subschemas.all_of {
|
|
if all_of.len() == 1 {
|
|
if let schemars::schema::Schema::Object(inner) = &all_of[0] {
|
|
if inner.reference.is_some()
|
|
&& inner.instance_type.is_none()
|
|
&& inner.object.is_none()
|
|
&& inner.array.is_none()
|
|
&& inner.subschemas.is_none()
|
|
{
|
|
ref_to_promote = inner.reference.clone();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if let Some(r) = ref_to_promote {
|
|
schema.subschemas = None;
|
|
schema.reference = Some(r);
|
|
}
|
|
|
|
// Process remaining subschemas
|
|
if let Some(subschemas) = &mut schema.subschemas {
|
|
if let Some(all_of) = &mut subschemas.all_of {
|
|
for s in all_of {
|
|
if let schemars::schema::Schema::Object(obj) = s {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
}
|
|
if let Some(any_of) = &mut subschemas.any_of {
|
|
for s in any_of {
|
|
if let schemars::schema::Schema::Object(obj) = s {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
}
|
|
if let Some(one_of) = &mut subschemas.one_of {
|
|
for s in one_of {
|
|
if let schemars::schema::Schema::Object(obj) = s {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process object properties
|
|
if let Some(object) = &mut schema.object {
|
|
for prop in object.properties.values_mut() {
|
|
if let schemars::schema::Schema::Object(obj) = prop {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
if let Some(additional) = &mut object.additional_properties {
|
|
if let schemars::schema::Schema::Object(obj) = additional.as_mut() {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process array items
|
|
if let Some(array) = &mut schema.array {
|
|
if let Some(items) = &mut array.items {
|
|
match items {
|
|
schemars::schema::SingleOrVec::Single(s) => {
|
|
if let schemars::schema::Schema::Object(obj) = s.as_mut() {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
schemars::schema::SingleOrVec::Vec(v) => {
|
|
for s in v {
|
|
if let schemars::schema::Schema::Object(obj) = s {
|
|
simplify_schema(obj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_parse_permissions() {
|
|
let toml = r#"
|
|
[permissions]
|
|
location = { precision = "fine", description = "Track your runs" }
|
|
camera = { description = "Take photos" }
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
permissions: PermissionsConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
let loc = config.permissions.location.unwrap();
|
|
assert_eq!(loc.precision, LocationPrecision::Fine);
|
|
assert_eq!(loc.description, "Track your runs");
|
|
assert!(config.permissions.camera.is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_ios_config() {
|
|
let toml = r#"
|
|
[ios]
|
|
deployment_target = "15.0"
|
|
|
|
[ios.entitlements]
|
|
app-groups = ["group.com.example.app"]
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
ios: IosConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.ios.deployment_target, Some("15.0".to_string()));
|
|
assert_eq!(
|
|
config.ios.entitlements.app_groups,
|
|
vec!["group.com.example.app"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_android_config() {
|
|
let toml = r#"
|
|
[android]
|
|
min_sdk = 24
|
|
target_sdk = 34
|
|
|
|
[android.permissions]
|
|
"android.permission.FOREGROUND_SERVICE" = { description = "Background" }
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
android: AndroidConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.android.min_sdk, Some(24));
|
|
assert!(config
|
|
.android
|
|
.permissions
|
|
.contains_key("android.permission.FOREGROUND_SERVICE"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_deep_links() {
|
|
let toml = r#"
|
|
[deep_links]
|
|
schemes = ["myapp", "com.example.app"]
|
|
hosts = ["example.com", "*.example.com"]
|
|
paths = ["/app/*", "/share/*"]
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
deep_links: DeepLinkConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.deep_links.schemes, vec!["myapp", "com.example.app"]);
|
|
assert_eq!(
|
|
config.deep_links.hosts,
|
|
vec!["example.com", "*.example.com"]
|
|
);
|
|
assert_eq!(config.deep_links.paths, vec!["/app/*", "/share/*"]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_background_modes() {
|
|
let toml = r#"
|
|
[background]
|
|
location = true
|
|
audio = true
|
|
fetch = true
|
|
remote-notifications = true
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
background: BackgroundConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert!(config.background.location);
|
|
assert!(config.background.audio);
|
|
assert!(config.background.fetch);
|
|
assert!(config.background.remote_notifications);
|
|
assert!(!config.background.voip);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_ios_url_schemes_and_background() {
|
|
let toml = r#"
|
|
[ios]
|
|
deployment_target = "15.0"
|
|
url_schemes = ["myapp-ios"]
|
|
background_modes = ["location", "fetch", "remote-notification"]
|
|
|
|
[[ios.document_types]]
|
|
name = "My Document"
|
|
extensions = ["mydoc"]
|
|
role = "Editor"
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
ios: IosConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.ios.url_schemes, vec!["myapp-ios"]);
|
|
assert_eq!(
|
|
config.ios.background_modes,
|
|
vec!["location", "fetch", "remote-notification"]
|
|
);
|
|
assert_eq!(config.ios.document_types.len(), 1);
|
|
assert_eq!(config.ios.document_types[0].name, "My Document");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_android_intent_filters() {
|
|
let toml = r#"
|
|
[android]
|
|
min_sdk = 24
|
|
url_schemes = ["myapp-android"]
|
|
foreground_service_types = ["location", "mediaPlayback"]
|
|
|
|
[[android.intent_filters]]
|
|
actions = ["android.intent.action.VIEW"]
|
|
categories = ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"]
|
|
auto_verify = true
|
|
|
|
[[android.intent_filters.data]]
|
|
scheme = "https"
|
|
host = "example.com"
|
|
path_prefix = "/app"
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
android: AndroidConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.android.url_schemes, vec!["myapp-android"]);
|
|
assert_eq!(
|
|
config.android.foreground_service_types,
|
|
vec!["location", "mediaPlayback"]
|
|
);
|
|
assert_eq!(config.android.intent_filters.len(), 1);
|
|
assert!(config.android.intent_filters[0].auto_verify);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_macos_url_schemes() {
|
|
let toml = r#"
|
|
[macos]
|
|
minimum_system_version = "11.0"
|
|
url_schemes = ["myapp-macos"]
|
|
category = "public.app-category.productivity"
|
|
|
|
[[macos.document_types]]
|
|
name = "My Format"
|
|
extensions = ["myfmt"]
|
|
"#;
|
|
|
|
#[derive(Deserialize)]
|
|
struct Config {
|
|
macos: MacosConfig,
|
|
}
|
|
|
|
let config: Config = toml::from_str(toml).unwrap();
|
|
assert_eq!(config.macos.url_schemes, vec!["myapp-macos"]);
|
|
assert_eq!(
|
|
config.macos.category,
|
|
Some("public.app-category.productivity".to_string())
|
|
);
|
|
assert_eq!(config.macos.document_types.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_generate_schema() {
|
|
let schema = generate_manifest_schema();
|
|
let json = serde_json::to_string_pretty(&schema).unwrap();
|
|
|
|
// Verify the schema contains all top-level DioxusConfig types
|
|
assert!(json.contains("ApplicationConfig"));
|
|
assert!(json.contains("WebConfig"));
|
|
assert!(json.contains("BundleConfig"));
|
|
assert!(json.contains("ComponentConfig"));
|
|
assert!(json.contains("PermissionsConfig"));
|
|
assert!(json.contains("DeepLinkConfig"));
|
|
assert!(json.contains("BackgroundConfig"));
|
|
assert!(json.contains("IosConfig"));
|
|
assert!(json.contains("AndroidConfig"));
|
|
assert!(json.contains("MacosConfig"));
|
|
assert!(json.contains("WindowsConfig"));
|
|
assert!(json.contains("LinuxConfig"));
|
|
|
|
// Verify some specific properties exist
|
|
assert!(json.contains("location"));
|
|
assert!(json.contains("camera"));
|
|
assert!(json.contains("deployment_target"));
|
|
assert!(json.contains("min_sdk"));
|
|
|
|
// Verify application config properties
|
|
assert!(json.contains("asset_dir"));
|
|
assert!(json.contains("public_dir"));
|
|
|
|
// Verify web config properties
|
|
assert!(json.contains("pre_compress"));
|
|
assert!(json.contains("wasm_opt"));
|
|
|
|
// Verify bundle config properties
|
|
assert!(json.contains("identifier"));
|
|
assert!(json.contains("publisher"));
|
|
}
|
|
}
|