1package com.parseable.android.data.model
3import kotlinx.serialization.SerialName
4import kotlinx.serialization.Serializable
5import kotlinx.serialization.json.JsonElement
6import kotlinx.serialization.json.JsonObject
9 * Server connection configuration stored in DataStore.
11data class ServerConfig(
12 val serverUrl: String,
15 val useTls: Boolean = true,
19 * Represents a log stream entry returned by GET /api/v1/logstream
27 * Query request body sent to POST /api/v1/query
30data class QueryRequest(
32 val startTime: String,
37 * Stream stats from GET /api/v1/logstream/{name}/stats
40data class StreamStats(
41 val ingestion: IngestionStats? = null,
42 val storage: StorageStats? = null,
43 val stream: String? = null,
44 val time: String? = null,
48data class IngestionStats(
49 val count: Long? = null,
50 val size: String? = null,
51 val format: String? = null,
52 @SerialName("lifetime_count")
53 val lifetimeCount: Long? = null,
54 @SerialName("lifetime_size")
55 val lifetimeSize: String? = null,
56 @SerialName("deleted_count")
57 val deletedCount: Long? = null,
58 @SerialName("deleted_size")
59 val deletedSize: String? = null,
63data class StorageStats(
64 val size: String? = null,
65 val format: String? = null,
66 @SerialName("lifetime_size")
67 val lifetimeSize: String? = null,
68 @SerialName("deleted_size")
69 val deletedSize: String? = null,
73 * Schema field info from GET /api/v1/logstream/{name}/schema
76data class StreamSchema(
77 val fields: List<SchemaField> = emptyList(),
81data class SchemaField(
83 @SerialName("data_type")
84 val dataType: JsonElement? = null,
85 val nullable: Boolean? = null,
86 val dict_id: Long? = null,
87 val dict_is_ordered: Boolean? = null,
88 val metadata: JsonObject? = null,
92 * Retention config from GET /api/v1/logstream/{name}/retention
95data class RetentionConfig(
96 val description: String? = null,
97 val duration: String? = null,
98 val action: String? = null,
102 * About info from GET /api/v1/about
106 val version: String? = null,
107 val commit: String? = null,
108 @SerialName("deploymentId")
109 val deploymentId: String? = null,
110 val license: JsonObject? = null,
111 val mode: String? = null,
112 val staging: String? = null,
113 val store: JsonObject? = null,
114 @SerialName("grpcPort")
115 val grpcPort: Int? = null,
116 val analytics: JsonObject? = null,
117 @SerialName("queryEngine")
118 val queryEngine: String? = null,
122 * Alert summary returned by GET /api/v1/alerts.
124 * The global alerts endpoint returns summary objects with fields like `title`, `state`,
125 * `severity`, and `datasets`. The per-stream endpoint uses `name` and `alerts[]` nesting.
126 * Both shapes are supported via optional fields.
130 val id: String? = null,
131 val version: String? = null,
132 // Per-stream alert format uses "name"; global summary uses "title"
133 val name: String? = null,
134 val title: String? = null,
135 val message: String? = null,
136 val rule: JsonObject? = null,
137 val targets: List<JsonObject> = emptyList(),
138 // Per-stream alert format
139 val stream: String? = null,
140 val enabled: Boolean? = null,
141 // Global summary fields
142 val state: String? = null,
143 val severity: String? = null,
144 @SerialName("alertType")
145 val alertType: String? = null,
146 @SerialName("notificationState")
147 val notificationState: String? = null,
148 val created: String? = null,
149 @SerialName("lastTriggeredAt")
150 val lastTriggeredAt: String? = null,
151 val tags: List<String> = emptyList(),
152 val datasets: List<String> = emptyList(),
154 /** Best-effort display name from either response format. */
155 val displayName: String get() = title ?: name ?: "Unnamed Alert"
157 /** Whether the alert is active, derived from either response format. */
158 val isEnabled: Boolean get() = when {
159 state != null -> state != "Disabled"
160 enabled != null -> enabled
164 /** Stream(s) this alert is configured for. */
165 val streamDisplay: String? get() = when {
166 datasets.isNotEmpty() -> datasets.joinToString(", ")
167 stream != null -> stream
173 * Result wrapper for API calls
175sealed class ApiResult<out T> {
176 data class Success<T>(val data: T) : ApiResult<T>()
177 data class Error(val message: String, val code: Int = 0) : ApiResult<Nothing>() {
178 val isUnauthorized: Boolean get() = code == 401
179 val isNotFound: Boolean get() = code == 404
180 val isServerError: Boolean get() = code in 500..599
181 val isNetworkError: Boolean get() = code == 0
183 val userMessage: String get() = when {
184 code == 401 -> "Session expired. Please log in again."
185 code == 403 -> "Permission denied."
186 code == 404 -> "Resource not found. It may have been deleted."
187 code == 429 -> "Too many requests. Please wait and try again."
188 code in 500..599 -> "Server error ($code). Please try again later."
190 message.contains("timeout", ignoreCase = true) -> "Connection timed out. Check your network."
191 message.contains("Unable to resolve host", ignoreCase = true) -> "No internet connection."
192 message.contains("Connection refused", ignoreCase = true) -> "Server is unreachable."
193 else -> "Network error: $message"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list