@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
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Homepage Setup Screen
|
|
3
|
-
* Configure Homepage dashboard with enabled apps
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { BoxRenderable, CliRenderer, TextRenderable, KeyEvent } from "@opentui/core"
|
|
7
|
-
import { createPageLayout } from "../components/PageLayout"
|
|
8
|
-
import { EasiarrConfig } from "../../config/schema"
|
|
9
|
-
import { saveHomepageConfig, generateServicesYaml } from "../../config/homepage-config"
|
|
10
|
-
import { getApp } from "../../apps/registry"
|
|
11
|
-
|
|
12
|
-
interface SetupResult {
|
|
13
|
-
name: string
|
|
14
|
-
status: "pending" | "configuring" | "success" | "error" | "skipped"
|
|
15
|
-
message?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type Step = "menu" | "generating" | "preview" | "done"
|
|
19
|
-
|
|
20
|
-
export class HomepageSetup extends BoxRenderable {
|
|
21
|
-
private config: EasiarrConfig
|
|
22
|
-
private cliRenderer: CliRenderer
|
|
23
|
-
private onBack: () => void
|
|
24
|
-
private keyHandler!: (key: KeyEvent) => void
|
|
25
|
-
private results: SetupResult[] = []
|
|
26
|
-
private currentStep: Step = "menu"
|
|
27
|
-
private contentBox!: BoxRenderable
|
|
28
|
-
private pageContainer!: BoxRenderable
|
|
29
|
-
private menuIndex = 0
|
|
30
|
-
private previewContent = ""
|
|
31
|
-
|
|
32
|
-
constructor(cliRenderer: CliRenderer, config: EasiarrConfig, onBack: () => void) {
|
|
33
|
-
const { container: pageContainer, content: contentBox } = createPageLayout(cliRenderer, {
|
|
34
|
-
title: "Homepage Setup",
|
|
35
|
-
stepInfo: "Configure Dashboard",
|
|
36
|
-
footerHint: [
|
|
37
|
-
{ type: "key", key: "↑↓", value: "Navigate" },
|
|
38
|
-
{ type: "key", key: "Enter", value: "Select" },
|
|
39
|
-
{ type: "key", key: "Esc", value: "Back" },
|
|
40
|
-
],
|
|
41
|
-
})
|
|
42
|
-
super(cliRenderer, { width: "100%", height: "100%" })
|
|
43
|
-
this.add(pageContainer)
|
|
44
|
-
|
|
45
|
-
this.config = config
|
|
46
|
-
this.cliRenderer = cliRenderer
|
|
47
|
-
this.onBack = onBack
|
|
48
|
-
this.contentBox = contentBox
|
|
49
|
-
this.pageContainer = pageContainer
|
|
50
|
-
|
|
51
|
-
this.initKeyHandler()
|
|
52
|
-
this.refreshContent()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private initKeyHandler(): void {
|
|
56
|
-
this.keyHandler = (key: KeyEvent) => {
|
|
57
|
-
if (key.name === "escape" || (key.name === "c" && key.ctrl)) {
|
|
58
|
-
if (this.currentStep === "menu") {
|
|
59
|
-
this.cleanup()
|
|
60
|
-
} else {
|
|
61
|
-
this.currentStep = "menu"
|
|
62
|
-
this.refreshContent()
|
|
63
|
-
}
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (this.currentStep === "menu") {
|
|
68
|
-
this.handleMenuKeys(key)
|
|
69
|
-
} else if (this.currentStep === "preview" || this.currentStep === "done") {
|
|
70
|
-
if (key.name === "return" || key.name === "escape") {
|
|
71
|
-
this.currentStep = "menu"
|
|
72
|
-
this.refreshContent()
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
this.cliRenderer.keyInput.on("keypress", this.keyHandler)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private handleMenuKeys(key: KeyEvent): void {
|
|
80
|
-
const menuItems = this.getMenuItems()
|
|
81
|
-
|
|
82
|
-
if (key.name === "up" && this.menuIndex > 0) {
|
|
83
|
-
this.menuIndex--
|
|
84
|
-
this.refreshContent()
|
|
85
|
-
} else if (key.name === "down" && this.menuIndex < menuItems.length - 1) {
|
|
86
|
-
this.menuIndex++
|
|
87
|
-
this.refreshContent()
|
|
88
|
-
} else if (key.name === "return") {
|
|
89
|
-
this.executeMenuItem(this.menuIndex)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private getMenuItems(): { name: string; description: string; action: () => void }[] {
|
|
94
|
-
return [
|
|
95
|
-
{
|
|
96
|
-
name: "📊 Generate Services",
|
|
97
|
-
description: "Create services.yaml with all enabled apps",
|
|
98
|
-
action: () => this.generateServices(),
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "👁️ Preview Config",
|
|
102
|
-
description: "Preview generated services.yaml",
|
|
103
|
-
action: () => this.previewServices(),
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
name: "📋 Show Enabled Apps",
|
|
107
|
-
description: "List apps that will be added to Homepage",
|
|
108
|
-
action: () => this.showEnabledApps(),
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
name: "↩️ Back",
|
|
112
|
-
description: "Return to main menu",
|
|
113
|
-
action: () => this.cleanup(),
|
|
114
|
-
},
|
|
115
|
-
]
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private executeMenuItem(index: number): void {
|
|
119
|
-
const items = this.getMenuItems()
|
|
120
|
-
if (index >= 0 && index < items.length) {
|
|
121
|
-
items[index].action()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private async generateServices(): Promise<void> {
|
|
126
|
-
this.currentStep = "generating"
|
|
127
|
-
this.results = [{ name: "services.yaml", status: "configuring" }]
|
|
128
|
-
this.refreshContent()
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
const paths = await saveHomepageConfig(this.config)
|
|
132
|
-
this.results[0].status = "success"
|
|
133
|
-
this.results[0].message = `Saved to ${paths.services}`
|
|
134
|
-
} catch (error) {
|
|
135
|
-
this.results[0].status = "error"
|
|
136
|
-
this.results[0].message = error instanceof Error ? error.message : String(error)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
this.currentStep = "done"
|
|
140
|
-
this.refreshContent()
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private async previewServices(): Promise<void> {
|
|
144
|
-
this.previewContent = await generateServicesYaml(this.config)
|
|
145
|
-
this.currentStep = "preview"
|
|
146
|
-
this.refreshContent()
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private showEnabledApps(): void {
|
|
150
|
-
const apps = this.config.apps.filter((a) => a.enabled && a.id !== "homepage")
|
|
151
|
-
|
|
152
|
-
this.results = apps.map((app) => {
|
|
153
|
-
const def = getApp(app.id)
|
|
154
|
-
const hasWidget = def?.homepage?.widget ? "📊" : "📌"
|
|
155
|
-
return {
|
|
156
|
-
name: `${hasWidget} ${def?.name || app.id}`,
|
|
157
|
-
status: "success" as const,
|
|
158
|
-
message: def?.description,
|
|
159
|
-
}
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
if (this.results.length === 0) {
|
|
163
|
-
this.results = [{ name: "No apps enabled", status: "skipped", message: "Enable apps first" }]
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
this.currentStep = "done"
|
|
167
|
-
this.refreshContent()
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private refreshContent(): void {
|
|
171
|
-
this.contentBox.getChildren().forEach((child) => child.destroy())
|
|
172
|
-
|
|
173
|
-
if (this.currentStep === "menu") {
|
|
174
|
-
this.renderMenu()
|
|
175
|
-
} else if (this.currentStep === "preview") {
|
|
176
|
-
this.renderPreview()
|
|
177
|
-
} else {
|
|
178
|
-
this.renderResults()
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private renderMenu(): void {
|
|
183
|
-
this.contentBox.add(
|
|
184
|
-
new TextRenderable(this.cliRenderer, {
|
|
185
|
-
content: "Configure Homepage dashboard with your enabled apps:\n\n",
|
|
186
|
-
fg: "#aaaaaa",
|
|
187
|
-
})
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
this.getMenuItems().forEach((item, idx) => {
|
|
191
|
-
const pointer = idx === this.menuIndex ? "→ " : " "
|
|
192
|
-
const fg = idx === this.menuIndex ? "#50fa7b" : "#8be9fd"
|
|
193
|
-
|
|
194
|
-
this.contentBox.add(
|
|
195
|
-
new TextRenderable(this.cliRenderer, {
|
|
196
|
-
content: `${pointer}${item.name}\n`,
|
|
197
|
-
fg,
|
|
198
|
-
})
|
|
199
|
-
)
|
|
200
|
-
this.contentBox.add(
|
|
201
|
-
new TextRenderable(this.cliRenderer, {
|
|
202
|
-
content: ` ${item.description}\n\n`,
|
|
203
|
-
fg: "#6272a4",
|
|
204
|
-
})
|
|
205
|
-
)
|
|
206
|
-
})
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private renderPreview(): void {
|
|
210
|
-
this.contentBox.add(
|
|
211
|
-
new TextRenderable(this.cliRenderer, {
|
|
212
|
-
content: "Preview: services.yaml\n",
|
|
213
|
-
fg: "#50fa7b",
|
|
214
|
-
})
|
|
215
|
-
)
|
|
216
|
-
this.contentBox.add(
|
|
217
|
-
new TextRenderable(this.cliRenderer, {
|
|
218
|
-
content: "─".repeat(40) + "\n",
|
|
219
|
-
fg: "#555555",
|
|
220
|
-
})
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
// Show preview (truncated)
|
|
224
|
-
const lines = this.previewContent.split("\n").slice(0, 30)
|
|
225
|
-
for (const line of lines) {
|
|
226
|
-
this.contentBox.add(
|
|
227
|
-
new TextRenderable(this.cliRenderer, {
|
|
228
|
-
content: line + "\n",
|
|
229
|
-
fg: line.startsWith("#") ? "#6272a4" : line.endsWith(":") ? "#8be9fd" : "#f8f8f2",
|
|
230
|
-
})
|
|
231
|
-
)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (this.previewContent.split("\n").length > 30) {
|
|
235
|
-
this.contentBox.add(
|
|
236
|
-
new TextRenderable(this.cliRenderer, {
|
|
237
|
-
content: "\n... (truncated)\n",
|
|
238
|
-
fg: "#6272a4",
|
|
239
|
-
})
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
this.contentBox.add(
|
|
244
|
-
new TextRenderable(this.cliRenderer, {
|
|
245
|
-
content: "\nPress Enter or Esc to go back",
|
|
246
|
-
fg: "#6272a4",
|
|
247
|
-
})
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private renderResults(): void {
|
|
252
|
-
const headerText = this.currentStep === "done" ? "Results:\n\n" : "Generating...\n\n"
|
|
253
|
-
this.contentBox.add(
|
|
254
|
-
new TextRenderable(this.cliRenderer, {
|
|
255
|
-
content: headerText,
|
|
256
|
-
fg: this.currentStep === "done" ? "#50fa7b" : "#f1fa8c",
|
|
257
|
-
})
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
for (const result of this.results) {
|
|
261
|
-
let status = ""
|
|
262
|
-
let fg = "#aaaaaa"
|
|
263
|
-
switch (result.status) {
|
|
264
|
-
case "pending":
|
|
265
|
-
status = "⏳"
|
|
266
|
-
break
|
|
267
|
-
case "configuring":
|
|
268
|
-
status = "🔄"
|
|
269
|
-
fg = "#f1fa8c"
|
|
270
|
-
break
|
|
271
|
-
case "success":
|
|
272
|
-
status = "✓"
|
|
273
|
-
fg = "#50fa7b"
|
|
274
|
-
break
|
|
275
|
-
case "error":
|
|
276
|
-
status = "✗"
|
|
277
|
-
fg = "#ff5555"
|
|
278
|
-
break
|
|
279
|
-
case "skipped":
|
|
280
|
-
status = "⊘"
|
|
281
|
-
fg = "#6272a4"
|
|
282
|
-
break
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
let content = `${status} ${result.name}`
|
|
286
|
-
if (result.message) {
|
|
287
|
-
content += ` - ${result.message}`
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
this.contentBox.add(new TextRenderable(this.cliRenderer, { content: content + "\n", fg }))
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
this.contentBox.add(
|
|
294
|
-
new TextRenderable(this.cliRenderer, {
|
|
295
|
-
content: "\nPress Enter or Esc to continue...",
|
|
296
|
-
fg: "#6272a4",
|
|
297
|
-
})
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
private cleanup(): void {
|
|
302
|
-
this.cliRenderer.keyInput.off("keypress", this.keyHandler)
|
|
303
|
-
this.destroy()
|
|
304
|
-
this.onBack()
|
|
305
|
-
}
|
|
306
|
-
}
|