@muhammedaksam/easiarr 1.4.0 → 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 (109) hide show
  1. package/dist/index.js +29837 -0
  2. package/package.json +15 -15
  3. package/src/VersionInfo.ts +0 -12
  4. package/src/api/arr-api.ts +0 -521
  5. package/src/api/auto-setup-types.ts +0 -64
  6. package/src/api/base-api.ts +0 -216
  7. package/src/api/bazarr-api.ts +0 -297
  8. package/src/api/cloudflare-api.ts +0 -493
  9. package/src/api/custom-format-api.ts +0 -224
  10. package/src/api/grafana-api.ts +0 -230
  11. package/src/api/heimdall-api.ts +0 -141
  12. package/src/api/homarr-api.ts +0 -209
  13. package/src/api/huntarr-api.ts +0 -457
  14. package/src/api/index.ts +0 -9
  15. package/src/api/jellyfin-api.ts +0 -389
  16. package/src/api/jellyseerr-api.ts +0 -559
  17. package/src/api/maintainerr-api.ts +0 -461
  18. package/src/api/naming-config.ts +0 -101
  19. package/src/api/overseerr-api.ts +0 -392
  20. package/src/api/plex-api.ts +0 -308
  21. package/src/api/portainer-api.ts +0 -374
  22. package/src/api/profilarr-api.ts +0 -391
  23. package/src/api/prowlarr-api.ts +0 -488
  24. package/src/api/qbittorrent-api.ts +0 -300
  25. package/src/api/quality-profile-api.ts +0 -272
  26. package/src/api/tautulli-api.ts +0 -244
  27. package/src/api/uptime-kuma-api.ts +0 -343
  28. package/src/apps/categories.ts +0 -14
  29. package/src/apps/index.ts +0 -2
  30. package/src/apps/registry.ts +0 -1275
  31. package/src/compose/caddy-config.ts +0 -130
  32. package/src/compose/generator.ts +0 -287
  33. package/src/compose/index.ts +0 -7
  34. package/src/compose/templates.ts +0 -78
  35. package/src/compose/traefik-config.ts +0 -187
  36. package/src/config/bookmarks-generator.ts +0 -160
  37. package/src/config/defaults.ts +0 -37
  38. package/src/config/homepage-config.ts +0 -381
  39. package/src/config/index.ts +0 -6
  40. package/src/config/manager.ts +0 -150
  41. package/src/config/recyclarr-config.ts +0 -181
  42. package/src/config/schema.ts +0 -310
  43. package/src/config/slskd-config.ts +0 -86
  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 -333
  48. package/src/docker/client.ts +0 -312
  49. package/src/docker/index.ts +0 -18
  50. package/src/index.ts +0 -77
  51. package/src/setup/actions/arr-common.ts +0 -307
  52. package/src/setup/actions/dashboards.ts +0 -79
  53. package/src/setup/actions/download-clients.ts +0 -54
  54. package/src/setup/actions/jellyseerr.ts +0 -331
  55. package/src/setup/actions/media-servers.ts +0 -68
  56. package/src/setup/actions/monitoring.ts +0 -120
  57. package/src/setup/actions/prowlarr.ts +0 -137
  58. package/src/setup/actions/utilities.ts +0 -490
  59. package/src/setup/index.ts +0 -78
  60. package/src/setup/types.ts +0 -144
  61. package/src/structure/manager.ts +0 -129
  62. package/src/ui/App.ts +0 -111
  63. package/src/ui/components/ApplicationSelector.ts +0 -275
  64. package/src/ui/components/CredentialsForm.ts +0 -180
  65. package/src/ui/components/DownloadClientForm.ts +0 -114
  66. package/src/ui/components/FileEditor.ts +0 -91
  67. package/src/ui/components/FooterHint.ts +0 -119
  68. package/src/ui/components/PageLayout.ts +0 -160
  69. package/src/ui/components/UpdateNotification.ts +0 -102
  70. package/src/ui/index.ts +0 -7
  71. package/src/ui/screens/AdvancedSettings.ts +0 -188
  72. package/src/ui/screens/ApiKeyViewer.ts +0 -511
  73. package/src/ui/screens/AppConfigurator.ts +0 -543
  74. package/src/ui/screens/AppManager.ts +0 -284
  75. package/src/ui/screens/ContainerControl.ts +0 -581
  76. package/src/ui/screens/LogsViewer.ts +0 -478
  77. package/src/ui/screens/MainMenu.ts +0 -299
  78. package/src/ui/screens/MonitorDashboard.ts +0 -881
  79. package/src/ui/screens/SecretsEditor.ts +0 -216
  80. package/src/ui/screens/SettingsScreen.ts +0 -633
  81. package/src/ui/screens/index.ts +0 -22
  82. package/src/ui/screens/setup/BaseAppSetupScreen.ts +0 -375
  83. package/src/ui/screens/setup/CloudflaredSetup.ts +0 -460
  84. package/src/ui/screens/setup/FullAutoSetup.ts +0 -766
  85. package/src/ui/screens/setup/HomepageSetup.ts +0 -165
  86. package/src/ui/screens/setup/JellyfinSetup.ts +0 -328
  87. package/src/ui/screens/setup/JellyseerrSetup.ts +0 -242
  88. package/src/ui/screens/setup/ProwlarrSetup.ts +0 -500
  89. package/src/ui/screens/setup/QBittorrentSetup.ts +0 -221
  90. package/src/ui/screens/setup/QuickSetup.ts +0 -1169
  91. package/src/ui/screens/setup/RecyclarrSetup.ts +0 -270
  92. package/src/ui/screens/setup/TRaSHProfileSetup.ts +0 -381
  93. package/src/utils/arch.ts +0 -78
  94. package/src/utils/browser.ts +0 -27
  95. package/src/utils/categories.ts +0 -61
  96. package/src/utils/debug.ts +0 -84
  97. package/src/utils/env.ts +0 -138
  98. package/src/utils/index.ts +0 -8
  99. package/src/utils/logs.ts +0 -119
  100. package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -102
  101. package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -91
  102. package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -45
  103. package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -114
  104. package/src/utils/migrations.ts +0 -165
  105. package/src/utils/password.ts +0 -42
  106. package/src/utils/paths.ts +0 -33
  107. package/src/utils/unraid.ts +0 -103
  108. package/src/utils/update-checker.ts +0 -210
  109. package/src/utils/url-utils.ts +0 -38
