@muhammedaksam/easiarr 1.3.5 → 1.4.1

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.
Files changed (94) hide show
  1. package/README.md +8 -5
  2. package/dist/index.js +29837 -0
  3. package/package.json +18 -16
  4. package/src/VersionInfo.ts +0 -12
  5. package/src/api/arr-api.ts +0 -508
  6. package/src/api/auto-setup-types.ts +0 -64
  7. package/src/api/bazarr-api.ts +0 -356
  8. package/src/api/cloudflare-api.ts +0 -577
  9. package/src/api/custom-format-api.ts +0 -212
  10. package/src/api/grafana-api.ts +0 -314
  11. package/src/api/heimdall-api.ts +0 -209
  12. package/src/api/homarr-api.ts +0 -296
  13. package/src/api/huntarr-api.ts +0 -622
  14. package/src/api/index.ts +0 -1
  15. package/src/api/jellyfin-api.ts +0 -473
  16. package/src/api/jellyseerr-api.ts +0 -660
  17. package/src/api/maintainerr-api.ts +0 -731
  18. package/src/api/naming-config.ts +0 -93
  19. package/src/api/overseerr-api.ts +0 -513
  20. package/src/api/plex-api.ts +0 -358
  21. package/src/api/portainer-api.ts +0 -467
  22. package/src/api/profilarr-api.ts +0 -380
  23. package/src/api/prowlarr-api.ts +0 -859
  24. package/src/api/qbittorrent-api.ts +0 -339
  25. package/src/api/quality-profile-api.ts +0 -269
  26. package/src/api/tautulli-api.ts +0 -277
  27. package/src/api/uptime-kuma-api.ts +0 -342
  28. package/src/apps/categories.ts +0 -14
  29. package/src/apps/index.ts +0 -2
  30. package/src/apps/registry.ts +0 -1255
  31. package/src/compose/caddy-config.ts +0 -129
  32. package/src/compose/generator.ts +0 -262
  33. package/src/compose/index.ts +0 -3
  34. package/src/compose/templates.ts +0 -78
  35. package/src/compose/traefik-config.ts +0 -185
  36. package/src/config/bookmarks-generator.ts +0 -149
  37. package/src/config/defaults.ts +0 -37
  38. package/src/config/homepage-config.ts +0 -376
  39. package/src/config/index.ts +0 -3
  40. package/src/config/manager.ts +0 -149
  41. package/src/config/recyclarr-config.ts +0 -179
  42. package/src/config/schema.ts +0 -310
  43. package/src/config/slskd-config.ts +0 -85
  44. package/src/config/soularr-config.ts +0 -105
  45. package/src/config/trash-quality-definitions.ts +0 -213
  46. package/src/data/lidarr-custom-formats.ts +0 -127
  47. package/src/data/trash-profiles.ts +0 -326
  48. package/src/docker/client.ts +0 -291
  49. package/src/docker/index.ts +0 -1
  50. package/src/index.ts +0 -77
  51. package/src/structure/manager.ts +0 -128
  52. package/src/ui/App.ts +0 -109
  53. package/src/ui/components/ApplicationSelector.ts +0 -272
  54. package/src/ui/components/FileEditor.ts +0 -91
  55. package/src/ui/components/FooterHint.ts +0 -119
  56. package/src/ui/components/PageLayout.ts +0 -152
  57. package/src/ui/components/UpdateNotification.ts +0 -101
  58. package/src/ui/index.ts +0 -1
  59. package/src/ui/screens/AdvancedSettings.ts +0 -181
  60. package/src/ui/screens/ApiKeyViewer.ts +0 -500
  61. package/src/ui/screens/AppConfigurator.ts +0 -731
  62. package/src/ui/screens/AppManager.ts +0 -276
  63. package/src/ui/screens/CloudflaredSetup.ts +0 -974
  64. package/src/ui/screens/ContainerControl.ts +0 -579
  65. package/src/ui/screens/FullAutoSetup.ts +0 -1719
  66. package/src/ui/screens/HomepageSetup.ts +0 -306
  67. package/src/ui/screens/JellyfinSetup.ts +0 -471
  68. package/src/ui/screens/JellyseerrSetup.ts +0 -612
  69. package/src/ui/screens/LogsViewer.ts +0 -468
  70. package/src/ui/screens/MainMenu.ts +0 -288
  71. package/src/ui/screens/MonitorDashboard.ts +0 -866
  72. package/src/ui/screens/ProwlarrSetup.ts +0 -623
  73. package/src/ui/screens/QBittorrentSetup.ts +0 -268
  74. package/src/ui/screens/QuickSetup.ts +0 -1161
  75. package/src/ui/screens/RecyclarrSetup.ts +0 -418
  76. package/src/ui/screens/SecretsEditor.ts +0 -214
  77. package/src/ui/screens/SettingsScreen.ts +0 -605
  78. package/src/ui/screens/TRaSHProfileSetup.ts +0 -395
  79. package/src/ui/screens/index.ts +0 -4
  80. package/src/util/arch.ts +0 -78
  81. package/src/utils/browser.ts +0 -26
  82. package/src/utils/categories.ts +0 -59
  83. package/src/utils/debug.ts +0 -91
  84. package/src/utils/env.ts +0 -137
  85. package/src/utils/logs.ts +0 -118
  86. package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -101
  87. package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -90
  88. package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -44
  89. package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -107
  90. package/src/utils/migrations.ts +0 -164
  91. package/src/utils/password.ts +0 -42
  92. package/src/utils/unraid.ts +0 -101
  93. package/src/utils/update-checker.ts +0 -210
  94. package/src/utils/url-utils.ts +0 -38
