@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,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
- }