@@ -1,333 +0,0 @@
1
- /**
2
- * TRaSH Guide Quality Profile Presets
3
- * Pre-configured quality profiles based on TRaSH Guides recommendations
4
- */
5
-
6
- export interface TRaSHProfilePreset {
7
- id: string
8
- name: string
9
- description: string
10
- app: "radarr" | "sonarr" | "lidarr" | "both"
11
- cutoffQuality: string
12
- allowedQualities: string[]
13
- cfScores: Record<string, number>
14
- }
15
-
16
- // Quality names for different resolutions
17
- export const RADARR_QUALITIES = {
18
- // HD
19
- "Bluray-1080p": "Bluray-1080p",
20
- "WEB-1080p": "WEBDL-1080p",
21
- "HDTV-1080p": "HDTV-1080p",
22
- "Bluray-720p": "Bluray-720p",
23
- "WEB-720p": "WEBDL-720p",
24
- // UHD
25
- "Bluray-2160p": "Bluray-2160p",
26
- "WEB-2160p": "WEBDL-2160p",
27
- // Remux
28
- "Remux-1080p": "Remux-1080p",
29
- "Remux-2160p": "Remux-2160p",
30
- }
31
-
32
- export const SONARR_QUALITIES = {
33
- "WEB-1080p": "WEBDL-1080p",
34
- "WEB-720p": "WEBDL-720p",
35
- "WEB-2160p": "WEBDL-2160p",
36
- "HDTV-1080p": "HDTV-1080p",
37
- "HDTV-720p": "HDTV-720p",
38
- "Bluray-1080p": "Bluray-1080p",
39
- "Bluray-720p": "Bluray-720p",
40
- "Bluray-2160p": "Bluray-2160p",
41
- "Remux-1080p": "Remux-1080p",
42
- "Remux-2160p": "Remux-2160p",
43
- }
44
-
45
- // TRaSH recommended Custom Format scores
46
- export const CF_SCORES = {
47
- // Unwanted (use negative scores)
48
- "BR-DISK": -10000,
49
- LQ: -10000,
50
- "LQ (Release Title)": -10000,
51
- "3D": -10000,
52
- x265: -10000, // Only for HD, not UHD
53
- Extras: -10000,
54
-
55
- // Preferred (positive scores)
56
- "Repack/Proper": 5,
57
- Repack2: 6,
58
-
59
- // HDR Formats
60
- "DV HDR10Plus": 1600,
61
- "DV HDR10": 1500,
62
- DV: 1400,
63
- "DV HLG": 1300,
64
- "DV SDR": 1200,
65
- HDR10Plus: 700,
66
- HDR10: 600,
67
- HDR: 500,
68
- "HDR (undefined)": 400,
69
- PQ: 300,
70
- HLG: 200,
71
-
72
- // Audio Formats
73
- "TrueHD Atmos": 5000,
74
- "DTS X": 4500,
75
- TrueHD: 4000,
76
- "DTS-HD MA": 3500,
77
- FLAC: 3000,
78
- PCM: 2500,
79
- "DTS-HD HRA": 2000,
80
- "DD+ Atmos": 1500,
81
- "DD+": 1000,
82
- "DTS-ES": 800,
83
- DTS: 600,
84
- AAC: 400,
85
- DD: 300,
86
-
87
- // Streaming Services
88
- AMZN: 0,
89
- ATVP: 100,
90
- DSNP: 100,
91
- HBO: 0,
92
- HMAX: 0,
93
- Hulu: 0,
94
- MA: 0,
95
- NF: 0,
96
- PCOK: 0,
97
- PMTP: 0,
98
-
99
- // Movie Versions
100
- "IMAX Enhanced": 800,
101
- IMAX: 700,
102
- Hybrid: 100,
103
- "Criterion Collection": 100,
104
- "Special Edition": 50,
105
- "Theatrical Cut": 0,
106
-
107
- // HQ Release Groups
108
- "HQ-Remux": 1750,
109
- "HQ-WEBDL": 1700,
110
- HQ: 1600,
111
- }
112
-
113
- // Radarr Profile Presets
114
- export const RADARR_PRESETS: TRaSHProfilePreset[] = [
115
- {
116
- id: "hd-bluray-web",
117
- name: "HD Bluray + WEB",
118
- description: "High-Quality HD Encodes (Bluray-720p/1080p). Size: 6-15 GB",
119
- app: "radarr",
120
- cutoffQuality: "Bluray-1080p",
121
- allowedQualities: [
122
- "Bluray-1080p",
123
- "Bluray-720p",
124
- "WEBDL-1080p",
125
- "WEBDL-720p",
126
- "WEBRip-1080p",
127
- "WEBRip-720p",
128
- ],
129
- cfScores: {
130
- "BR-DISK": -10000,
131
- LQ: -10000,
132
- "LQ (Release Title)": -10000,
133
- "3D": -10000,
134
- "x265 (HD)": -10000,
135
- "Repack/Proper": 5,
136
- "HQ-WEBDL": 1700,
137
- HQ: 1600,
138
- },
139
- },
140
- {
141
- id: "uhd-bluray-web",
142
- name: "UHD Bluray + WEB",
143
- description: "High-Quality UHD Encodes (Bluray-2160p). Size: 20-60 GB",
144
- app: "radarr",
145
- cutoffQuality: "Bluray-2160p",
146
- allowedQualities: ["Bluray-2160p", "WEBDL-2160p", "WEBRip-2160p"],
147
- cfScores: {
148
- "BR-DISK": -10000,
149
- LQ: -10000,
150
- "LQ (Release Title)": -10000,
151
- "DV HDR10Plus": 1600,
152
- "DV HDR10": 1500,
153
- DV: 1400,
154
- HDR10Plus: 700,
155
- HDR10: 600,
156
- "Repack/Proper": 5,
157
- "TrueHD Atmos": 5000,
158
- "DTS X": 4500,
159
- "HQ-WEBDL": 1700,
160
- },
161
- },
162
- {
163
- id: "remux-web-1080p",
164
- name: "Remux + WEB 1080p",
165
- description: "1080p Remuxes. Size: 20-40 GB",
166
- app: "radarr",
167
- cutoffQuality: "Remux-1080p",
168
- allowedQualities: ["Remux-1080p", "WEBDL-1080p", "WEBRip-1080p"],
169
- cfScores: {
170
- "BR-DISK": -10000,
171
- LQ: -10000,
172
- "x265 (HD)": -10000,
173
- "HQ-Remux": 1750,
174
- "Repack/Proper": 5,
175
- "TrueHD Atmos": 5000,
176
- "DTS X": 4500,
177
- TrueHD: 4000,
178
- "DTS-HD MA": 3500,
179
- },
180
- },
181
- {
182
- id: "remux-web-2160p",
183
- name: "Remux + WEB 2160p",
184
- description: "2160p Remuxes. Size: 40-100 GB",
185
- app: "radarr",
186
- cutoffQuality: "Remux-2160p",
187
- allowedQualities: ["Remux-2160p", "WEBDL-2160p", "WEBRip-2160p"],
188
- cfScores: {
189
- "BR-DISK": -10000,
190
- LQ: -10000,
191
- "DV HDR10Plus": 1600,
192
- "DV HDR10": 1500,
193
- DV: 1400,
194
- HDR10Plus: 700,
195
- HDR10: 600,
196
- "HQ-Remux": 1750,
197
- "Repack/Proper": 5,
198
- "TrueHD Atmos": 5000,
199
- "DTS X": 4500,
200
- },
201
- },
202
- ]
203
-
204
- // Sonarr Profile Presets
205
- export const SONARR_PRESETS: TRaSHProfilePreset[] = [
206
- {
207
- id: "web-1080p",
208
- name: "WEB-1080p",
209
- description: "720p/1080p WEBDL. Balanced quality and size",
210
- app: "sonarr",
211
- cutoffQuality: "WEBDL-1080p",
212
- allowedQualities: ["WEBDL-1080p", "WEBRip-1080p", "WEBDL-720p", "WEBRip-720p"],
213
- cfScores: {
214
- "BR-DISK": -10000,
215
- LQ: -10000,
216
- "x265 (HD)": -10000,
217
- "Repack/Proper": 5,
218
- "HQ-WEBDL": 1700,
219
- AMZN: 100,
220
- ATVP: 100,
221
- DSNP: 100,
222
- NF: 100,
223
- },
224
- },
225
- {
226
- id: "web-2160p",
227
- name: "WEB-2160p",
228
- description: "2160p WEBDL with HDR. Premium quality",
229
- app: "sonarr",
230
- cutoffQuality: "WEBDL-2160p",
231
- allowedQualities: ["WEBDL-2160p", "WEBRip-2160p"],
232
- cfScores: {
233
- "BR-DISK": -10000,
234
- LQ: -10000,
235
- "DV HDR10Plus": 1600,
236
- "DV HDR10": 1500,
237
- DV: 1400,
238
- HDR10Plus: 700,
239
- HDR10: 600,
240
- "Repack/Proper": 5,
241
- "HQ-WEBDL": 1700,
242
- AMZN: 100,
243
- ATVP: 100,
244
- NF: 100,
245
- },
246
- },
247
- ]
248
-
249
- // Lidarr Quality Names (Davo's Community Guide)
250
- export const LIDARR_QUALITIES = {
251
- FLAC: "FLAC",
252
- "FLAC 24bit": "FLAC 24bit",
253
- "MP3-320": "MP3-320",
254
- "MP3-256": "MP3-256",
255
- "MP3-128": "MP3-128",
256
- }
257
-
258
- // Lidarr Custom Format Scores (Davo's Community Guide)
259
- // Scoring requires minimum 1 to grab, prefers CD > WEB, avoids Vinyl
260
- export const LIDARR_CF_SCORES = {
261
- // Preferred Release Groups
262
- "Preferred Groups": 5,
263
-
264
- // Source Preferences
265
- CD: 3, // Prefer CD source
266
- WEB: 2, // Accept WEB source
267
- Lossless: 1, // Tag for lossless
268
-
269
- // Avoid Vinyl (analog noise, pops, clicks)
270
- Vinyl: -10000,
271
- }
272
-
273
- // Lidarr Profile Presets (Davo's Community Guide)
274
- export const LIDARR_PRESETS: TRaSHProfilePreset[] = [
275
- {
276
- id: "high-quality-flac",
277
- name: "High Quality FLAC",
278
- description: "FLAC quality with MP3-320 fallback. Prefers CD source, avoids Vinyl.",
279
- app: "lidarr",
280
- cutoffQuality: "FLAC",
281
- allowedQualities: ["FLAC", "FLAC 24bit", "MP3-320"],
282
- cfScores: {
283
- "Preferred Groups": 5,
284
- CD: 3,
285
- WEB: 2,
286
- Lossless: 1,
287
- Vinyl: -10000,
288
- },
289
- },
290
- {
291
- id: "flac-only",
292
- name: "FLAC Only",
293
- description: "Lossless FLAC only, no MP3 fallback. Best quality.",
294
- app: "lidarr",
295
- cutoffQuality: "FLAC",
296
- allowedQualities: ["FLAC", "FLAC 24bit"],
297
- cfScores: {
298
- "Preferred Groups": 5,
299
- CD: 3,
300
- WEB: 2,
301
- Lossless: 1,
302
- Vinyl: -10000,
303
- },
304
- },
305
- {
306
- id: "any-quality",
307
- name: "Any Quality",
308
- description: "Accept any quality including MP3. For maximum availability.",
309
- app: "lidarr",
310
- cutoffQuality: "MP3-320",
311
- allowedQualities: ["FLAC", "FLAC 24bit", "MP3-320", "MP3-256", "MP3-128"],
312
- cfScores: {
313
- "Preferred Groups": 5,
314
- CD: 3,
315
- WEB: 2,
316
- Lossless: 1,
317
- Vinyl: -10000,
318
- },
319
- },
320
- ]
321
-
322
- // Get all presets for an app
323
- export function getPresetsForApp(app: "radarr" | "sonarr" | "lidarr"): TRaSHProfilePreset[] {
324
- if (app === "radarr") return RADARR_PRESETS
325
- if (app === "sonarr") return SONARR_PRESETS
326
- if (app === "lidarr") return LIDARR_PRESETS
327
- return []
328
- }
329
-
330
- // Get a specific preset by ID
331
- export function getPresetById(id: string): TRaSHProfilePreset | undefined {
332
- return [...RADARR_PRESETS, ...SONARR_PRESETS, ...LIDARR_PRESETS].find((p) => p.id === id)
333
- }
@@ -1,312 +0,0 @@
1
- /**
2
- * Docker Client
3
- * Wrapper for docker compose commands using Bun.$
4
- */
5
-
6
- import { $ } from "bun"
7
-
8
- import { getComposePath } from "~/config/manager"
9
- import { debugLog } from "~/utils/debug"
10
-
11
- export interface ContainerStatus {
12
- name: string
13
- status: "running" | "stopped" | "not_found"
14
- ports?: string
15
- }
16
-
17
- export async function composeUp(): Promise<{
18
- success: boolean
19
- output: string
20
- }> {
21
- try {
22
- const composePath = getComposePath()
23
- debugLog("Docker", `compose up -d (path: ${composePath})`)
24
- const result = await $`docker compose -f ${composePath} up -d`.text()
25
- debugLog("Docker", `compose up success`)
26
- return { success: true, output: result }
27
- } catch (error) {
28
- debugLog("Docker", `compose up failed: ${error}`)
29
- return { success: false, output: String(error) }
30
- }
31
- }
32
-
33
- export async function composeDown(): Promise<{
34
- success: boolean
35
- output: string
36
- }> {
37
- try {
38
- const composePath = getComposePath()
39
- debugLog("Docker", `compose down (path: ${composePath})`)
40
- const result = await $`docker compose -f ${composePath} down`.text()
41
- debugLog("Docker", `compose down success`)
42
- return { success: true, output: result }
43
- } catch (error) {
44
- debugLog("Docker", `compose down failed: ${error}`)
45
- return { success: false, output: String(error) }
46
- }
47
- }
48
-
49
- /**
50
- * Run a one-off container with docker compose run --rm
51
- */
52
- export async function composeRun(
53
- service: string,
54
- command: string
55
- ): Promise<{ success: boolean; output: string }> {
56
- try {
57
- const composePath = getComposePath()
58
- debugLog("Docker", `compose run --rm ${service} ${command}`)
59
- const result = await $`docker compose -f ${composePath} run --rm ${service} ${command}`.text()
60
- debugLog("Docker", `compose run success`)
61
- return { success: true, output: result }
62
- } catch (error) {
63
- debugLog("Docker", `compose run failed: ${error}`)
64
- return { success: false, output: String(error) }
65
- }
66
- }
67
-
68
- export async function composeRestart(
69
- service?: string
70
- ): Promise<{ success: boolean; output: string }> {
71
- try {
72
- const composePath = getComposePath()
73
- debugLog("Docker", `compose restart ${service || "all"}`)
74
- const result = service
75
- ? await $`docker compose -f ${composePath} restart ${service}`.text()
76
- : await $`docker compose -f ${composePath} restart`.text()
77
- debugLog("Docker", `compose restart success`)
78
- return { success: true, output: result }
79
- } catch (error) {
80
- debugLog("Docker", `compose restart failed: ${error}`)
81
- return { success: false, output: String(error) }
82
- }
83
- }
84
-
85
- export async function composeStop(service?: string): Promise<{ success: boolean; output: string }> {
86
- try {
87
- const composePath = getComposePath()
88
- debugLog("Docker", `compose stop ${service || "all"}`)
89
- const result = service
90
- ? await $`docker compose -f ${composePath} stop ${service}`.text()
91
- : await $`docker compose -f ${composePath} stop`.text()
92
- return { success: true, output: result }
93
- } catch (error) {
94
- return { success: false, output: String(error) }
95
- }
96
- }
97
-
98
- export async function composeStart(
99
- service?: string
100
- ): Promise<{ success: boolean; output: string }> {
101
- try {
102
- const composePath = getComposePath()
103
- const result = service
104
- ? await $`docker compose -f ${composePath} start ${service}`.text()
105
- : await $`docker compose -f ${composePath} start`.text()
106
- return { success: true, output: result }
107
- } catch (error) {
108
- return { success: false, output: String(error) }
109
- }
110
- }
111
-
112
- export async function getContainerStatuses(): Promise<ContainerStatus[]> {
113
- try {
114
- const composePath = getComposePath()
115
- const result = await $`docker compose -f ${composePath} ps --format json`.text()
116
-
117
- if (!result.trim()) {
118
- return []
119
- }
120
-
121
- // Parse JSON lines output
122
- const lines = result.trim().split("\n")
123
- const statuses: ContainerStatus[] = []
124
-
125
- for (const line of lines) {
126
- try {
127
- const container = JSON.parse(line)
128
- statuses.push({
129
- name: container.Name || container.Service,
130
- status: container.State === "running" ? "running" : "stopped",
131
- ports: container.Ports,
132
- })
133
- } catch {
134
- // Skip malformed lines
135
- }
136
- }
137
-
138
- return statuses
139
- } catch {
140
- return []
141
- }
142
- }
143
-
144
- export async function pullImages(): Promise<{
145
- success: boolean
146
- output: string
147
- }> {
148
- try {
149
- const composePath = getComposePath()
150
- const result = await $`docker compose -f ${composePath} pull`.text()
151
- return { success: true, output: result }
152
- } catch (error) {
153
- return { success: false, output: String(error) }
154
- }
155
- }
156
-
157
- export async function isDockerAvailable(): Promise<boolean> {
158
- try {
159
- await $`docker --version`.quiet()
160
- return true
161
- } catch {
162
- return false
163
- }
164
- }
165
-
166
- // ==========================================
167
- // Individual Container Operations
168
- // ==========================================
169
-
170
- export interface ContainerDetails {
171
- id: string
172
- name: string
173
- service: string
174
- status: "running" | "stopped" | "exited" | "paused"
175
- state: string
176
- health?: string
177
- ports: string
178
- uptime?: string
179
- image: string
180
- createdAt: string
181
- }
182
-
183
- /**
184
- * Start a specific container by service name
185
- */
186
- export async function startContainer(
187
- service: string
188
- ): Promise<{ success: boolean; output: string }> {
189
- try {
190
- const composePath = getComposePath()
191
- const result = await $`docker compose -f ${composePath} start ${service}`.text()
192
- return { success: true, output: result }
193
- } catch (error) {
194
- return { success: false, output: String(error) }
195
- }
196
- }
197
-
198
- /**
199
- * Stop a specific container by service name
200
- */
201
- export async function stopContainer(
202
- service: string
203
- ): Promise<{ success: boolean; output: string }> {
204
- try {
205
- const composePath = getComposePath()
206
- const result = await $`docker compose -f ${composePath} stop ${service}`.text()
207
- return { success: true, output: result }
208
- } catch (error) {
209
- return { success: false, output: String(error) }
210
- }
211
- }
212
-
213
- /**
214
- * Restart a specific container by service name
215
- */
216
- export async function restartContainer(
217
- service: string
218
- ): Promise<{ success: boolean; output: string }> {
219
- try {
220
- const composePath = getComposePath()
221
- const result = await $`docker compose -f ${composePath} restart ${service}`.text()
222
- return { success: true, output: result }
223
- } catch (error) {
224
- return { success: false, output: String(error) }
225
- }
226
- }
227
-
228
- /**
229
- * Get detailed info for a specific container
230
- */
231
- export async function getContainerDetails(containerName: string): Promise<ContainerDetails | null> {
232
- try {
233
- const result =
234
- await $`docker inspect ${containerName} --format '{"id":"{{.Id}}","name":"{{.Name}}","state":"{{.State.Status}}","health":"{{if .State.Health}}{{.State.Health.Status}}{{end}}","image":"{{.Config.Image}}","createdAt":"{{.Created}}"}'`.text()
235
-
236
- if (!result.trim()) return null
237
-
238
- const data = JSON.parse(result.trim())
239
-
240
- // Get uptime from Status
241
- const statusResult =
242
- await $`docker ps --filter "name=${containerName}" --format "{{.Status}}"`.text()
243
-
244
- // Get port mappings
245
- const portsResult = await $`docker port ${containerName} 2>/dev/null`.text()
246
-
247
- return {
248
- id: data.id.substring(0, 12),
249
- name: data.name.replace(/^\//, ""),
250
- service: containerName,
251
- status: data.state === "running" ? "running" : data.state === "exited" ? "exited" : "stopped",
252
- state: data.state,
253
- health: data.health || undefined,
254
- ports: portsResult.trim() || "-",
255
- uptime: statusResult.trim() || undefined,
256
- image: data.image,
257
- createdAt: data.createdAt,
258
- }
259
- } catch {
260
- return null
261
- }
262
- }
263
-
264
- /**
265
- * Get container logs
266
- */
267
- export async function getContainerLogs(
268
- service: string,
269
- lines: number = 50
270
- ): Promise<{ success: boolean; output: string }> {
271
- try {
272
- const composePath = getComposePath()
273
- const result =
274
- await $`docker compose -f ${composePath} logs ${service} --tail ${lines} --no-color`.text()
275
- return { success: true, output: result }
276
- } catch (error) {
277
- return { success: false, output: String(error) }
278
- }
279
- }
280
-
281
- /**
282
- * Pull latest image for a specific service
283
- */
284
- export async function pullServiceImage(
285
- service: string
286
- ): Promise<{ success: boolean; output: string }> {
287
- try {
288
- const composePath = getComposePath()
289
- const result = await $`docker compose -f ${composePath} pull ${service}`.text()
290
- return { success: true, output: result }
291
- } catch (error) {
292
- return { success: false, output: String(error) }
293
- }
294
- }
295
-
296
- /**
297
- * Recreate a specific service (pull + up)
298
- */
299
- export async function recreateService(
300
- service: string
301
- ): Promise<{ success: boolean; output: string }> {
302
- try {
303
- const composePath = getComposePath()
304
- // Pull first, then recreate
305
- await $`docker compose -f ${composePath} pull ${service}`.text()
306
- const result =
307
- await $`docker compose -f ${composePath} up -d --force-recreate ${service}`.text()
308
- return { success: true, output: result }
309
- } catch (error) {
310
- return { success: false, output: String(error) }
311
- }
312
- }
@@ -1,18 +0,0 @@
1
- export {
2
- getContainerStatuses,
3
- getContainerLogs,
4
- composeUp,
5
- composeDown,
6
- composeRun,
7
- composeRestart,
8
- composeStop,
9
- composeStart,
10
- pullImages,
11
- pullServiceImage,
12
- startContainer,
13
- stopContainer,
14
- restartContainer,
15
- getContainerDetails,
16
- recreateService,
17
- type ContainerStatus,
18
- } from "./client"