@@ -1,209 +0,0 @@
1
- /**
2
- * Heimdall API Client
3
- * Handles Heimdall dashboard auto-setup with application tiles
4
- */
5
-
6
- import { debugLog } from "../utils/debug"
7
- import type { IAutoSetupClient, AutoSetupOptions, AutoSetupResult } from "./auto-setup-types"
8
- import type { AppConfig } from "../config/schema"
9
- import { getApp } from "../apps/registry"
10
-
11
- interface HeimdallApp {
12
- id?: number
13
- title: string
14
- url: string
15
- colour?: string
16
- icon?: string
17
- appdescription?: string
18
- pinned?: boolean
19
- }
20
-
21
- export class HeimdallClient implements IAutoSetupClient {
22
- private host: string
23
- private port: number
24
-
25
- constructor(host: string, port: number = 80) {
26
- this.host = host
27
- this.port = port
28
- }
29
-
30
- /**
31
- * Get base URL for Heimdall
32
- */
33
- private get baseUrl(): string {
34
- return `http://${this.host}:${this.port}`
35
- }
36
-
37
- /**
38
- * Check if Heimdall is reachable
39
- */
40
- async isHealthy(): Promise<boolean> {
41
- try {
42
- const response = await fetch(this.baseUrl, {
43
- method: "GET",
44
- })
45
- debugLog("HeimdallApi", `Health check: ${response.status}`)
46
- return response.ok
47
- } catch (error) {
48
- debugLog("HeimdallApi", `Health check failed: ${error}`)
49
- return false
50
- }
51
- }
52
-
53
- /**
54
- * Check if already configured
55
- */
56
- async isInitialized(): Promise<boolean> {
57
- // Heimdall is always "initialized" - it works out of the box
58
- return true
59
- }
60
-
61
- /**
62
- * Get list of apps (via API if available)
63
- * Note: Heimdall primarily uses web UI for configuration
64
- */
65
- async getApps(): Promise<HeimdallApp[]> {
66
- try {
67
- const response = await fetch(`${this.baseUrl}/api/items`, {
68
- method: "GET",
69
- headers: {
70
- Accept: "application/json",
71
- },
72
- })
73
-
74
- if (response.ok) {
75
- return response.json()
76
- }
77
- } catch {
78
- // API may not be available or require auth
79
- }
80
- return []
81
- }
82
-
83
- /**
84
- * Add an app/tile to Heimdall
85
- * Note: Heimdall API may require authentication
86
- */
87
- async addApp(app: HeimdallApp): Promise<boolean> {
88
- debugLog("HeimdallApi", `Adding app: ${app.title}`)
89
-
90
- try {
91
- const response = await fetch(`${this.baseUrl}/api/items`, {
92
- method: "POST",
93
- headers: {
94
- "Content-Type": "application/json",
95
- Accept: "application/json",
96
- },
97
- body: JSON.stringify(app),
98
- })
99
-
100
- if (response.ok) {
101
- debugLog("HeimdallApi", `App "${app.title}" added successfully`)
102
- return true
103
- }
104
-
105
- // API might require auth or not exist
106
- if (response.status === 401 || response.status === 403) {
107
- debugLog("HeimdallApi", "API requires authentication")
108
- return false
109
- }
110
-
111
- if (response.status === 404) {
112
- debugLog("HeimdallApi", "Items API not available")
113
- return false
114
- }
115
-
116
- const text = await response.text()
117
- debugLog("HeimdallApi", `Failed to add app: ${response.status} - ${text}`)
118
- return false
119
- } catch (error) {
120
- debugLog("HeimdallApi", `Failed to add app: ${error}`)
121
- return false
122
- }
123
- }
124
-
125
- /**
126
- * Build app config for an easiarr app
127
- */
128
- buildAppConfig(appConfig: AppConfig): HeimdallApp | null {
129
- const appDef = getApp(appConfig.id)
130
- if (!appDef) return null
131
-
132
- // Skip apps without web UI
133
- if (appDef.defaultPort === 0) return null
134
-
135
- const port = appConfig.port || appDef.defaultPort
136
-
137
- return {
138
- title: appDef.name,
139
- url: `http://${appConfig.id}:${port}`,
140
- appdescription: appDef.description,
141
- pinned: true,
142
- colour: this.getColorForCategory(appDef.category),
143
- }
144
- }
145
-
146
- /**
147
- * Get a color based on app category
148
- */
149
- private getColorForCategory(category: string): string {
150
- const colors: Record<string, string> = {
151
- servarr: "#ffc107",
152
- indexer: "#17a2b8",
153
- downloader: "#28a745",
154
- mediaserver: "#6c5ce7",
155
- request: "#e17055",
156
- monitoring: "#00cec9",
157
- infrastructure: "#636e72",
158
- vpn: "#fd79a8",
159
- utility: "#74b9ff",
160
- }
161
- return colors[category] || "#6c757d"
162
- }
163
-
164
- /**
165
- * Run the auto-setup process for Heimdall
166
- */
167
- async setup(_options: AutoSetupOptions): Promise<AutoSetupResult> {
168
- try {
169
- // Check if reachable
170
- const healthy = await this.isHealthy()
171
- if (!healthy) {
172
- return { success: false, message: "Heimdall not reachable" }
173
- }
174
-
175
- // Check existing apps count
176
- const existingApps = await this.getApps()
177
-
178
- // Heimdall works out of the box, tiles can be added via UI
179
- return {
180
- success: true,
181
- message: "Ready - add tiles via UI",
182
- data: { existingAppsCount: existingApps.length },
183
- }
184
- } catch (error) {
185
- return { success: false, message: `${error}` }
186
- }
187
- }
188
-
189
- /**
190
- * Auto-add apps for enabled easiarr services
191
- */
192
- async setupEasiarrApps(apps: AppConfig[]): Promise<number> {
193
- let addedCount = 0
194
-
195
- for (const appConfig of apps) {
196
- if (!appConfig.enabled) continue
197
-
198
- const heimdallApp = this.buildAppConfig(appConfig)
199
- if (!heimdallApp) continue
200
-
201
- const success = await this.addApp(heimdallApp)
202
- if (success) {
203
- addedCount++
204
- }
205
- }
206
-
207
- return addedCount
208
- }
209
- }
@@ -1,296 +0,0 @@
1
- /**
2
- * Homarr API Client
3
- * Handles Homarr dashboard auto-setup with user and app management
4
- * Based on Homarr OpenAPI v1.0.0
5
- */
6
-
7
- import { debugLog } from "../utils/debug"
8
- import type { IAutoSetupClient, AutoSetupOptions, AutoSetupResult } from "./auto-setup-types"
9
- import type { AppConfig } from "../config/schema"
10
- import { getApp } from "../apps/registry"
11
-
12
- interface HomarrApp {
13
- id?: string
14
- appId?: string
15
- name: string
16
- description: string | null
17
- iconUrl: string
18
- href: string | null
19
- pingUrl: string | null
20
- }
21
-
22
- interface HomarrUser {
23
- id: string
24
- name: string | null
25
- email: string | null
26
- }
27
-
28
- interface HomarrInfo {
29
- version: string
30
- }
31
-
32
- export class HomarrClient implements IAutoSetupClient {
33
- private host: string
34
- private port: number
35
- private apiKey?: string
36
-
37
- constructor(host: string, port: number = 7575, apiKey?: string) {
38
- this.host = host
39
- this.port = port
40
- this.apiKey = apiKey
41
- }
42
-
43
- /**
44
- * Get base URL for Homarr
45
- */
46
- private get baseUrl(): string {
47
- return `http://${this.host}:${this.port}`
48
- }
49
-
50
- /**
51
- * Set API key for authenticated requests
52
- */
53
- setApiKey(apiKey: string): void {
54
- this.apiKey = apiKey
55
- }
56
-
57
- /**
58
- * Common headers for Homarr API requests
59
- */
60
- private getHeaders(): Record<string, string> {
61
- const headers: Record<string, string> = {
62
- "Content-Type": "application/json",
63
- Accept: "application/json",
64
- }
65
- if (this.apiKey) {
66
- headers["ApiKey"] = this.apiKey
67
- }
68
- return headers
69
- }
70
-
71
- /**
72
- * Check if Homarr is reachable
73
- */
74
- async isHealthy(): Promise<boolean> {
75
- try {
76
- const response = await fetch(this.baseUrl, {
77
- method: "GET",
78
- })
79
- debugLog("HomarrApi", `Health check: ${response.status}`)
80
- return response.ok
81
- } catch (error) {
82
- debugLog("HomarrApi", `Health check failed: ${error}`)
83
- return false
84
- }
85
- }
86
-
87
- /**
88
- * Check if already configured (has users)
89
- */
90
- async isInitialized(): Promise<boolean> {
91
- // Homarr is always "initialized" after first access
92
- return true
93
- }
94
-
95
- /**
96
- * Get Homarr version info
97
- */
98
- async getInfo(): Promise<HomarrInfo | null> {
99
- try {
100
- const response = await fetch(`${this.baseUrl}/api/info`, {
101
- method: "GET",
102
- headers: this.getHeaders(),
103
- })
104
-
105
- if (response.ok) {
106
- return response.json()
107
- }
108
- } catch {
109
- // API may not be available
110
- }
111
- return null
112
- }
113
-
114
- /**
115
- * Get all users
116
- */
117
- async getUsers(): Promise<HomarrUser[]> {
118
- try {
119
- const response = await fetch(`${this.baseUrl}/api/users`, {
120
- method: "GET",
121
- headers: this.getHeaders(),
122
- })
123
-
124
- if (response.ok) {
125
- return response.json()
126
- }
127
- } catch {
128
- // API may require auth
129
- }
130
- return []
131
- }
132
-
133
- /**
134
- * Create a user
135
- */
136
- async createUser(username: string, password: string, email?: string): Promise<boolean> {
137
- debugLog("HomarrApi", `Creating user: ${username}`)
138
-
139
- try {
140
- const response = await fetch(`${this.baseUrl}/api/users`, {
141
- method: "POST",
142
- headers: this.getHeaders(),
143
- body: JSON.stringify({
144
- username,
145
- password,
146
- confirmPassword: password,
147
- email: email || "",
148
- groupIds: [],
149
- }),
150
- })
151
-
152
- if (response.ok) {
153
- debugLog("HomarrApi", `User "${username}" created successfully`)
154
- return true
155
- }
156
-
157
- const text = await response.text()
158
- debugLog("HomarrApi", `Failed to create user: ${response.status} - ${text}`)
159
- return false
160
- } catch (error) {
161
- debugLog("HomarrApi", `Failed to create user: ${error}`)
162
- return false
163
- }
164
- }
165
-
166
- /**
167
- * Get all apps
168
- */
169
- async getApps(): Promise<HomarrApp[]> {
170
- try {
171
- const response = await fetch(`${this.baseUrl}/api/apps`, {
172
- method: "GET",
173
- headers: this.getHeaders(),
174
- })
175
-
176
- if (response.ok) {
177
- return response.json()
178
- }
179
- } catch {
180
- // API may require auth
181
- }
182
- return []
183
- }
184
-
185
- /**
186
- * Create an app
187
- */
188
- async createApp(app: Omit<HomarrApp, "id" | "appId">): Promise<string | null> {
189
- debugLog("HomarrApi", `Creating app: ${app.name}`)
190
-
191
- try {
192
- const response = await fetch(`${this.baseUrl}/api/apps`, {
193
- method: "POST",
194
- headers: this.getHeaders(),
195
- body: JSON.stringify(app),
196
- })
197
-
198
- if (response.ok) {
199
- const data = await response.json()
200
- debugLog("HomarrApi", `App "${app.name}" created with ID ${data.appId}`)
201
- return data.appId
202
- }
203
-
204
- const text = await response.text()
205
- debugLog("HomarrApi", `Failed to create app: ${response.status} - ${text}`)
206
- return null
207
- } catch (error) {
208
- debugLog("HomarrApi", `Failed to create app: ${error}`)
209
- return null
210
- }
211
- }
212
-
213
- /**
214
- * Build app config for an easiarr app
215
- */
216
- buildAppConfig(appConfig: AppConfig): Omit<HomarrApp, "id" | "appId"> | null {
217
- const appDef = getApp(appConfig.id)
218
- if (!appDef) return null
219
-
220
- // Skip apps without web UI
221
- if (appDef.defaultPort === 0) return null
222
-
223
- const port = appConfig.port || appDef.defaultPort
224
-
225
- return {
226
- name: appDef.name,
227
- description: appDef.description || null,
228
- iconUrl: `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${appConfig.id}.png`,
229
- href: `http://${appConfig.id}:${port}`,
230
- pingUrl: `http://${appConfig.id}:${port}`,
231
- }
232
- }
233
-
234
- /**
235
- * Run the auto-setup process for Homarr
236
- */
237
- async setup(options: AutoSetupOptions): Promise<AutoSetupResult> {
238
- const { username, password } = options
239
-
240
- try {
241
- // Check if reachable
242
- const healthy = await this.isHealthy()
243
- if (!healthy) {
244
- return { success: false, message: "Homarr not reachable" }
245
- }
246
-
247
- // Check if users exist
248
- const users = await this.getUsers()
249
- let userCreated = false
250
-
251
- if (users.length === 0) {
252
- // Try to create initial user
253
- userCreated = await this.createUser(username, password)
254
- }
255
-
256
- return {
257
- success: true,
258
- message: userCreated ? "User created, ready" : "Ready - add apps via UI or API",
259
- data: { userCreated },
260
- }
261
- } catch (error) {
262
- return { success: false, message: `${error}` }
263
- }
264
- }
265
-
266
- /**
267
- * Auto-add apps for enabled easiarr services
268
- */
269
- async setupEasiarrApps(apps: AppConfig[]): Promise<number> {
270
- let addedCount = 0
271
-
272
- // Get existing apps to avoid duplicates
273
- const existingApps = await this.getApps()
274
- const existingNames = new Set(existingApps.map((a) => a.name))
275
-
276
- for (const appConfig of apps) {
277
- if (!appConfig.enabled) continue
278
-
279
- const homarrApp = this.buildAppConfig(appConfig)
280
- if (!homarrApp) continue
281
-
282
- // Skip if already exists
283
- if (existingNames.has(homarrApp.name)) {
284
- debugLog("HomarrApi", `App "${homarrApp.name}" already exists, skipping`)
285
- continue
286
- }
287
-
288
- const appId = await this.createApp(homarrApp)
289
- if (appId) {
290
- addedCount++
291
- }
292
- }
293
-
294
- return addedCount
295
- }
296
- }