tauri_plugin_licenseseat/
lib.rs1pub use licenseseat;
65
66mod commands;
67mod config;
68mod error;
69
70use tauri::{
71 Emitter, Manager, Runtime,
72 plugin::{Builder, TauriPlugin},
73};
74
75pub use config::PluginConfig;
76pub use error::{Error, Result};
77
78fn resolve_env_placeholder(value: String) -> String {
79 if let Some(name) = value.strip_prefix('$') {
80 std::env::var(name).unwrap_or(value)
81 } else {
82 value
83 }
84}
85
86fn resolve_optional_env_placeholder(value: Option<String>) -> Option<String> {
87 value.map(resolve_env_placeholder)
88}
89
90pub fn init<R: Runtime>() -> TauriPlugin<R, PluginConfig> {
103 Builder::<R, PluginConfig>::new("licenseseat")
104 .setup(|app, api| {
105 let config = api.config().clone();
106 let api_key = resolve_env_placeholder(config.api_key.clone());
107 let product_slug = resolve_env_placeholder(config.product_slug.clone());
108 let api_base_url = resolve_optional_env_placeholder(config.api_base_url.clone());
109 let storage_prefix = resolve_optional_env_placeholder(config.storage_prefix.clone());
110 let storage_path = resolve_optional_env_placeholder(config.storage_path.clone());
111 let device_identifier =
112 resolve_optional_env_placeholder(config.device_identifier.clone());
113 let signing_public_key =
114 resolve_optional_env_placeholder(config.signing_public_key.clone());
115 let signing_key_id = resolve_optional_env_placeholder(config.signing_key_id.clone());
116 let app_version = resolve_optional_env_placeholder(
117 config
118 .app_version
119 .clone()
120 .or_else(|| Some(app.package_info().version.to_string())),
121 );
122 let app_build = resolve_optional_env_placeholder(
123 config
124 .app_build
125 .clone()
126 .or_else(|| Some(app.package_info().name.clone())),
127 );
128
129 let offline_fallback_mode = match config.offline_fallback_mode.as_deref() {
130 Some("always")
131 | Some("allow_offline")
132 | Some("offline_first")
133 | Some("offlineFirst") => licenseseat::OfflineFallbackMode::Always,
134 _ => licenseseat::OfflineFallbackMode::NetworkOnly,
135 };
136
137 let sdk_config = licenseseat::Config {
139 api_key,
140 product_slug,
141 api_base_url: api_base_url
142 .unwrap_or_else(|| "https://licenseseat.com/api/v1".into()),
143 storage_prefix: storage_prefix.unwrap_or_else(|| "licenseseat_".into()),
144 storage_path: storage_path.map(Into::into),
145 device_identifier,
146 signing_public_key,
147 signing_key_id,
148 auto_validate_interval: std::time::Duration::from_secs(
149 config.auto_validate_interval.unwrap_or(3600),
150 ),
151 heartbeat_interval: std::time::Duration::from_secs(
152 config.heartbeat_interval.unwrap_or(300),
153 ),
154 network_recheck_interval: std::time::Duration::from_secs(
155 config.network_recheck_interval.unwrap_or(30),
156 ),
157 request_timeout: std::time::Duration::from_secs(
158 config.timeout_seconds.unwrap_or(30),
159 ),
160 verify_ssl: config.verify_ssl.unwrap_or(true),
161 offline_fallback_mode,
162 offline_token_refresh_interval: std::time::Duration::from_secs(
163 config.offline_token_refresh_interval.unwrap_or(72 * 3600),
164 ),
165 enable_legacy_offline_tokens: config.enable_legacy_offline_tokens.unwrap_or(false),
166 max_offline_days: config.max_offline_days.unwrap_or(0),
167 debug: config.debug.unwrap_or(false),
168 telemetry_enabled: config.telemetry_enabled.unwrap_or(true),
169 app_version,
170 app_build,
171 ..Default::default()
172 };
173
174 app.manage(sdk_config);
176 let sdk =
177 licenseseat::LicenseSeat::new(app.state::<licenseseat::Config>().inner().clone());
178 let event_sdk = sdk.clone();
179 let app_handle = app.clone();
180 tauri::async_runtime::spawn(async move {
181 let mut rx = event_sdk.subscribe();
182 while let Ok(event) = rx.recv().await {
183 let event_name =
184 format!("licenseseat://{}", event.kind.to_string().replace(':', "-"));
185 let payload = commands::event_payload_to_json(event.data);
186 let _ = app_handle.emit(&event_name, payload);
187 }
188 });
189 app.manage(sdk);
190
191 tracing::info!("LicenseSeat plugin initialized");
192 Ok(())
193 })
194 .invoke_handler(tauri::generate_handler![
195 commands::activate,
196 commands::validate_key,
197 commands::validate,
198 commands::deactivate,
199 commands::deactivate_key,
200 commands::heartbeat,
201 commands::heartbeat_key,
202 commands::get_status,
203 commands::get_client_status,
204 commands::is_online,
205 commands::get_fingerprint,
206 commands::restore_license,
207 commands::health,
208 commands::check_entitlement,
209 commands::get_entitlements,
210 commands::has_entitlement,
211 commands::get_license,
212 commands::get_state,
213 commands::get_admin_snapshot,
214 commands::get_latest_release,
215 commands::list_releases,
216 commands::generate_download_token,
217 commands::generate_offline_token,
218 commands::verify_offline_token,
219 commands::checkout_machine_file,
220 commands::fetch_signing_key,
221 commands::sync_offline_assets,
222 commands::verify_machine_file,
223 commands::reset,
224 ])
225 .build()
226}