@muhammedaksam/easiarr 1.4.0 → 1.6.0
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/dist/index.js +29750 -0
- package/package.json +15 -15
- package/src/VersionInfo.ts +0 -12
- package/src/api/arr-api.ts +0 -521
- package/src/api/auto-setup-types.ts +0 -64
- package/src/api/base-api.ts +0 -216
- package/src/api/bazarr-api.ts +0 -297
- package/src/api/cloudflare-api.ts +0 -493
- package/src/api/custom-format-api.ts +0 -224
- package/src/api/grafana-api.ts +0 -230
- package/src/api/heimdall-api.ts +0 -141
- package/src/api/homarr-api.ts +0 -209
- package/src/api/huntarr-api.ts +0 -457
- package/src/api/index.ts +0 -9
- package/src/api/jellyfin-api.ts +0 -389
- package/src/api/jellyseerr-api.ts +0 -559
- package/src/api/maintainerr-api.ts +0 -461
- package/src/api/naming-config.ts +0 -101
- package/src/api/overseerr-api.ts +0 -392
- package/src/api/plex-api.ts +0 -308
- package/src/api/portainer-api.ts +0 -374
- package/src/api/profilarr-api.ts +0 -391
- package/src/api/prowlarr-api.ts +0 -488
- package/src/api/qbittorrent-api.ts +0 -300
- package/src/api/quality-profile-api.ts +0 -272
- package/src/api/tautulli-api.ts +0 -244
- package/src/api/uptime-kuma-api.ts +0 -343
- package/src/apps/categories.ts +0 -14
- package/src/apps/index.ts +0 -2
- package/src/apps/registry.ts +0 -1275
- package/src/compose/caddy-config.ts +0 -130
- package/src/compose/generator.ts +0 -287
- package/src/compose/index.ts +0 -7
- package/src/compose/templates.ts +0 -78
- package/src/compose/traefik-config.ts +0 -187
- package/src/config/bookmarks-generator.ts +0 -160
- package/src/config/defaults.ts +0 -37
- package/src/config/homepage-config.ts +0 -381
- package/src/config/index.ts +0 -6
- package/src/config/manager.ts +0 -150
- package/src/config/recyclarr-config.ts +0 -181
- package/src/config/schema.ts +0 -310
- package/src/config/slskd-config.ts +0 -86
- 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 -333
- package/src/docker/client.ts +0 -312
- package/src/docker/index.ts +0 -18
- package/src/index.ts +0 -77
- package/src/setup/actions/arr-common.ts +0 -307
- package/src/setup/actions/dashboards.ts +0 -79
- package/src/setup/actions/download-clients.ts +0 -54
- package/src/setup/actions/jellyseerr.ts +0 -331
- package/src/setup/actions/media-servers.ts +0 -68
- package/src/setup/actions/monitoring.ts +0 -120
- package/src/setup/actions/prowlarr.ts +0 -137
- package/src/setup/actions/utilities.ts +0 -490
- package/src/setup/index.ts +0 -78
- package/src/setup/types.ts +0 -144
- package/src/structure/manager.ts +0 -129
- package/src/ui/App.ts +0 -111
- package/src/ui/components/ApplicationSelector.ts +0 -275
- package/src/ui/components/CredentialsForm.ts +0 -180
- package/src/ui/components/DownloadClientForm.ts +0 -114
- package/src/ui/components/FileEditor.ts +0 -91
- package/src/ui/components/FooterHint.ts +0 -119
- package/src/ui/components/PageLayout.ts +0 -160
- package/src/ui/components/UpdateNotification.ts +0 -102
- package/src/ui/index.ts +0 -7
- package/src/ui/screens/AdvancedSettings.ts +0 -188
- package/src/ui/screens/ApiKeyViewer.ts +0 -511
- package/src/ui/screens/AppConfigurator.ts +0 -543
- package/src/ui/screens/AppManager.ts +0 -284
- package/src/ui/screens/ContainerControl.ts +0 -581
- package/src/ui/screens/LogsViewer.ts +0 -478
- package/src/ui/screens/MainMenu.ts +0 -299
- package/src/ui/screens/MonitorDashboard.ts +0 -881
- package/src/ui/screens/SecretsEditor.ts +0 -216
- package/src/ui/screens/SettingsScreen.ts +0 -633
- package/src/ui/screens/index.ts +0 -22
- package/src/ui/screens/setup/BaseAppSetupScreen.ts +0 -375
- package/src/ui/screens/setup/CloudflaredSetup.ts +0 -460
- package/src/ui/screens/setup/FullAutoSetup.ts +0 -766
- package/src/ui/screens/setup/HomepageSetup.ts +0 -165
- package/src/ui/screens/setup/JellyfinSetup.ts +0 -328
- package/src/ui/screens/setup/JellyseerrSetup.ts +0 -242
- package/src/ui/screens/setup/ProwlarrSetup.ts +0 -500
- package/src/ui/screens/setup/QBittorrentSetup.ts +0 -221
- package/src/ui/screens/setup/QuickSetup.ts +0 -1169
- package/src/ui/screens/setup/RecyclarrSetup.ts +0 -270
- package/src/ui/screens/setup/TRaSHProfileSetup.ts +0 -381
- package/src/utils/arch.ts +0 -78
- package/src/utils/browser.ts +0 -27
- package/src/utils/categories.ts +0 -61
- package/src/utils/debug.ts +0 -84
- package/src/utils/env.ts +0 -138
- package/src/utils/index.ts +0 -8
- package/src/utils/logs.ts +0 -119
- package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -102
- package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -91
- package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -45
- package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -114
- package/src/utils/migrations.ts +0 -165
- package/src/utils/password.ts +0 -42
- package/src/utils/paths.ts +0 -33
- package/src/utils/unraid.ts +0 -103
- package/src/utils/update-checker.ts +0 -210
- package/src/utils/url-utils.ts +0 -38
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises"
|
|
2
|
-
import { dirname } from "node:path"
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
BoxOptions,
|
|
6
|
-
BoxRenderable,
|
|
7
|
-
CliRenderer,
|
|
8
|
-
InputRenderable,
|
|
9
|
-
KeyEvent,
|
|
10
|
-
RenderContext,
|
|
11
|
-
RGBA,
|
|
12
|
-
TextRenderable,
|
|
13
|
-
} from "@opentui/core"
|
|
14
|
-
|
|
15
|
-
import { getApp } from "~/apps/registry"
|
|
16
|
-
import { AppSecret, EasiarrConfig } from "~/config/schema"
|
|
17
|
-
import { getEnvPath, readEnv, updateEnv } from "~/utils/env"
|
|
18
|
-
|
|
19
|
-
export interface SecretsEditorOptions extends BoxOptions {
|
|
20
|
-
config: EasiarrConfig
|
|
21
|
-
onSave: () => void
|
|
22
|
-
onCancel: () => void
|
|
23
|
-
extraEnv?: Record<string, { value: string; description: string }>
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export class SecretsEditor extends BoxRenderable {
|
|
27
|
-
private inputs: Map<string, InputRenderable> = new Map()
|
|
28
|
-
private secrets: Map<string, AppSecret> = new Map()
|
|
29
|
-
private currentFocusIndex = 0
|
|
30
|
-
private inputKeys: string[] = []
|
|
31
|
-
private config: EasiarrConfig
|
|
32
|
-
private onSave: () => void
|
|
33
|
-
private onCancel: () => void
|
|
34
|
-
private extraEnv: Record<string, { value: string; description: string }> = {}
|
|
35
|
-
private envValues: Record<string, string> = {}
|
|
36
|
-
private renderer: CliRenderer
|
|
37
|
-
private keyHandler: ((k: KeyEvent) => void) | null = null
|
|
38
|
-
|
|
39
|
-
constructor(renderer: CliRenderer | RenderContext, options: SecretsEditorOptions) {
|
|
40
|
-
super(renderer, {
|
|
41
|
-
...options,
|
|
42
|
-
border: true,
|
|
43
|
-
borderStyle: "double",
|
|
44
|
-
title: "Secrets Manager (.env)",
|
|
45
|
-
titleAlignment: "center",
|
|
46
|
-
backgroundColor: RGBA.fromHex("#1a1a1a"), // Dark background
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
this.renderer = renderer as CliRenderer
|
|
50
|
-
this.config = options.config
|
|
51
|
-
this.onSave = options.onSave
|
|
52
|
-
this.onCancel = options.onCancel
|
|
53
|
-
this.extraEnv = options.extraEnv || {}
|
|
54
|
-
|
|
55
|
-
this.initSecrets()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private async initSecrets() {
|
|
59
|
-
// 0. Add Extra Env (System Config)
|
|
60
|
-
for (const [key, info] of Object.entries(this.extraEnv)) {
|
|
61
|
-
this.secrets.set(key, {
|
|
62
|
-
name: key,
|
|
63
|
-
description: info.description,
|
|
64
|
-
default: info.value,
|
|
65
|
-
required: true,
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 1. Collect Secrets from Enabled Apps
|
|
70
|
-
for (const appConfig of this.config.apps) {
|
|
71
|
-
if (!appConfig.enabled) continue
|
|
72
|
-
const appDef = getApp(appConfig.id)
|
|
73
|
-
if (appDef && appDef.secrets) {
|
|
74
|
-
for (const secret of appDef.secrets) {
|
|
75
|
-
if (!this.secrets.has(secret.name)) {
|
|
76
|
-
this.secrets.set(secret.name, secret)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (this.secrets.size === 0) {
|
|
83
|
-
this.add(
|
|
84
|
-
new TextRenderable(this.renderer as CliRenderer, {
|
|
85
|
-
content: "No secrets required for selected apps.",
|
|
86
|
-
left: 2,
|
|
87
|
-
top: 2,
|
|
88
|
-
})
|
|
89
|
-
)
|
|
90
|
-
// Add Exit hint
|
|
91
|
-
this.add(
|
|
92
|
-
new TextRenderable(this.renderer as CliRenderer, {
|
|
93
|
-
content: "Press ESC to return",
|
|
94
|
-
bottom: 1,
|
|
95
|
-
left: 2,
|
|
96
|
-
})
|
|
97
|
-
)
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 2. Load existing .env
|
|
102
|
-
await this.loadEnv()
|
|
103
|
-
|
|
104
|
-
// 3. Render Inputs
|
|
105
|
-
const container = new BoxRenderable(this.renderer as CliRenderer, {
|
|
106
|
-
width: "100%",
|
|
107
|
-
flexDirection: "column",
|
|
108
|
-
padding: 1,
|
|
109
|
-
})
|
|
110
|
-
this.add(container)
|
|
111
|
-
|
|
112
|
-
this.secrets.forEach((secret, key) => {
|
|
113
|
-
const row = new BoxRenderable(this.renderer as CliRenderer, {
|
|
114
|
-
width: "100%",
|
|
115
|
-
height: 1,
|
|
116
|
-
flexDirection: "row",
|
|
117
|
-
marginBottom: 1,
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// Label
|
|
121
|
-
const label = new TextRenderable(this.renderer as CliRenderer, {
|
|
122
|
-
content: `${secret.name}${secret.required ? "*" : ""}:`.padEnd(30),
|
|
123
|
-
width: 30,
|
|
124
|
-
fg: secret.required ? RGBA.fromHex("#ff5555") : RGBA.fromHex("#aaaaaa"),
|
|
125
|
-
})
|
|
126
|
-
row.add(label)
|
|
127
|
-
|
|
128
|
-
// Input
|
|
129
|
-
const input = new InputRenderable(this.renderer as CliRenderer, {
|
|
130
|
-
id: `input-${key}`,
|
|
131
|
-
width: 60, // Wider for paths
|
|
132
|
-
placeholder: secret.description,
|
|
133
|
-
backgroundColor: RGBA.fromHex("#333333"),
|
|
134
|
-
focusedBackgroundColor: RGBA.fromHex("#444444"),
|
|
135
|
-
textColor: RGBA.fromHex("#ffffff"),
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
// Prefer envValue > default > empty
|
|
139
|
-
input.value = this.envValues[key] || secret.default || ""
|
|
140
|
-
|
|
141
|
-
row.add(input)
|
|
142
|
-
container.add(row)
|
|
143
|
-
|
|
144
|
-
this.inputs.set(key, input)
|
|
145
|
-
this.inputKeys.push(key)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
// Instructions
|
|
149
|
-
this.add(
|
|
150
|
-
new TextRenderable(this.renderer as CliRenderer, {
|
|
151
|
-
content: "TAB: Next Field | CTRL+S: Save | ESC: Cancel",
|
|
152
|
-
bottom: 0,
|
|
153
|
-
left: 2,
|
|
154
|
-
width: "100%",
|
|
155
|
-
})
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
// Global Key Handling (intercept Tab, Enter, Esc, Ctrl+S)
|
|
159
|
-
this.keyHandler = (k: KeyEvent) => {
|
|
160
|
-
// Allow inputs to handle typing, but intercept navigation/actions
|
|
161
|
-
if (k.name === "tab") {
|
|
162
|
-
// k.preventDefault() // Prevent Input from adding tab char?
|
|
163
|
-
this.focusNext()
|
|
164
|
-
} else if (k.name === "s" && k.ctrl) {
|
|
165
|
-
// k.preventDefault()
|
|
166
|
-
this.save()
|
|
167
|
-
} else if (k.name === "escape") {
|
|
168
|
-
this.onCancel()
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
this.renderer.keyInput.on("keypress", this.keyHandler)
|
|
172
|
-
|
|
173
|
-
// Focus first
|
|
174
|
-
if (this.inputKeys.length > 0) {
|
|
175
|
-
this.inputs.get(this.inputKeys[0])?.focus()
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
private async loadEnv() {
|
|
180
|
-
this.envValues = await readEnv()
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
private async save() {
|
|
184
|
-
// Collect values from inputs
|
|
185
|
-
const updates: Record<string, string> = {}
|
|
186
|
-
this.inputs.forEach((input, key) => {
|
|
187
|
-
updates[key] = input.value
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
// Ensure directory exists
|
|
191
|
-
try {
|
|
192
|
-
await mkdir(dirname(getEnvPath()), { recursive: true })
|
|
193
|
-
} catch {
|
|
194
|
-
// Ignore if exists
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Update .env file
|
|
198
|
-
await updateEnv(updates)
|
|
199
|
-
|
|
200
|
-
this.onSave()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
override destroy(): void {
|
|
204
|
-
if (this.keyHandler) {
|
|
205
|
-
this.renderer.keyInput.off("keypress", this.keyHandler)
|
|
206
|
-
this.keyHandler = null
|
|
207
|
-
}
|
|
208
|
-
super.destroy()
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
private focusNext() {
|
|
212
|
-
this.currentFocusIndex = (this.currentFocusIndex + 1) % this.inputKeys.length
|
|
213
|
-
const key = this.inputKeys[this.currentFocusIndex]
|
|
214
|
-
this.inputs.get(key)?.focus()
|
|
215
|
-
}
|
|
216
|
-
}
|