diff --git a/Cargo.toml b/Cargo.toml
index a9337f7..54f3fba 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "tauri-plugin-aptabase"
version = "0.5.1"
license = "MIT"
description = "Tauri Plugin for Aptabase: Open Source, Privacy-First and Simple Analytics for Mobile, Desktop and Web Apps"
-authors = [ "Guilherme Oenning" ]
+authors = ["Guilherme Oenning"]
edition = "2021"
rust-version = "1.70"
readme = "README.md"
@@ -12,19 +12,16 @@ exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"]
links = "tauri-plugin-aptabase"
[dependencies]
-tauri = { version = "2.0.0-beta.2" }
+tauri = "2.1"
tokio = "1"
-futures = "0"
-serde = "1.0"
-serde_json = "1.0"
-thiserror = "1.0"
-reqwest = { version = "0.11", features = ["json"] }
-time = { version = "0.3", features = ["formatting"]}
+serde = "1"
+serde_json = "1"
+reqwest = { version = "0.12", features = ["json"] }
+time = { version = "0.3", features = ["formatting"] }
os_info = "3"
-uuid = "1"
rand = "0.8"
log = "0.4"
-sys-locale = "0.3.1"
+sys-locale = "0.3"
[build-dependencies]
-tauri-plugin = { version = "2.0.0-beta.1", features = ["build"] }
+tauri-plugin = { version = "2.0", features = ["build"] }
diff --git a/build.rs b/build.rs
index a11838f..b6b7b1a 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,5 @@
const COMMANDS: &[&str] = &["track_event"];
fn main() {
- tauri_plugin::Builder::new(COMMANDS).build();
+ tauri_plugin::Builder::new(COMMANDS).build();
}
diff --git a/examples/helloworld/package.json b/examples/helloworld/package.json
index be2b571..2c6fd20 100644
--- a/examples/helloworld/package.json
+++ b/examples/helloworld/package.json
@@ -11,7 +11,7 @@
"tauri": "tauri"
},
"dependencies": {
- "@tauri-apps/api": "^2.0.0-alpha.11",
+ "@tauri-apps/api": "^2.1.1",
"@aptabase/tauri": "file:../../"
},
"devDependencies": {
@@ -19,6 +19,6 @@
"internal-ip": "^7.0.0",
"svelte": "^3.49.0",
"vite": "^3.0.2",
- "@tauri-apps/cli": "^2.0.0-alpha.17"
+ "@tauri-apps/cli": "^2.1.0"
}
-}
\ No newline at end of file
+}
diff --git a/examples/helloworld/src-tauri/Cargo.toml b/examples/helloworld/src-tauri/Cargo.toml
index e4820a7..619e34e 100644
--- a/examples/helloworld/src-tauri/Cargo.toml
+++ b/examples/helloworld/src-tauri/Cargo.toml
@@ -15,10 +15,10 @@ crate-type = ["staticlib", "cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
-tauri-build = { version = "2.0.0-beta.1", default-features = false , features = [] }
+tauri-build = { version = "2.0", default-features = false, features = [] }
[dependencies]
-tauri = { version = "2.0.0-beta.2", features = [] }
+tauri = { version = "2.1", features = [] }
tauri-plugin-aptabase = { path = "../../../" }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
@@ -26,4 +26,4 @@ serde = { version = "1.0", features = ["derive"] }
[features]
# this feature is used for production builds or when `devUrl` points to the filesystem
# DO NOT REMOVE!!
-custom-protocol = [ "tauri/custom-protocol" ]
+custom-protocol = ["tauri/custom-protocol"]
diff --git a/package.json b/package.json
index ef0f752..2c16439 100644
--- a/package.json
+++ b/package.json
@@ -29,14 +29,14 @@
"package.json"
],
"devDependencies": {
- "@rollup/plugin-node-resolve": "15.2.3",
- "@rollup/plugin-typescript": "11.1.6",
- "@rollup/plugin-terser": "0.4.4",
- "rollup": "4.9.6",
- "typescript": "5.3.3"
+ "@rollup/plugin-node-resolve": "^15.3.0",
+ "@rollup/plugin-typescript": "^12.1.1",
+ "@rollup/plugin-terser": "^0.4.4",
+ "rollup": "^4.27.4",
+ "typescript": "^5.7.2"
},
"dependencies": {
- "@tauri-apps/api": "^2.0.0-alpha.11",
- "tslib": "^2.6.2"
+ "@tauri-apps/api": "^2.1.1",
+ "tslib": "^2.8.1"
}
}
diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md
index 8b4dfdd..3c0486b 100644
--- a/permissions/autogenerated/reference.md
+++ b/permissions/autogenerated/reference.md
@@ -1,10 +1,36 @@
-# Permissions
-## allow-track-event
+## Permission Table
+
+
+
+| Identifier |
+Description |
+
+
+
+
+|
+
+`aptabase:allow-track-event`
+
+ |
+
Enables the track_event command without any pre-configured scope.
-## deny-track-event
+ |
+
+
+
+|
+
+`aptabase:deny-track-event`
+
+ |
+
Denies the track_event command without any pre-configured scope.
+ |
+
+
diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json
index eebaa1c..f13b11b 100644
--- a/permissions/schemas/schema.json
+++ b/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,24 +251,60 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-track-event -> Enables the track_event command without any pre-configured scope.",
+ "description": "MacOS.",
+ "type": "string",
+ "enum": [
+ "macOS"
+ ]
+ },
+ {
+ "description": "Windows.",
+ "type": "string",
+ "enum": [
+ "windows"
+ ]
+ },
+ {
+ "description": "Linux.",
+ "type": "string",
+ "enum": [
+ "linux"
+ ]
+ },
+ {
+ "description": "Android.",
"type": "string",
"enum": [
- "allow-track-event"
+ "android"
]
},
{
- "description": "deny-track-event -> Denies the track_event command without any pre-configured scope.",
+ "description": "iOS.",
"type": "string",
"enum": [
- "deny-track-event"
+ "iOS"
]
}
]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the track_event command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-track-event"
+ },
+ {
+ "description": "Denies the track_event command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-track-event"
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..43d4840
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+newline_style = "Unix"
diff --git a/src/client.rs b/src/client.rs
index 5f3f2a7..5c23ffd 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -1,12 +1,16 @@
-use std::time::{SystemTime, UNIX_EPOCH};
use rand::Rng;
use serde_json::{json, Value};
-use std::{sync::{Arc, Mutex as SyncMutex}, time::Duration};
+use std::time::{SystemTime, UNIX_EPOCH};
+use std::{
+ sync::{Arc, Mutex as SyncMutex},
+ time::Duration,
+};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use crate::{
config::Config,
- sys::{self, SystemProperties}, dispatcher::EventDispatcher,
+ dispatcher::EventDispatcher,
+ sys::{self, SystemProperties},
};
static SESSION_TIMEOUT: Duration = Duration::from_secs(4 * 60 * 60);
@@ -22,7 +26,7 @@ fn new_session_id() -> String {
let id = epoch_in_seconds * 100_000_000 + random;
- return id.to_string();
+ id.to_string()
}
/// A tracking session.
@@ -34,7 +38,7 @@ pub struct TrackingSession {
impl TrackingSession {
fn new() -> Self {
- TrackingSession {
+ Self {
id: new_session_id(),
last_touch_ts: OffsetDateTime::now_utc(),
}
@@ -51,7 +55,6 @@ pub struct AptabaseClient {
}
impl AptabaseClient {
-
/// Creates a new Aptabase client.
pub fn new(config: &Config, app_version: String) -> Self {
let sys_info = sys::get_info();
@@ -59,7 +62,7 @@ impl AptabaseClient {
let is_enabled = !config.app_key.is_empty();
let dispatcher = Arc::new(EventDispatcher::new(config, &sys_info));
- AptabaseClient {
+ Self {
is_enabled,
dispatcher,
session: SyncMutex::new(TrackingSession::new()),
@@ -67,7 +70,7 @@ impl AptabaseClient {
sys_info,
}
}
-
+
/// Starts the event dispatcher loop.
pub(crate) fn start_polling(&self, interval: Duration) {
let dispatcher = self.dispatcher.clone();
@@ -90,7 +93,8 @@ impl AptabaseClient {
} else {
session.last_touch_ts = now;
}
- return session.id.clone();
+
+ session.id.clone()
}
/// Enqueues an event to be sent to the server.
diff --git a/src/commands.rs b/src/commands.rs
index 0755c35..04fdf60 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -1,14 +1,10 @@
-use std::sync::Arc;
use serde_json::Value;
+use std::sync::Arc;
use tauri::{command, State};
use crate::client::AptabaseClient;
#[command]
-pub fn track_event(
- client: State<'_, Arc>,
- name: &str,
- props: Option,
-) {
- client.track_event(name, props);
-}
\ No newline at end of file
+pub fn track_event(client: State<'_, Arc>, name: &str, props: Option) {
+ client.track_event(name, props);
+}
diff --git a/src/config.rs b/src/config.rs
index 1b78d87..1985f11 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -22,13 +22,16 @@ static DEFAULT_FLUSH_INTERVAL: Duration = Duration::from_secs(60);
#[cfg(debug_assertions)]
static DEFAULT_FLUSH_INTERVAL: Duration = Duration::from_secs(2);
-const VALID_REGIONS: &'static [&'static str] = &["US", "EU", "DEV", "SH"];
+const VALID_REGIONS: &[&str] = &["US", "EU", "DEV", "SH"];
impl Config {
pub fn new(app_key: String, opts: InitOptions) -> Self {
let parts = app_key.split("-").collect::>();
if parts.len() != 3 || !VALID_REGIONS.contains(&parts[1]) {
- debug!("The Aptabase App Key '{}' is invalid. Tracking will be disabled.", app_key);
+ debug!(
+ "The Aptabase App Key '{}' is invalid. Tracking will be disabled.",
+ app_key
+ );
return Config::default();
}
@@ -43,24 +46,24 @@ impl Config {
debug!("Host parameter must be defined when using Self-Hosted App Key. Tracking will be disabled.");
return Config::default();
}
- },
+ }
_ => return Config::default(),
};
- Config {
+ Self {
app_key,
ingest_api_url: format!("{}/api/v0/events", base_url).parse().unwrap(),
- flush_interval: opts.flush_interval.clone().unwrap_or(DEFAULT_FLUSH_INTERVAL)
+ flush_interval: opts.flush_interval.unwrap_or(DEFAULT_FLUSH_INTERVAL),
}
}
}
impl Default for Config {
fn default() -> Self {
- return Config {
+ Self {
app_key: String::new(),
ingest_api_url: Url::parse(LOCAL).unwrap(),
flush_interval: DEFAULT_FLUSH_INTERVAL,
- };
+ }
}
}
diff --git a/src/dispatcher.rs b/src/dispatcher.rs
index 76698cb..b4885a4 100644
--- a/src/dispatcher.rs
+++ b/src/dispatcher.rs
@@ -1,8 +1,16 @@
-use std::{collections::VecDeque, time::Duration, cmp::min, sync::{Arc, RwLock}};
+use std::{
+ cmp::min,
+ collections::VecDeque,
+ sync::{Arc, RwLock},
+ time::Duration,
+};
use log::{debug, trace};
-use reqwest::{header::{HeaderMap, HeaderValue}, Url};
-use serde_json::{Value, json};
+use reqwest::{
+ header::{HeaderMap, HeaderValue},
+ Url,
+};
+use serde_json::{json, Value};
use crate::{config::Config, sys::SystemProperties};
@@ -22,17 +30,20 @@ impl EventDispatcher {
headers.insert("App-Key", app_key_header);
headers.insert("Content-Type", HeaderValue::from_static("application/json"));
- let user_agent = format!("{}/{} {}/{} {}", sys.os_name, sys.os_version, sys.engine_name, sys.engine_version, sys.locale);
+ let user_agent = format!(
+ "{}/{} {}/{} {}",
+ sys.os_name, sys.os_version, sys.engine_name, sys.engine_version, sys.locale
+ );
let http_client = reqwest::Client::builder()
.timeout(HTTP_REQUEST_TIMEOUT)
.default_headers(headers)
.user_agent(user_agent)
.build()
.expect("could not build http client");
-
+
let queue = Arc::new(RwLock::new(VecDeque::new()));
- EventDispatcher {
+ Self {
url: config.ingest_api_url.clone(),
queue,
http_client,
@@ -40,7 +51,7 @@ impl EventDispatcher {
}
pub fn is_empty(&self) -> bool {
- let queue = self.queue.read().expect("could not lock queue for reading");
+ let queue = self.queue.read().expect("could not lock queue for reading");
queue.is_empty()
}
@@ -54,7 +65,7 @@ impl EventDispatcher {
queue.extend(events);
}
- fn dequeue_many(&self, max: usize) -> Vec {
+ fn dequeue_many(&self, max: usize) -> Vec {
let mut queue = self.queue.write().expect("could not lock queue");
if queue.is_empty() {
return Vec::new();
@@ -79,26 +90,29 @@ impl EventDispatcher {
}
trace!("preparing {} events to send", events_to_send.len());
-
+
let body = json!(events_to_send);
- let response = self.http_client.post(self.url.clone()).json(&body).send().await;
+ let response = self
+ .http_client
+ .post(self.url.clone())
+ .json(&body)
+ .send()
+ .await;
match response {
- Ok(response) => {
- match response.status().is_success() {
- true => {
- trace!("sent {} tracking events", events_to_send.len());
- },
- false => {
- debug!(
- "failed to track_event with status code {}",
- response.status()
- );
- if response.status().is_server_error() {
- failed_items.extend(events_to_send);
- }
+ Ok(response) => match response.status().is_success() {
+ true => {
+ trace!("sent {} tracking events", events_to_send.len());
+ }
+ false => {
+ debug!(
+ "failed to track_event with status code {}",
+ response.status()
+ );
+ if response.status().is_server_error() {
+ failed_items.extend(events_to_send);
}
}
- }
+ },
Err(err) => {
failed_items.extend(events_to_send);
debug!("failed to track_event: {}", err.to_string());
diff --git a/src/lib.rs b/src/lib.rs
index 663ad91..54469ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,7 +4,7 @@ mod config;
mod dispatcher;
mod sys;
-use std::{panic::PanicInfo, sync::Arc, time::Duration};
+use std::{panic::PanicHookInfo, sync::Arc, time::Duration};
use client::AptabaseClient;
use config::Config;
@@ -27,9 +27,10 @@ pub struct Builder {
options: InitOptions,
}
-pub type PanicHook = Box, String) + 'static + Sync + Send>;
+pub type PanicHook =
+ Box, String) + 'static + Sync + Send>;
-fn get_panic_message(info: &PanicInfo) -> String {
+fn get_panic_message(info: &PanicHookInfo) -> String {
let payload = info.payload();
if let Some(s) = payload.downcast_ref::<&str>() {
return s.to_string();
@@ -37,13 +38,13 @@ fn get_panic_message(info: &PanicInfo) -> String {
return s.to_string();
}
- return format!("{:?}", payload);
+ format!("{:?}", payload)
}
impl Builder {
/// Creates a new builder.
pub fn new(app_key: &str) -> Self {
- Builder {
+ Self {
app_key: app_key.into(),
panic_hook: None,
options: Default::default(),