@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.
- package/README.md +8 -5
- package/dist/index.js +29837 -0
- package/package.json +18 -16
- package/src/VersionInfo.ts +0 -12
- package/src/api/arr-api.ts +0 -508
- package/src/api/auto-setup-types.ts +0 -64
- package/src/api/bazarr-api.ts +0 -356
- package/src/api/cloudflare-api.ts +0 -577
- package/src/api/custom-format-api.ts +0 -212
- package/src/api/grafana-api.ts +0 -314
- package/src/api/heimdall-api.ts +0 -209
- package/src/api/homarr-api.ts +0 -296
- package/src/api/huntarr-api.ts +0 -622
- package/src/api/index.ts +0 -1
- package/src/api/jellyfin-api.ts +0 -473
- package/src/api/jellyseerr-api.ts +0 -660
- package/src/api/maintainerr-api.ts +0 -731
- package/src/api/naming-config.ts +0 -93
- package/src/api/overseerr-api.ts +0 -513
- package/src/api/plex-api.ts +0 -358
- package/src/api/portainer-api.ts +0 -467
- package/src/api/profilarr-api.ts +0 -380
- package/src/api/prowlarr-api.ts +0 -859
- package/src/api/qbittorrent-api.ts +0 -339
- package/src/api/quality-profile-api.ts +0 -269
- package/src/api/tautulli-api.ts +0 -277
- package/src/api/uptime-kuma-api.ts +0 -342
- package/src/apps/categories.ts +0 -14
- package/src/apps/index.ts +0 -2
- package/src/apps/registry.ts +0 -1255
- package/src/compose/caddy-config.ts +0 -129
- package/src/compose/generator.ts +0 -262
- package/src/compose/index.ts +0 -3
- package/src/compose/templates.ts +0 -78
- package/src/compose/traefik-config.ts +0 -185
- package/src/config/bookmarks-generator.ts +0 -149
- package/src/config/defaults.ts +0 -37
- package/src/config/homepage-config.ts +0 -376
- package/src/config/index.ts +0 -3
- package/src/config/manager.ts +0 -149
- package/src/config/recyclarr-config.ts +0 -179
- package/src/config/schema.ts +0 -310
- package/src/config/slskd-config.ts +0 -85
- package/src/config/soularr-config.ts +0 -105
- package/src/config/trash-quality-definitions.ts +0 -213
- package/src/data/lidarr-custom-formats.ts +0 -127
- package/src/data/trash-profiles.ts +0 -326
- package/src/docker/client.ts +0 -291
- package/src/docker/index.ts +0 -1
- package/src/index.ts +0 -77
- package/src/structure/manager.ts +0 -128
- package/src/ui/App.ts +0 -109
- package/src/ui/components/ApplicationSelector.ts +0 -272
- package/src/ui/components/FileEditor.ts +0 -91
- package/src/ui/components/FooterHint.ts +0 -119
- package/src/ui/components/PageLayout.ts +0 -152
- package/src/ui/components/UpdateNotification.ts +0 -101
- package/src/ui/index.ts +0 -1
- package/src/ui/screens/AdvancedSettings.ts +0 -181
- package/src/ui/screens/ApiKeyViewer.ts +0 -500
- package/src/ui/screens/AppConfigurator.ts +0 -731
- package/src/ui/screens/AppManager.ts +0 -276
- package/src/ui/screens/CloudflaredSetup.ts +0 -974
- package/src/ui/screens/ContainerControl.ts +0 -579
- package/src/ui/screens/FullAutoSetup.ts +0 -1719
- package/src/ui/screens/HomepageSetup.ts +0 -306
- package/src/ui/screens/JellyfinSetup.ts +0 -471
- package/src/ui/screens/JellyseerrSetup.ts +0 -612
- package/src/ui/screens/LogsViewer.ts +0 -468
- package/src/ui/screens/MainMenu.ts +0 -288
- package/src/ui/screens/MonitorDashboard.ts +0 -866
- package/src/ui/screens/ProwlarrSetup.ts +0 -623
- package/src/ui/screens/QBittorrentSetup.ts +0 -268
- package/src/ui/screens/QuickSetup.ts +0 -1161
- package/src/ui/screens/RecyclarrSetup.ts +0 -418
- package/src/ui/screens/SecretsEditor.ts +0 -214
- package/src/ui/screens/SettingsScreen.ts +0 -605
- package/src/ui/screens/TRaSHProfileSetup.ts +0 -395
- package/src/ui/screens/index.ts +0 -4
- package/src/util/arch.ts +0 -78
- package/src/utils/browser.ts +0 -26
- package/src/utils/categories.ts +0 -59
- package/src/utils/debug.ts +0 -91
- package/src/utils/env.ts +0 -137
- package/src/utils/logs.ts +0 -118
- package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -101
- package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -90
- package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -44
- package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -107
- package/src/utils/migrations.ts +0 -164
- package/src/utils/password.ts +0 -42
- package/src/utils/unraid.ts +0 -101
- package/src/utils/update-checker.ts +0 -210
- package/src/utils/url-utils.ts +0 -38
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muhammedaksam/easiarr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "TUI tool for generating docker-compose files for the *arr media ecosystem with 41 apps, TRaSH Guides best practices, VPN routing, and Traefik reverse proxy support",
|
|
5
|
-
"module": "
|
|
5
|
+
"module": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"easiarr": "./
|
|
8
|
+
"easiarr": "./dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
|
-
"
|
|
11
|
+
"dist"
|
|
12
12
|
],
|
|
13
13
|
"author": "Muhammed Mustafa AKŞAM <info@muhammedaksam.com.tr> (https://github.com/muhammedaksam)",
|
|
14
14
|
"license": "MIT",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"dev": "bun run --watch src/index.ts",
|
|
38
38
|
"dev:debug": "bun run dev --debug",
|
|
39
|
-
"build": "bun build src/index.ts --outdir dist --target bun",
|
|
39
|
+
"build": "bun build src/index.ts --outdir dist --target bun --external @opentui/core",
|
|
40
40
|
"typecheck": "bun x tsc --noEmit",
|
|
41
41
|
"lint": "eslint src/",
|
|
42
42
|
"lint:fix": "eslint src/ --fix",
|
|
@@ -51,28 +51,30 @@
|
|
|
51
51
|
"start": "bun run src/index.ts"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^
|
|
54
|
+
"@eslint/js": "^10.0.1",
|
|
55
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
|
|
55
56
|
"@types/bcrypt": "^6.0.0",
|
|
56
57
|
"@types/bun": "latest",
|
|
57
58
|
"@types/jest": "^30.0.0",
|
|
58
|
-
"@types/node": "^
|
|
59
|
-
"eslint": "^
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
59
|
+
"@types/node": "^26.0.1",
|
|
60
|
+
"eslint": "^10.6.0",
|
|
61
|
+
"eslint-plugin-import": "^2.32.0",
|
|
62
|
+
"jest": "^30.4.2",
|
|
63
|
+
"jiti": "^2.7.0",
|
|
64
|
+
"prettier": "^3.9.1",
|
|
65
|
+
"ts-jest": "^29.4.11",
|
|
66
|
+
"typescript-eslint": "^8.62.0"
|
|
65
67
|
},
|
|
66
68
|
"peerDependencies": {
|
|
67
69
|
"typescript": "^5.9.3"
|
|
68
70
|
},
|
|
69
71
|
"dependencies": {
|
|
70
|
-
"@opentui/core": "^0.
|
|
72
|
+
"@opentui/core": "^0.4.2",
|
|
71
73
|
"bcrypt": "^6.0.0",
|
|
72
74
|
"socket.io-client": "^4.8.3",
|
|
73
|
-
"yaml": "^2.
|
|
75
|
+
"yaml": "^2.9.0"
|
|
74
76
|
},
|
|
75
77
|
"engines": {
|
|
76
78
|
"bun": ">=1.0"
|
|
77
79
|
}
|
|
78
|
-
}
|
|
80
|
+
}
|
package/src/VersionInfo.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import packageJson from "../package.json" with { type: "json" }
|
|
2
|
-
|
|
3
|
-
const pkg = packageJson
|
|
4
|
-
|
|
5
|
-
export const VersionInfo = {
|
|
6
|
-
version: pkg.version,
|
|
7
|
-
name: pkg.name,
|
|
8
|
-
description: pkg.description,
|
|
9
|
-
author: pkg.author,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const getVersion = () => `v${VersionInfo.version}`
|
package/src/api/arr-api.ts
DELETED
|
@@ -1,508 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* *arr API Client
|
|
3
|
-
* Interacts with Radarr, Sonarr, Lidarr, Readarr, Whisparr APIs
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { debugLog } from "../utils/debug"
|
|
7
|
-
|
|
8
|
-
// Types for Root Folder API
|
|
9
|
-
export interface RootFolder {
|
|
10
|
-
id?: number
|
|
11
|
-
path: string
|
|
12
|
-
accessible?: boolean
|
|
13
|
-
freeSpace?: number | null
|
|
14
|
-
unmappedFolders?: { name: string | null; path: string | null; relativePath: string | null }[]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Options for adding root folder (some apps like Lidarr need extra fields)
|
|
18
|
-
export interface AddRootFolderOptions {
|
|
19
|
-
path: string
|
|
20
|
-
name?: string // Required for Lidarr
|
|
21
|
-
defaultMetadataProfileId?: number
|
|
22
|
-
defaultQualityProfileId?: number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Types for Download Client API
|
|
26
|
-
export interface DownloadClientConfig {
|
|
27
|
-
name: string
|
|
28
|
-
implementation: string
|
|
29
|
-
configContract: string
|
|
30
|
-
enable?: boolean
|
|
31
|
-
priority?: number
|
|
32
|
-
fields: { name: string; value: unknown }[]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface DownloadClient extends DownloadClientConfig {
|
|
36
|
-
id?: number
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Types for Remote Path Mapping API
|
|
40
|
-
export interface RemotePathMapping {
|
|
41
|
-
id?: number
|
|
42
|
-
host: string
|
|
43
|
-
remotePath: string
|
|
44
|
-
localPath: string
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
import type { AppId } from "../config/schema"
|
|
48
|
-
import { getCategoryForApp, getCategoryFieldName } from "../utils/categories"
|
|
49
|
-
import { TRASH_NAMING_CONFIG, type NamingConfig } from "./naming-config"
|
|
50
|
-
|
|
51
|
-
// qBittorrent download client config
|
|
52
|
-
export function createQBittorrentConfig(
|
|
53
|
-
host: string,
|
|
54
|
-
port: number,
|
|
55
|
-
username: string,
|
|
56
|
-
password: string,
|
|
57
|
-
appId?: AppId
|
|
58
|
-
): DownloadClientConfig {
|
|
59
|
-
const category = appId ? getCategoryForApp(appId) : "default"
|
|
60
|
-
const categoryField = appId ? getCategoryFieldName(appId) : "category"
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
name: "qBittorrent",
|
|
64
|
-
implementation: "QBittorrent",
|
|
65
|
-
configContract: "QBittorrentSettings",
|
|
66
|
-
enable: true,
|
|
67
|
-
priority: 1,
|
|
68
|
-
fields: [
|
|
69
|
-
{ name: "host", value: host },
|
|
70
|
-
{ name: "port", value: port },
|
|
71
|
-
{ name: "username", value: username },
|
|
72
|
-
{ name: "password", value: password },
|
|
73
|
-
{ name: categoryField, value: category },
|
|
74
|
-
{ name: "savePath", value: "/data/torrents" },
|
|
75
|
-
{ name: "recentMoviePriority", value: 0 },
|
|
76
|
-
{ name: "olderMoviePriority", value: 0 },
|
|
77
|
-
{ name: "initialState", value: 0 },
|
|
78
|
-
{ name: "sequentialOrder", value: false },
|
|
79
|
-
{ name: "firstAndLast", value: false },
|
|
80
|
-
],
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// SABnzbd download client config
|
|
85
|
-
export function createSABnzbdConfig(host: string, port: number, apiKey: string, appId?: AppId): DownloadClientConfig {
|
|
86
|
-
const category = appId ? getCategoryForApp(appId) : "default"
|
|
87
|
-
const categoryField = appId ? getCategoryFieldName(appId) : "category"
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
name: "SABnzbd",
|
|
91
|
-
implementation: "Sabnzbd",
|
|
92
|
-
configContract: "SabnzbdSettings",
|
|
93
|
-
enable: true,
|
|
94
|
-
priority: 1,
|
|
95
|
-
fields: [
|
|
96
|
-
{ name: "host", value: host },
|
|
97
|
-
{ name: "port", value: port },
|
|
98
|
-
{ name: "apiKey", value: apiKey },
|
|
99
|
-
{ name: categoryField, value: category },
|
|
100
|
-
{ name: "savePath", value: "/data/usenet" },
|
|
101
|
-
{ name: "recentMoviePriority", value: -100 },
|
|
102
|
-
{ name: "olderMoviePriority", value: -100 },
|
|
103
|
-
],
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export type ApiVersion = "v1" | "v3"
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* *arr API Client
|
|
111
|
-
*/
|
|
112
|
-
export class ArrApiClient {
|
|
113
|
-
private baseUrl: string
|
|
114
|
-
private apiKey: string
|
|
115
|
-
private apiVersion: ApiVersion
|
|
116
|
-
|
|
117
|
-
constructor(host: string, port: number, apiKey: string, apiVersion: ApiVersion = "v3") {
|
|
118
|
-
this.baseUrl = `http://${host}:${port}`
|
|
119
|
-
this.apiKey = apiKey
|
|
120
|
-
this.apiVersion = apiVersion
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
|
124
|
-
const url = `${this.baseUrl}/api/${this.apiVersion}${endpoint}`
|
|
125
|
-
const headers = {
|
|
126
|
-
"X-Api-Key": this.apiKey,
|
|
127
|
-
"Content-Type": "application/json",
|
|
128
|
-
...options.headers,
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
debugLog("ArrAPI", `${options.method || "GET"} ${url}`)
|
|
132
|
-
if (options.body) {
|
|
133
|
-
debugLog("ArrAPI", `Request Body: ${options.body}`)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const response = await fetch(url, { ...options, headers })
|
|
137
|
-
const text = await response.text()
|
|
138
|
-
|
|
139
|
-
debugLog("ArrAPI", `Response ${response.status} from ${endpoint}`)
|
|
140
|
-
if (text && text.length < 2000) {
|
|
141
|
-
debugLog("ArrAPI", `Response Body: ${text}`)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (!response.ok) {
|
|
145
|
-
throw new Error(`API request failed: ${response.status} ${response.statusText} - ${text}`)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (!text) return {} as T
|
|
149
|
-
return JSON.parse(text) as T
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Root Folder methods
|
|
153
|
-
async getRootFolders(): Promise<RootFolder[]> {
|
|
154
|
-
return this.request<RootFolder[]>("/rootfolder")
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async addRootFolder(pathOrOptions: string | AddRootFolderOptions): Promise<RootFolder> {
|
|
158
|
-
const body = typeof pathOrOptions === "string" ? { path: pathOrOptions } : pathOrOptions
|
|
159
|
-
return this.request<RootFolder>("/rootfolder", {
|
|
160
|
-
method: "POST",
|
|
161
|
-
body: JSON.stringify(body),
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Profile methods (needed for Lidarr root folders)
|
|
166
|
-
async getMetadataProfiles(): Promise<{ id: number; name: string }[]> {
|
|
167
|
-
try {
|
|
168
|
-
return await this.request<{ id: number; name: string }[]>("/metadataprofile")
|
|
169
|
-
} catch {
|
|
170
|
-
return []
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async getQualityProfiles(): Promise<{ id: number; name: string }[]> {
|
|
175
|
-
try {
|
|
176
|
-
return await this.request<{ id: number; name: string }[]>("/qualityprofile")
|
|
177
|
-
} catch {
|
|
178
|
-
return []
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async deleteRootFolder(id: number): Promise<void> {
|
|
183
|
-
await this.request(`/rootfolder/${id}`, { method: "DELETE" })
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Download Client methods
|
|
187
|
-
async getDownloadClients(): Promise<DownloadClient[]> {
|
|
188
|
-
return this.request<DownloadClient[]>("/downloadclient")
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async addDownloadClient(config: DownloadClientConfig): Promise<DownloadClient> {
|
|
192
|
-
return this.request<DownloadClient>("/downloadclient", {
|
|
193
|
-
method: "POST",
|
|
194
|
-
body: JSON.stringify(config),
|
|
195
|
-
})
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async deleteDownloadClient(id: number): Promise<void> {
|
|
199
|
-
await this.request(`/downloadclient/${id}`, { method: "DELETE" })
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Health check
|
|
203
|
-
async isHealthy(): Promise<boolean> {
|
|
204
|
-
try {
|
|
205
|
-
await this.request("/system/status")
|
|
206
|
-
return true
|
|
207
|
-
} catch {
|
|
208
|
-
return false
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Host Config methods - for setting up authentication
|
|
213
|
-
async getHostConfig(): Promise<HostConfig> {
|
|
214
|
-
return this.request<HostConfig>("/config/host")
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
async updateHostConfig(username: string, password: string, override = false): Promise<HostConfig | null> {
|
|
218
|
-
// First get current config to preserve all other settings
|
|
219
|
-
const currentConfig = await this.getHostConfig()
|
|
220
|
-
|
|
221
|
-
// Only update if no password is set OR override is requested
|
|
222
|
-
if (currentConfig.password && !override) {
|
|
223
|
-
return null // Skip - password already configured
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Update with authentication settings (id must be in body, not URL)
|
|
227
|
-
const updatedConfig: HostConfig = {
|
|
228
|
-
...currentConfig,
|
|
229
|
-
authenticationMethod: "forms",
|
|
230
|
-
authenticationRequired: "enabled",
|
|
231
|
-
username,
|
|
232
|
-
password,
|
|
233
|
-
passwordConfirmation: password,
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// PUT to /config/host with id in body (not /config/host/{id})
|
|
237
|
-
return this.request<HostConfig>("/config/host", {
|
|
238
|
-
method: "PUT",
|
|
239
|
-
body: JSON.stringify(updatedConfig),
|
|
240
|
-
})
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Set application URL for external access (e.g., from Jellyseerr/dashboard links)
|
|
245
|
-
* URL will be used when generating external links in the app
|
|
246
|
-
*/
|
|
247
|
-
async setApplicationUrl(applicationUrl: string): Promise<HostConfig> {
|
|
248
|
-
const currentConfig = await this.getHostConfig()
|
|
249
|
-
|
|
250
|
-
const updatedConfig: HostConfig = {
|
|
251
|
-
...currentConfig,
|
|
252
|
-
applicationUrl,
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
debugLog("ArrAPI", `Setting applicationUrl to: ${applicationUrl}`)
|
|
256
|
-
|
|
257
|
-
return this.request<HostConfig>("/config/host", {
|
|
258
|
-
method: "PUT",
|
|
259
|
-
body: JSON.stringify(updatedConfig),
|
|
260
|
-
})
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Remote Path Mapping methods - for Docker path translation
|
|
264
|
-
|
|
265
|
-
async getRemotePathMappings(): Promise<RemotePathMapping[]> {
|
|
266
|
-
return this.request<RemotePathMapping[]>("/remotepathmapping")
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Naming Configuration methods
|
|
270
|
-
async getNamingConfig<T extends NamingConfig>(): Promise<T> {
|
|
271
|
-
return this.request<T>("/config/naming")
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
async updateNamingConfig<T extends NamingConfig>(config: T): Promise<T> {
|
|
275
|
-
return this.request<T>("/config/naming", {
|
|
276
|
-
method: "PUT",
|
|
277
|
-
body: JSON.stringify(config),
|
|
278
|
-
})
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async configureTRaSHNaming(appType: "radarr" | "sonarr" | "lidarr"): Promise<void> {
|
|
282
|
-
try {
|
|
283
|
-
// 1. Get current configuration to preserve ID and other fields
|
|
284
|
-
const currentConfig = await this.getNamingConfig<NamingConfig & { id?: number }>()
|
|
285
|
-
|
|
286
|
-
// 2. Merge with TRaSH defaults
|
|
287
|
-
const trashConfig = TRASH_NAMING_CONFIG[appType]
|
|
288
|
-
const newConfig = {
|
|
289
|
-
...currentConfig,
|
|
290
|
-
...trashConfig,
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// 3. Update configuration
|
|
294
|
-
await this.updateNamingConfig(newConfig)
|
|
295
|
-
} catch (e) {
|
|
296
|
-
throw new Error(`Failed to configure naming: ${e}`)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
async addRemotePathMapping(host: string, remotePath: string, localPath: string): Promise<RemotePathMapping> {
|
|
301
|
-
return this.request<RemotePathMapping>("/remotepathmapping", {
|
|
302
|
-
method: "POST",
|
|
303
|
-
body: JSON.stringify({ host, remotePath, localPath }),
|
|
304
|
-
})
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async deleteRemotePathMapping(id: number): Promise<void> {
|
|
308
|
-
await this.request(`/remotepathmapping/${id}`, { method: "DELETE" })
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// ==========================================
|
|
312
|
-
// Health Check & Status Methods
|
|
313
|
-
// ==========================================
|
|
314
|
-
|
|
315
|
-
// Get health issues/warnings
|
|
316
|
-
async getHealth(): Promise<HealthResource[]> {
|
|
317
|
-
return this.request<HealthResource[]>("/health")
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Get disk space information for all monitored paths
|
|
321
|
-
async getDiskSpace(): Promise<DiskSpaceResource[]> {
|
|
322
|
-
return this.request<DiskSpaceResource[]>("/diskspace")
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Get system status (version, OS, runtime, etc.)
|
|
326
|
-
async getSystemStatus(): Promise<SystemResource> {
|
|
327
|
-
return this.request<SystemResource>("/system/status")
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Get all items in the download queue
|
|
331
|
-
async getQueueDetails(includeUnknown = true): Promise<QueueResource[]> {
|
|
332
|
-
const params = new URLSearchParams()
|
|
333
|
-
if (includeUnknown) {
|
|
334
|
-
params.set("includeUnknownMovieItems", "true")
|
|
335
|
-
}
|
|
336
|
-
const query = params.toString()
|
|
337
|
-
return this.request<QueueResource[]>(`/queue/details${query ? `?${query}` : ""}`)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Get queue status summary (counts, errors, warnings)
|
|
341
|
-
async getQueueStatus(): Promise<QueueStatusResource> {
|
|
342
|
-
return this.request<QueueStatusResource>("/queue/status")
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Types for Host Config API
|
|
347
|
-
export interface HostConfig {
|
|
348
|
-
id: number
|
|
349
|
-
bindAddress: string | null
|
|
350
|
-
port: number
|
|
351
|
-
sslPort: number
|
|
352
|
-
enableSsl: boolean
|
|
353
|
-
launchBrowser: boolean
|
|
354
|
-
authenticationMethod: "none" | "basic" | "forms" | "external"
|
|
355
|
-
authenticationRequired: "enabled" | "disabledForLocalAddresses"
|
|
356
|
-
analyticsEnabled: boolean
|
|
357
|
-
username: string | null
|
|
358
|
-
password: string | null
|
|
359
|
-
passwordConfirmation: string | null
|
|
360
|
-
logLevel: string | null
|
|
361
|
-
logSizeLimit: number
|
|
362
|
-
consoleLogLevel: string | null
|
|
363
|
-
branch: string | null
|
|
364
|
-
apiKey: string | null
|
|
365
|
-
sslCertPath: string | null
|
|
366
|
-
sslCertPassword: string | null
|
|
367
|
-
urlBase: string | null
|
|
368
|
-
instanceName: string | null
|
|
369
|
-
applicationUrl: string | null
|
|
370
|
-
updateAutomatically: boolean
|
|
371
|
-
updateMechanism: string
|
|
372
|
-
updateScriptPath: string | null
|
|
373
|
-
proxyEnabled: boolean
|
|
374
|
-
proxyType: string
|
|
375
|
-
proxyHostname: string | null
|
|
376
|
-
proxyPort: number
|
|
377
|
-
proxyUsername: string | null
|
|
378
|
-
proxyPassword: string | null
|
|
379
|
-
proxyBypassFilter: string | null
|
|
380
|
-
proxyBypassLocalAddresses: boolean
|
|
381
|
-
certificateValidation: string
|
|
382
|
-
backupFolder: string | null
|
|
383
|
-
backupInterval: number
|
|
384
|
-
backupRetention: number
|
|
385
|
-
trustCgnatIpAddresses: boolean
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// ==========================================
|
|
389
|
-
// Health Check & Status Types
|
|
390
|
-
// ==========================================
|
|
391
|
-
|
|
392
|
-
// Health check result types
|
|
393
|
-
export type HealthCheckType = "ok" | "notice" | "warning" | "error"
|
|
394
|
-
|
|
395
|
-
export interface HealthResource {
|
|
396
|
-
id?: number
|
|
397
|
-
source: string | null
|
|
398
|
-
type: HealthCheckType
|
|
399
|
-
message: string | null
|
|
400
|
-
wikiUrl: string | null
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Disk space types
|
|
404
|
-
export interface DiskSpaceResource {
|
|
405
|
-
id?: number
|
|
406
|
-
path: string | null
|
|
407
|
-
label: string | null
|
|
408
|
-
freeSpace: number // int64
|
|
409
|
-
totalSpace: number // int64
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// System status types
|
|
413
|
-
export type RuntimeMode = "console" | "service" | "tray"
|
|
414
|
-
export type DatabaseType = "sqLite" | "postgreSQL"
|
|
415
|
-
|
|
416
|
-
export interface SystemResource {
|
|
417
|
-
appName: string | null
|
|
418
|
-
instanceName: string | null
|
|
419
|
-
version: string | null
|
|
420
|
-
buildTime: string | null
|
|
421
|
-
isDebug: boolean
|
|
422
|
-
isProduction: boolean
|
|
423
|
-
isAdmin: boolean
|
|
424
|
-
isUserInteractive: boolean
|
|
425
|
-
startupPath: string | null
|
|
426
|
-
appData: string | null
|
|
427
|
-
osName: string | null
|
|
428
|
-
osVersion: string | null
|
|
429
|
-
isNetCore: boolean
|
|
430
|
-
isLinux: boolean
|
|
431
|
-
isOsx: boolean
|
|
432
|
-
isWindows: boolean
|
|
433
|
-
isDocker: boolean
|
|
434
|
-
mode: RuntimeMode
|
|
435
|
-
branch: string | null
|
|
436
|
-
databaseType: DatabaseType
|
|
437
|
-
databaseVersion: string | null
|
|
438
|
-
authentication: "none" | "basic" | "forms" | "external"
|
|
439
|
-
migrationVersion: number
|
|
440
|
-
urlBase: string | null
|
|
441
|
-
runtimeVersion: string | null
|
|
442
|
-
runtimeName: string | null
|
|
443
|
-
startTime: string | null
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Queue types
|
|
447
|
-
export type QueueStatus =
|
|
448
|
-
| "unknown"
|
|
449
|
-
| "queued"
|
|
450
|
-
| "paused"
|
|
451
|
-
| "downloading"
|
|
452
|
-
| "completed"
|
|
453
|
-
| "failed"
|
|
454
|
-
| "warning"
|
|
455
|
-
| "delay"
|
|
456
|
-
| "downloadClientUnavailable"
|
|
457
|
-
| "fallback"
|
|
458
|
-
|
|
459
|
-
export type TrackedDownloadStatus = "ok" | "warning" | "error"
|
|
460
|
-
export type TrackedDownloadState =
|
|
461
|
-
| "downloading"
|
|
462
|
-
| "importBlocked"
|
|
463
|
-
| "importPending"
|
|
464
|
-
| "importing"
|
|
465
|
-
| "imported"
|
|
466
|
-
| "failedPending"
|
|
467
|
-
| "failed"
|
|
468
|
-
| "ignored"
|
|
469
|
-
|
|
470
|
-
export interface QueueStatusMessage {
|
|
471
|
-
title: string | null
|
|
472
|
-
messages: string[] | null
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
export interface QueueResource {
|
|
476
|
-
id?: number
|
|
477
|
-
movieId?: number | null // Radarr
|
|
478
|
-
seriesId?: number | null // Sonarr
|
|
479
|
-
artistId?: number | null // Lidarr
|
|
480
|
-
authorId?: number | null // Readarr
|
|
481
|
-
title: string | null
|
|
482
|
-
size: number
|
|
483
|
-
sizeleft?: number
|
|
484
|
-
timeleft?: string | null
|
|
485
|
-
estimatedCompletionTime: string | null
|
|
486
|
-
added: string | null
|
|
487
|
-
status: QueueStatus
|
|
488
|
-
trackedDownloadStatus: TrackedDownloadStatus
|
|
489
|
-
trackedDownloadState: TrackedDownloadState
|
|
490
|
-
statusMessages?: QueueStatusMessage[] | null
|
|
491
|
-
errorMessage: string | null
|
|
492
|
-
downloadId: string | null
|
|
493
|
-
protocol: "unknown" | "usenet" | "torrent"
|
|
494
|
-
downloadClient: string | null
|
|
495
|
-
indexer: string | null
|
|
496
|
-
outputPath: string | null
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
export interface QueueStatusResource {
|
|
500
|
-
id?: number
|
|
501
|
-
totalCount: number
|
|
502
|
-
count: number
|
|
503
|
-
unknownCount: number
|
|
504
|
-
errors: boolean
|
|
505
|
-
warnings: boolean
|
|
506
|
-
unknownErrors: boolean
|
|
507
|
-
unknownWarnings: boolean
|
|
508
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auto-Setup Types
|
|
3
|
-
* Interfaces for auto-setup capability metadata and clients
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { AppId } from "../config/schema"
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Describes an app's auto-setup capability
|
|
10
|
-
*/
|
|
11
|
-
export interface AutoSetupCapability {
|
|
12
|
-
/** Type of auto-setup support */
|
|
13
|
-
type: "full" | "partial" | "manual"
|
|
14
|
-
/** Human-readable description of what gets configured */
|
|
15
|
-
description: string
|
|
16
|
-
/** Other apps that must be set up first */
|
|
17
|
-
requires?: AppId[]
|
|
18
|
-
/** Environment variables required for setup */
|
|
19
|
-
envVars?: string[]
|
|
20
|
-
/** Setup function name in FullAutoSetup (for dynamic discovery) */
|
|
21
|
-
setupMethod?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Result of an auto-setup operation
|
|
26
|
-
*/
|
|
27
|
-
export interface AutoSetupResult {
|
|
28
|
-
success: boolean
|
|
29
|
-
message?: string
|
|
30
|
-
/** Data to persist (e.g., API keys, tokens) */
|
|
31
|
-
envUpdates?: Record<string, string>
|
|
32
|
-
/** Additional result data (e.g., API keys, generated credentials) */
|
|
33
|
-
data?: Record<string, unknown>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Base interface for auto-setup clients
|
|
38
|
-
*/
|
|
39
|
-
export interface IAutoSetupClient {
|
|
40
|
-
/** Check if service is reachable */
|
|
41
|
-
isHealthy(): Promise<boolean>
|
|
42
|
-
|
|
43
|
-
/** Check if service is already configured */
|
|
44
|
-
isInitialized(): Promise<boolean>
|
|
45
|
-
|
|
46
|
-
/** Run the auto-setup process */
|
|
47
|
-
setup(options: AutoSetupOptions): Promise<AutoSetupResult>
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Common options for auto-setup
|
|
52
|
-
*/
|
|
53
|
-
export interface AutoSetupOptions {
|
|
54
|
-
/** Global username for auth */
|
|
55
|
-
username: string
|
|
56
|
-
/** Global password for auth */
|
|
57
|
-
password: string
|
|
58
|
-
/** Environment variables available */
|
|
59
|
-
env: Record<string, string>
|
|
60
|
-
/** Plex authentication token (for Plex-dependent services) */
|
|
61
|
-
plexToken?: string
|
|
62
|
-
/** List of enabled app IDs (for smart library/config creation) */
|
|
63
|
-
enabledApps?: AppId[]
|
|
64
|
-
}
|