@fastybird/smart-panel-backend 0.1.0-alpha.7 → 0.1.0-alpha.9
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/app.module.js +2 -0
- package/dist/app.module.js.map +1 -1
- package/dist/modules/platform/platforms/abstract.platform.d.ts +40 -0
- package/dist/modules/platform/platforms/abstract.platform.js +242 -0
- package/dist/modules/platform/platforms/abstract.platform.js.map +1 -1
- package/dist/modules/platform/platforms/docker.platform.d.ts +2 -0
- package/dist/modules/platform/platforms/docker.platform.js +3 -0
- package/dist/modules/platform/platforms/docker.platform.js.map +1 -1
- package/dist/modules/platform/platforms/generic.platform.d.ts +2 -1
- package/dist/modules/platform/platforms/generic.platform.js +15 -15
- package/dist/modules/platform/platforms/generic.platform.js.map +1 -1
- package/dist/modules/platform/platforms/home-assistant.platform.d.ts +4 -0
- package/dist/modules/platform/platforms/home-assistant.platform.js +21 -0
- package/dist/modules/platform/platforms/home-assistant.platform.js.map +1 -1
- package/dist/modules/platform/platforms/raspberry.platform.js +20 -40
- package/dist/modules/platform/platforms/raspberry.platform.js.map +1 -1
- package/dist/modules/platform/services/platform.service.d.ts +2 -0
- package/dist/modules/platform/services/platform.service.js +7 -0
- package/dist/modules/platform/services/platform.service.js.map +1 -1
- package/dist/modules/storage/services/storage.service.js +3 -0
- package/dist/modules/storage/services/storage.service.js.map +1 -1
- package/dist/modules/system/models/system.model.d.ts +1 -0
- package/dist/modules/system/models/system.model.js +11 -0
- package/dist/modules/system/models/system.model.js.map +1 -1
- package/dist/modules/system/scripts/update-worker.sh +290 -0
- package/dist/modules/system/services/system.service.js +4 -1
- package/dist/modules/system/services/system.service.js.map +1 -1
- package/dist/modules/system/services/update-executor.service.d.ts +4 -0
- package/dist/modules/system/services/update-executor.service.js +104 -1
- package/dist/modules/system/services/update-executor.service.js.map +1 -1
- package/dist/plugins/devices-home-assistant/services/home-assistant.http.service.d.ts +2 -0
- package/dist/plugins/devices-home-assistant/services/home-assistant.http.service.js +16 -5
- package/dist/plugins/devices-home-assistant/services/home-assistant.http.service.js.map +1 -1
- package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.d.ts +3 -0
- package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js +46 -4
- package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js.map +1 -1
- package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js +1 -0
- package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.d.ts +1 -0
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js +23 -0
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.d.ts +3 -0
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js +34 -0
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/dto/update-config.dto.js +6 -6
- package/dist/plugins/devices-shelly-ng/dto/update-config.dto.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/models/config.model.js +6 -6
- package/dist/plugins/devices-shelly-ng/models/config.model.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.d.ts +4 -0
- package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js +31 -0
- package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/services/shellies-adapter.service.d.ts +6 -2
- package/dist/plugins/devices-shelly-v1/services/shellies-adapter.service.js +68 -20
- package/dist/plugins/devices-shelly-v1/services/shellies-adapter.service.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js +4 -0
- package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js.map +1 -1
- package/dist/plugins/influx-v2/dto/update-config.dto.d.ts +8 -0
- package/dist/plugins/influx-v2/dto/update-config.dto.js +82 -0
- package/dist/plugins/influx-v2/dto/update-config.dto.js.map +1 -0
- package/dist/plugins/influx-v2/influx-v2.constants.d.ts +4 -0
- package/dist/plugins/influx-v2/influx-v2.constants.js +8 -0
- package/dist/plugins/influx-v2/influx-v2.constants.js.map +1 -0
- package/dist/plugins/influx-v2/influx-v2.openapi.d.ts +2 -0
- package/dist/plugins/influx-v2/influx-v2.openapi.js +7 -0
- package/dist/plugins/influx-v2/influx-v2.openapi.js.map +1 -0
- package/dist/plugins/influx-v2/influx-v2.plugin.d.ts +17 -0
- package/dist/plugins/influx-v2/influx-v2.plugin.js +95 -0
- package/dist/plugins/influx-v2/influx-v2.plugin.js.map +1 -0
- package/dist/plugins/influx-v2/models/config.model.d.ts +9 -0
- package/dist/plugins/influx-v2/models/config.model.js +93 -0
- package/dist/plugins/influx-v2/models/config.model.js.map +1 -0
- package/dist/plugins/influx-v2/services/influx-v2.storage.d.ts +33 -0
- package/dist/plugins/influx-v2/services/influx-v2.storage.js +230 -0
- package/dist/plugins/influx-v2/services/influx-v2.storage.js.map +1 -0
- package/dist/plugins/memory-storage/services/in-memory-timeseries.store.js +1 -1
- package/dist/plugins/memory-storage/services/in-memory-timeseries.store.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
VERSION="${1:-${UPDATE_VERSION:-latest}}"
|
|
5
|
+
STATUS_FILE="${STATUS_FILE:-/var/lib/smart-panel/update-status.json}"
|
|
6
|
+
INSTALL_TYPE="${INSTALL_TYPE:-npm}"
|
|
7
|
+
IMAGE_BASE_DIR="${IMAGE_BASE_DIR:-/opt/smart-panel}"
|
|
8
|
+
DOWNLOAD_URL="${DOWNLOAD_URL:-}"
|
|
9
|
+
|
|
10
|
+
# Capture once — used for all status writes so timeout detection works correctly
|
|
11
|
+
STARTED_AT="$(date -Iseconds)"
|
|
12
|
+
|
|
13
|
+
update_status() {
|
|
14
|
+
local status="$1"
|
|
15
|
+
local phase="$2"
|
|
16
|
+
local error="${3:-}"
|
|
17
|
+
local completed_at=""
|
|
18
|
+
|
|
19
|
+
if [ "$status" = "complete" ] || [ "$status" = "failed" ]; then
|
|
20
|
+
completed_at=$(date -Iseconds)
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
local tmp_file="${STATUS_FILE}.tmp"
|
|
24
|
+
|
|
25
|
+
# Use printf with %s to prevent injection in JSON values.
|
|
26
|
+
# Escape double-quotes and backslashes in the error message.
|
|
27
|
+
local safe_error=""
|
|
28
|
+
if [ -n "$error" ]; then
|
|
29
|
+
safe_error=$(printf '%s' "$error" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
printf '{\n\t"status": "%s",\n\t"phase": "%s",\n\t"targetVersion": "%s",\n\t"startedAt": "%s"' \
|
|
33
|
+
"$status" "$phase" "$VERSION" "$STARTED_AT" > "$tmp_file"
|
|
34
|
+
|
|
35
|
+
if [ -n "$completed_at" ]; then
|
|
36
|
+
printf ',\n\t"completedAt": "%s"' "$completed_at" >> "$tmp_file"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
printf ',\n\t"error": "%s"' "$safe_error" >> "$tmp_file"
|
|
40
|
+
printf '\n}\n' >> "$tmp_file"
|
|
41
|
+
|
|
42
|
+
mv "$tmp_file" "$STATUS_FILE"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
cleanup() {
|
|
46
|
+
local exit_code=$?
|
|
47
|
+
|
|
48
|
+
if [ $exit_code -ne 0 ]; then
|
|
49
|
+
# Only write a generic failure if a specific error wasn't already recorded
|
|
50
|
+
if [ -f "$STATUS_FILE" ] && grep -q '"status": "failed"' "$STATUS_FILE" 2>/dev/null; then
|
|
51
|
+
return
|
|
52
|
+
fi
|
|
53
|
+
update_status "failed" "failed" "Update process exited with code $exit_code"
|
|
54
|
+
fi
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
trap cleanup EXIT
|
|
58
|
+
|
|
59
|
+
# ──────────────────────────────────────────────────────────────
|
|
60
|
+
# Image-based update (Raspbian image installs)
|
|
61
|
+
# ──────────────────────────────────────────────────────────────
|
|
62
|
+
if [ "$INSTALL_TYPE" = "image" ]; then
|
|
63
|
+
# Verify passwordless sudo is available (required for systemctl, chown, ln)
|
|
64
|
+
if ! sudo -n true 2>/dev/null; then
|
|
65
|
+
update_status "failed" "failed" "Passwordless sudo is not available for this user"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
# Strip leading 'v' prefix if present to avoid double-prefixed dirs like vv1.0.0
|
|
69
|
+
CLEAN_VERSION="${VERSION#v}"
|
|
70
|
+
NEW_VERSION_DIR="${IMAGE_BASE_DIR}/v${CLEAN_VERSION}"
|
|
71
|
+
CURRENT_LINK="${IMAGE_BASE_DIR}/current"
|
|
72
|
+
PREVIOUS_TARGET=""
|
|
73
|
+
|
|
74
|
+
# Save the current version for rollback
|
|
75
|
+
if [ -L "$CURRENT_LINK" ]; then
|
|
76
|
+
PREVIOUS_TARGET=$(readlink "$CURRENT_LINK")
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Guard: refuse to overwrite the currently running version
|
|
80
|
+
# Resolve relative to IMAGE_BASE_DIR since PREVIOUS_TARGET may be relative
|
|
81
|
+
RESOLVED_PREV=$(cd "$IMAGE_BASE_DIR" && realpath "$PREVIOUS_TARGET" 2>/dev/null || true)
|
|
82
|
+
RESOLVED_NEW=$(cd "$IMAGE_BASE_DIR" && realpath "$NEW_VERSION_DIR" 2>/dev/null || true)
|
|
83
|
+
|
|
84
|
+
if [ -n "$PREVIOUS_TARGET" ] && [ -n "$RESOLVED_PREV" ] && [ -n "$RESOLVED_NEW" ] && [ "$RESOLVED_PREV" = "$RESOLVED_NEW" ]; then
|
|
85
|
+
update_status "failed" "failed" "Target version v${CLEAN_VERSION} is already the active version"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# ── Download ──
|
|
90
|
+
update_status "downloading" "downloading"
|
|
91
|
+
|
|
92
|
+
if [ -z "$DOWNLOAD_URL" ]; then
|
|
93
|
+
update_status "failed" "failed" "No download URL provided for image update"
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
TMP_TARBALL="/tmp/smart-panel-backend-v${CLEAN_VERSION}.tar.gz"
|
|
98
|
+
|
|
99
|
+
curl -fSL -o "$TMP_TARBALL" "$DOWNLOAD_URL" 2>&1 || {
|
|
100
|
+
update_status "failed" "failed" "Download failed from ${DOWNLOAD_URL}"
|
|
101
|
+
exit 1
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# ── Extract ──
|
|
105
|
+
update_status "installing" "installing"
|
|
106
|
+
|
|
107
|
+
mkdir -p "$NEW_VERSION_DIR"
|
|
108
|
+
|
|
109
|
+
tar -xzf "$TMP_TARBALL" -C "$NEW_VERSION_DIR" 2>&1 || {
|
|
110
|
+
rm -rf "$NEW_VERSION_DIR"
|
|
111
|
+
rm -f "$TMP_TARBALL"
|
|
112
|
+
update_status "failed" "failed" "Failed to extract update archive"
|
|
113
|
+
exit 1
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
rm -f "$TMP_TARBALL"
|
|
117
|
+
|
|
118
|
+
# Create the image-install marker in the new version
|
|
119
|
+
touch "${NEW_VERSION_DIR}/.image-install" || {
|
|
120
|
+
rm -rf "$NEW_VERSION_DIR"
|
|
121
|
+
update_status "failed" "failed" "Failed to create image-install marker"
|
|
122
|
+
exit 1
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# ── Verify dependencies ──
|
|
126
|
+
cd "$NEW_VERSION_DIR"
|
|
127
|
+
|
|
128
|
+
# The release tarball includes pre-built node_modules with native modules
|
|
129
|
+
# compiled for ARM64 by the CI arm-runner. Only install as fallback if
|
|
130
|
+
# node_modules is missing (e.g. manually extracted tarball without deps).
|
|
131
|
+
if [ ! -d "node_modules" ]; then
|
|
132
|
+
npm install --omit=dev 2>&1 || {
|
|
133
|
+
rm -rf "$NEW_VERSION_DIR"
|
|
134
|
+
update_status "failed" "failed" "npm install failed"
|
|
135
|
+
exit 1
|
|
136
|
+
}
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Set ownership
|
|
140
|
+
sudo chown -R smart-panel:smart-panel "$NEW_VERSION_DIR" || {
|
|
141
|
+
rm -rf "$NEW_VERSION_DIR"
|
|
142
|
+
update_status "failed" "failed" "Failed to set ownership on ${NEW_VERSION_DIR}"
|
|
143
|
+
exit 1
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# ── Stop service ──
|
|
147
|
+
update_status "stopping" "stopping"
|
|
148
|
+
sudo systemctl stop smart-panel 2>/dev/null || true
|
|
149
|
+
|
|
150
|
+
# ── Switch symlink (atomic on same filesystem) ──
|
|
151
|
+
sudo ln -sfn "$NEW_VERSION_DIR" "$CURRENT_LINK" || {
|
|
152
|
+
# Revert on failure
|
|
153
|
+
if [ -n "$PREVIOUS_TARGET" ]; then
|
|
154
|
+
sudo ln -sfn "$PREVIOUS_TARGET" "$CURRENT_LINK"
|
|
155
|
+
fi
|
|
156
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
157
|
+
update_status "failed" "failed" "Failed to switch version symlink"
|
|
158
|
+
exit 1
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# ── Run database migrations ──
|
|
162
|
+
update_status "migrating" "migrating"
|
|
163
|
+
|
|
164
|
+
ENV_FILE="/etc/smart-panel/environment"
|
|
165
|
+
|
|
166
|
+
if [ -f "${NEW_VERSION_DIR}/dist/dataSource.js" ]; then
|
|
167
|
+
(
|
|
168
|
+
set -a
|
|
169
|
+
# shellcheck source=/dev/null
|
|
170
|
+
[ -f "$ENV_FILE" ] && . "$ENV_FILE"
|
|
171
|
+
set +a
|
|
172
|
+
cd "$NEW_VERSION_DIR"
|
|
173
|
+
node node_modules/typeorm/cli.js migration:run -d dist/dataSource.js
|
|
174
|
+
) 2>&1 || {
|
|
175
|
+
# Migration failed — revert symlink if possible
|
|
176
|
+
update_status "stopping" "stopping"
|
|
177
|
+
sudo systemctl stop smart-panel 2>/dev/null || true
|
|
178
|
+
|
|
179
|
+
if [ -n "$PREVIOUS_TARGET" ]; then
|
|
180
|
+
if sudo ln -sfn "$PREVIOUS_TARGET" "$CURRENT_LINK"; then
|
|
181
|
+
rm -rf "$NEW_VERSION_DIR"
|
|
182
|
+
update_status "failed" "failed" "Database migration failed — reverted to previous version"
|
|
183
|
+
else
|
|
184
|
+
# Symlink revert failed — keep new version so system stays bootable
|
|
185
|
+
update_status "failed" "failed" "Database migration failed — symlink revert also failed"
|
|
186
|
+
fi
|
|
187
|
+
else
|
|
188
|
+
# No previous version — keep current in place so system stays bootable
|
|
189
|
+
update_status "failed" "failed" "Database migration failed — no previous version to revert to"
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
193
|
+
exit 1
|
|
194
|
+
}
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# ── Start service ──
|
|
198
|
+
update_status "starting" "starting"
|
|
199
|
+
sudo systemctl start smart-panel 2>&1 || {
|
|
200
|
+
# Try to revert if start fails
|
|
201
|
+
if [ -n "$PREVIOUS_TARGET" ]; then
|
|
202
|
+
sudo ln -sfn "$PREVIOUS_TARGET" "$CURRENT_LINK"
|
|
203
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
204
|
+
fi
|
|
205
|
+
update_status "failed" "failed" "Failed to start service after update"
|
|
206
|
+
exit 1
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# ── Cleanup old versions (keep max 2 previous) ──
|
|
210
|
+
cd "$IMAGE_BASE_DIR"
|
|
211
|
+
|
|
212
|
+
# Use the known current version rather than re-reading the symlink,
|
|
213
|
+
# so cleanup is safe even if readlink fails unexpectedly
|
|
214
|
+
CURRENT_BASENAME="v${CLEAN_VERSION}"
|
|
215
|
+
|
|
216
|
+
if [ -n "$CURRENT_BASENAME" ]; then
|
|
217
|
+
# Only match semver-versioned directories (v<digits>.<digits>.<digits>*)
|
|
218
|
+
# to avoid accidentally deleting unrelated v-prefixed directories
|
|
219
|
+
# shellcheck disable=SC2010
|
|
220
|
+
OLD_VERSIONS=$(ls -d v[0-9]*.[0-9]*.[0-9]*/ 2>/dev/null | grep -v "^${CURRENT_BASENAME}/" | sort -V | head -n -2 || true)
|
|
221
|
+
|
|
222
|
+
for old_dir in $OLD_VERSIONS; do
|
|
223
|
+
rm -rf "${IMAGE_BASE_DIR}/${old_dir}"
|
|
224
|
+
done
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
# ── Mark complete ──
|
|
228
|
+
update_status "complete" "complete"
|
|
229
|
+
trap - EXIT
|
|
230
|
+
exit 0
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# ──────────────────────────────────────────────────────────────
|
|
234
|
+
# NPM-based update (global npm installs)
|
|
235
|
+
# ──────────────────────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
# Downloading / preparing
|
|
238
|
+
update_status "downloading" "downloading"
|
|
239
|
+
|
|
240
|
+
# Stop the service
|
|
241
|
+
update_status "stopping" "stopping"
|
|
242
|
+
sudo systemctl stop smart-panel 2>/dev/null || true
|
|
243
|
+
|
|
244
|
+
# Install the update
|
|
245
|
+
update_status "installing" "installing"
|
|
246
|
+
|
|
247
|
+
if [ "$VERSION" = "latest" ]; then
|
|
248
|
+
npm update -g @fastybird/smart-panel 2>&1 || {
|
|
249
|
+
update_status "failed" "failed" "npm update failed"
|
|
250
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
251
|
+
exit 1
|
|
252
|
+
}
|
|
253
|
+
else
|
|
254
|
+
npm install -g "@fastybird/smart-panel@$VERSION" 2>&1 || {
|
|
255
|
+
update_status "failed" "failed" "npm install failed for version $VERSION"
|
|
256
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
257
|
+
exit 1
|
|
258
|
+
}
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# Run database migrations
|
|
262
|
+
update_status "migrating" "migrating"
|
|
263
|
+
|
|
264
|
+
DATA_DIR="${FB_DATA_DIR:-/var/lib/smart-panel}"
|
|
265
|
+
DB_PATH="${FB_DB_PATH:-${DATA_DIR}/data}"
|
|
266
|
+
|
|
267
|
+
if [ -f "$(npm root -g)/@fastybird/smart-panel/dataSource.js" ]; then
|
|
268
|
+
node "$(npm root -g)/@fastybird/smart-panel/node_modules/typeorm/cli.js" \
|
|
269
|
+
migration:run \
|
|
270
|
+
-d "$(npm root -g)/@fastybird/smart-panel/dataSource.js" 2>&1 || {
|
|
271
|
+
update_status "failed" "failed" "Database migration failed"
|
|
272
|
+
sudo systemctl start smart-panel 2>/dev/null || true
|
|
273
|
+
exit 1
|
|
274
|
+
}
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Start the service
|
|
278
|
+
update_status "starting" "starting"
|
|
279
|
+
sudo systemctl start smart-panel 2>&1 || {
|
|
280
|
+
update_status "failed" "failed" "Failed to start service after update"
|
|
281
|
+
exit 1
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
# Mark as complete
|
|
285
|
+
update_status "complete" "complete"
|
|
286
|
+
|
|
287
|
+
# Remove the exit trap since we completed successfully
|
|
288
|
+
trap - EXIT
|
|
289
|
+
|
|
290
|
+
exit 0
|
|
@@ -26,7 +26,10 @@ let SystemService = class SystemService {
|
|
|
26
26
|
}
|
|
27
27
|
async getSystemInfo() {
|
|
28
28
|
const rawInfo = await this.platformService.getSystemInfo();
|
|
29
|
-
return (0, transform_utils_1.toInstance)(system_model_1.SystemInfoModel,
|
|
29
|
+
return (0, transform_utils_1.toInstance)(system_model_1.SystemInfoModel, {
|
|
30
|
+
...rawInfo,
|
|
31
|
+
platform: this.platformService.getPlatformType(),
|
|
32
|
+
});
|
|
30
33
|
}
|
|
31
34
|
async getThrottleStatus() {
|
|
32
35
|
const rawStatus = await this.platformService.getThrottleStatus();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/system.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,yDAAsD;AACtD,+CAAwD;AAExD,mDAA+D;AAC/D,2EAAmE;AACnE,+EAA2E;AAC3E,yDAAuH;AACvH,0DAAoE;AAG7D,IAAM,aAAa,GAAnB,MAAM,aAAa;IAGzB,YACkB,eAAgC,EAChC,YAA2B;QAD3B,oBAAe,GAAf,eAAe,CAAiB;QAChC,iBAAY,GAAZ,YAAY,CAAe;QAJ5B,WAAM,GAAG,IAAA,8BAAqB,EAAC,qCAAkB,EAAE,eAAe,CAAC,CAAC;IAKlF,CAAC;IAEJ,KAAK,CAAC,aAAa;QAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;QAE3D,OAAO,IAAA,4BAAU,EAAC,8BAAe,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"system.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/system.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,yDAAsD;AACtD,+CAAwD;AAExD,mDAA+D;AAC/D,2EAAmE;AACnE,+EAA2E;AAC3E,yDAAuH;AACvH,0DAAoE;AAG7D,IAAM,aAAa,GAAnB,MAAM,aAAa;IAGzB,YACkB,eAAgC,EAChC,YAA2B;QAD3B,oBAAe,GAAf,eAAe,CAAiB;QAChC,iBAAY,GAAZ,YAAY,CAAe;QAJ5B,WAAM,GAAG,IAAA,8BAAqB,EAAC,qCAAkB,EAAE,eAAe,CAAC,CAAC;IAKlF,CAAC;IAEJ,KAAK,CAAC,aAAa;QAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;QAE3D,OAAO,IAAA,4BAAU,EAAC,8BAAe,EAAE;YAClC,GAAG,OAAO;YACV,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE;SAChD,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB;QACtB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,CAAC;QAEjE,OAAO,IAAA,4BAAU,EAAC,kCAAmB,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,cAAc;QACnB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC;QAE9D,OAAO,IAAA,4BAAU,EAAC,mCAAoB,EAAE,SAAS,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,eAAe;QACpB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,CAAC;QAE/D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,4BAAU,EAAC,gCAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAGK,AAAN,KAAK,CAAC,mBAAmB;QACxB,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAE9C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,4BAAS,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAE1D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,KAAc,CAAC;YAE3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QAClG,CAAC;IACF,CAAC;CACD,CAAA;AAjDY,sCAAa;AAoCnB;IADL,IAAA,eAAI,EAAC,yBAAc,CAAC,eAAe,CAAC;;;;wDAapC;wBAhDW,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAKuB,kCAAe;QAClB,6BAAa;GALjC,aAAa,CAiDzB"}
|
|
@@ -12,9 +12,13 @@ export interface UpdateProgressFile {
|
|
|
12
12
|
export declare class UpdateExecutorService implements OnModuleInit {
|
|
13
13
|
private readonly updateService;
|
|
14
14
|
private readonly logger;
|
|
15
|
+
private statusPollTimer;
|
|
16
|
+
private progressHighWaterMark;
|
|
15
17
|
constructor(updateService: UpdateService);
|
|
16
18
|
onModuleInit(): void;
|
|
17
19
|
private checkPendingUpdateStatus;
|
|
18
20
|
startUpdate(targetVersion: string): Promise<void>;
|
|
21
|
+
private startStatusPolling;
|
|
22
|
+
private stopStatusPolling;
|
|
19
23
|
private writeStatusFile;
|
|
20
24
|
}
|
|
@@ -51,10 +51,22 @@ const system_constants_1 = require("../system.constants");
|
|
|
51
51
|
const update_service_1 = require("./update.service");
|
|
52
52
|
const STATUS_FILE = '/var/lib/smart-panel/update-status.json';
|
|
53
53
|
const UPDATE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
54
|
+
const STATUS_POLL_INTERVAL_MS = 3_000;
|
|
55
|
+
const STATUS_POLL_MAX_MS = UPDATE_TIMEOUT_MS + 30_000;
|
|
56
|
+
const PHASE_PROGRESS = {
|
|
57
|
+
downloading: 20,
|
|
58
|
+
installing: 45,
|
|
59
|
+
stopping: 45,
|
|
60
|
+
migrating: 65,
|
|
61
|
+
starting: 85,
|
|
62
|
+
complete: 100,
|
|
63
|
+
};
|
|
54
64
|
let UpdateExecutorService = class UpdateExecutorService {
|
|
55
65
|
constructor(updateService) {
|
|
56
66
|
this.updateService = updateService;
|
|
57
67
|
this.logger = (0, logger_1.createExtensionLogger)(system_constants_1.SYSTEM_MODULE_NAME, 'UpdateExecutorService');
|
|
68
|
+
this.statusPollTimer = null;
|
|
69
|
+
this.progressHighWaterMark = 0;
|
|
58
70
|
}
|
|
59
71
|
onModuleInit() {
|
|
60
72
|
this.checkPendingUpdateStatus();
|
|
@@ -158,7 +170,27 @@ let UpdateExecutorService = class UpdateExecutorService {
|
|
|
158
170
|
error: null,
|
|
159
171
|
startedAt: new Date(),
|
|
160
172
|
});
|
|
161
|
-
const updateScript = (0, path_1.join)(__dirname, '..', '
|
|
173
|
+
const updateScript = (0, path_1.join)(__dirname, '..', 'scripts', 'update-worker.sh');
|
|
174
|
+
if (!(0, fs_1.existsSync)(updateScript)) {
|
|
175
|
+
this.updateService.releaseUpdateLock();
|
|
176
|
+
const errorMsg = `Update worker script not found at ${updateScript}`;
|
|
177
|
+
this.logger.error(errorMsg);
|
|
178
|
+
this.updateService.setStatus({
|
|
179
|
+
status: system_constants_1.UpdateStatusType.FAILED,
|
|
180
|
+
phase: system_constants_1.UpdatePhase.FAILED,
|
|
181
|
+
progressPercent: null,
|
|
182
|
+
message: null,
|
|
183
|
+
error: errorMsg,
|
|
184
|
+
});
|
|
185
|
+
this.writeStatusFile({
|
|
186
|
+
status: system_constants_1.UpdateStatusType.FAILED,
|
|
187
|
+
phase: system_constants_1.UpdatePhase.FAILED,
|
|
188
|
+
targetVersion,
|
|
189
|
+
startedAt: new Date().toISOString(),
|
|
190
|
+
error: errorMsg,
|
|
191
|
+
});
|
|
192
|
+
throw new Error(errorMsg);
|
|
193
|
+
}
|
|
162
194
|
try {
|
|
163
195
|
const { spawn } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
164
196
|
const child = spawn('bash', [updateScript, targetVersion], {
|
|
@@ -175,6 +207,7 @@ let UpdateExecutorService = class UpdateExecutorService {
|
|
|
175
207
|
});
|
|
176
208
|
child.unref();
|
|
177
209
|
this.logger.log(`Update worker spawned for version ${targetVersion} (PID: ${child.pid}, type: ${installType})`);
|
|
210
|
+
this.startStatusPolling();
|
|
178
211
|
}
|
|
179
212
|
catch (error) {
|
|
180
213
|
const err = error;
|
|
@@ -196,6 +229,76 @@ let UpdateExecutorService = class UpdateExecutorService {
|
|
|
196
229
|
throw error;
|
|
197
230
|
}
|
|
198
231
|
}
|
|
232
|
+
startStatusPolling() {
|
|
233
|
+
this.stopStatusPolling();
|
|
234
|
+
this.progressHighWaterMark = 10;
|
|
235
|
+
const startedAt = Date.now();
|
|
236
|
+
this.statusPollTimer = setInterval(() => {
|
|
237
|
+
if (Date.now() - startedAt > STATUS_POLL_MAX_MS) {
|
|
238
|
+
this.logger.error('Update status polling timed out');
|
|
239
|
+
this.updateService.setStatus({
|
|
240
|
+
status: system_constants_1.UpdateStatusType.FAILED,
|
|
241
|
+
phase: system_constants_1.UpdatePhase.FAILED,
|
|
242
|
+
progressPercent: null,
|
|
243
|
+
message: null,
|
|
244
|
+
error: 'Update timed out — no completion signal received',
|
|
245
|
+
});
|
|
246
|
+
this.updateService.releaseUpdateLock();
|
|
247
|
+
this.stopStatusPolling();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!(0, fs_1.existsSync)(STATUS_FILE)) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const raw = (0, fs_1.readFileSync)(STATUS_FILE, 'utf-8');
|
|
255
|
+
const fileStatus = JSON.parse(raw);
|
|
256
|
+
if (fileStatus.status === system_constants_1.UpdateStatusType.FAILED) {
|
|
257
|
+
this.logger.error(`Update worker failed: ${fileStatus.error ?? 'unknown error'}`);
|
|
258
|
+
this.updateService.setStatus({
|
|
259
|
+
status: system_constants_1.UpdateStatusType.FAILED,
|
|
260
|
+
phase: system_constants_1.UpdatePhase.FAILED,
|
|
261
|
+
progressPercent: null,
|
|
262
|
+
message: null,
|
|
263
|
+
error: fileStatus.error ?? 'Update failed with unknown error',
|
|
264
|
+
});
|
|
265
|
+
this.updateService.releaseUpdateLock();
|
|
266
|
+
this.stopStatusPolling();
|
|
267
|
+
}
|
|
268
|
+
else if (fileStatus.status === system_constants_1.UpdateStatusType.COMPLETE) {
|
|
269
|
+
this.updateService.setStatus({
|
|
270
|
+
status: system_constants_1.UpdateStatusType.COMPLETE,
|
|
271
|
+
phase: system_constants_1.UpdatePhase.COMPLETE,
|
|
272
|
+
progressPercent: 100,
|
|
273
|
+
message: `Successfully updated to ${fileStatus.targetVersion}`,
|
|
274
|
+
error: null,
|
|
275
|
+
});
|
|
276
|
+
this.updateService.releaseUpdateLock();
|
|
277
|
+
this.stopStatusPolling();
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const rawProgress = PHASE_PROGRESS[fileStatus.phase] ?? 10;
|
|
281
|
+
const progress = Math.max(this.progressHighWaterMark, rawProgress);
|
|
282
|
+
this.progressHighWaterMark = progress;
|
|
283
|
+
this.updateService.setStatus({
|
|
284
|
+
status: fileStatus.status ?? system_constants_1.UpdateStatusType.DOWNLOADING,
|
|
285
|
+
phase: fileStatus.phase ?? system_constants_1.UpdatePhase.DOWNLOADING,
|
|
286
|
+
progressPercent: progress,
|
|
287
|
+
message: `Update in progress: ${fileStatus.phase}...`,
|
|
288
|
+
error: null,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
}
|
|
294
|
+
}, STATUS_POLL_INTERVAL_MS);
|
|
295
|
+
}
|
|
296
|
+
stopStatusPolling() {
|
|
297
|
+
if (this.statusPollTimer) {
|
|
298
|
+
clearInterval(this.statusPollTimer);
|
|
299
|
+
this.statusPollTimer = null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
199
302
|
writeStatusFile(status) {
|
|
200
303
|
try {
|
|
201
304
|
const dir = (0, path_1.dirname)(STATUS_FILE);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-executor.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/update-executor.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2BAAgG;AAChG,+BAAqC;AAErC,2CAA0D;AAE1D,mDAA+D;AAC/D,0DAAwF;AAExF,qDAAiD;AAWjD,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAC9D,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"update-executor.service.js","sourceRoot":"","sources":["../../../../src/modules/system/services/update-executor.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2BAAgG;AAChG,+BAAqC;AAErC,2CAA0D;AAE1D,mDAA+D;AAC/D,0DAAwF;AAExF,qDAAiD;AAWjD,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAC9D,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzC,MAAM,uBAAuB,GAAG,KAAK,CAAC;AACtC,MAAM,kBAAkB,GAAG,iBAAiB,GAAG,MAAM,CAAC;AAQtD,MAAM,cAAc,GAA2B;IAC9C,WAAW,EAAE,EAAE;IACf,UAAU,EAAE,EAAE;IACd,QAAQ,EAAE,EAAE;IACZ,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,GAAG;CACb,CAAC;AAGK,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAKjC,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAJxC,WAAM,GAAG,IAAA,8BAAqB,EAAC,qCAAkB,EAAE,uBAAuB,CAAC,CAAC;QACrF,oBAAe,GAA0B,IAAI,CAAC;QAC9C,0BAAqB,GAAG,CAAC,CAAC;IAE0B,CAAC;IAE7D,YAAY;QACX,IAAI,CAAC,wBAAwB,EAAE,CAAC;IACjC,CAAC;IAEO,wBAAwB;QAC/B,IAAI,CAAC,IAAA,eAAU,EAAC,WAAW,CAAC,EAAE,CAAC;YAC9B,OAAO;QACR,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;YAErD,IAAI,MAAM,CAAC,MAAM,KAAK,mCAAgB,CAAC,QAAQ,EAAE,CAAC;gBACjD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,aAAa,yBAAyB,CAAC,CAAC;gBAE5E,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;oBAC5B,MAAM,EAAE,mCAAgB,CAAC,QAAQ;oBACjC,KAAK,EAAE,8BAAW,CAAC,QAAQ;oBAC3B,eAAe,EAAE,GAAG;oBACpB,OAAO,EAAE,2BAA2B,MAAM,CAAC,aAAa,EAAE;oBAC1D,KAAK,EAAE,IAAI;iBACX,CAAC,CAAC;YACJ,CAAC;iBAAM,IAAI,MAAM,CAAC,MAAM,KAAK,mCAAgB,CAAC,MAAM,EAAE,CAAC;gBACtD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,aAAa,YAAY,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;gBAElG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;oBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;oBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;oBACzB,eAAe,EAAE,IAAI;oBACrB,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,kCAAkC;iBACzD,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBAEP,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;gBAEvD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,iBAAiB,EAAE,CAAC;oBAChD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,aAAa,YAAY,CAAC,CAAC;oBAEjE,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;wBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;wBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;wBACzB,eAAe,EAAE,IAAI;wBACrB,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE,mCAAmC;qBAC1C,CAAC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,MAAM,CAAC,IAAI,CACf,aAAa,MAAM,CAAC,aAAa,4BAA4B,MAAM,CAAC,KAAK,sBAAsB,CAC/F,CAAC;oBAEF,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;wBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;wBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;wBACzB,eAAe,EAAE,IAAI;wBACrB,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE,6BAA6B,MAAM,CAAC,KAAK,QAAQ;qBACxD,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YAGD,IAAA,eAAU,EAAC,WAAW,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,KAAc,CAAC;YAE3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAEvE,IAAI,CAAC;gBACJ,IAAA,eAAU,EAAC,WAAW,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACF,CAAC;QAGD,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,aAAqB;QACtC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QAExD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,WAAW,sBAAsB,aAAa,EAAE,CAAC,CAAC;QAG9E,IAAI,WAA+B,CAAC;QAEpC,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC;YAE9E,IAAI,CAAC,KAAK,EAAE,CAAC;gBACZ,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;gBAEvC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;oBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;oBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;oBACzB,eAAe,EAAE,IAAI;oBACrB,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,iDAAiD,aAAa,EAAE;iBACvE,CAAC,CAAC;gBAEH,MAAM,IAAI,KAAK,CAAC,iDAAiD,aAAa,EAAE,CAAC,CAAC;YACnF,CAAC;YAED,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QACjC,CAAC;QAGD,IAAI,CAAC,eAAe,CAAC;YACpB,MAAM,EAAE,mCAAgB,CAAC,WAAW;YACpC,KAAK,EAAE,8BAAW,CAAC,WAAW;YAC9B,aAAa;YACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;YAC5B,MAAM,EAAE,mCAAgB,CAAC,WAAW;YACpC,KAAK,EAAE,8BAAW,CAAC,WAAW;YAC9B,eAAe,EAAE,EAAE;YACnB,OAAO,EAAE,4BAA4B;YACrC,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI,IAAI,EAAE;SACrB,CAAC,CAAC;QAGH,MAAM,YAAY,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAE1E,IAAI,CAAC,IAAA,eAAU,EAAC,YAAY,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;YAEvC,MAAM,QAAQ,GAAG,qCAAqC,YAAY,EAAE,CAAC;YAErE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE5B,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;gBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;gBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;gBACzB,eAAe,EAAE,IAAI;gBACrB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,QAAQ;aACf,CAAC,CAAC;YAEH,IAAI,CAAC,eAAe,CAAC;gBACpB,MAAM,EAAE,mCAAgB,CAAC,MAAM;gBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;gBACzB,aAAa;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,QAAQ;aACf,CAAC,CAAC;YAEH,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,EAAE,KAAK,EAAE,GAAG,wDAAa,eAAe,GAAC,CAAC;YAEhD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE;gBAC1D,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ;gBACf,GAAG,EAAE;oBACJ,GAAG,OAAO,CAAC,GAAG;oBACd,cAAc,EAAE,aAAa;oBAC7B,WAAW;oBACX,YAAY,EAAE,WAAW;oBACzB,cAAc,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE;oBACnF,YAAY,EAAE,WAAW,IAAI,EAAE;iBAC/B;aACD,CAAC,CAAC;YAEH,KAAK,CAAC,KAAK,EAAE,CAAC;YAEd,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qCAAqC,aAAa,UAAU,KAAK,CAAC,GAAG,WAAW,WAAW,GAAG,CAAC,CAAC;YAKhH,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,KAAc,CAAC;YAE3B,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;YAEvC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;gBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;gBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;gBACzB,eAAe,EAAE,IAAI;gBACrB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,kCAAkC,GAAG,CAAC,OAAO,EAAE;aACtD,CAAC,CAAC;YAEH,IAAI,CAAC,eAAe,CAAC;gBACpB,MAAM,EAAE,mCAAgB,CAAC,MAAM;gBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;gBACzB,aAAa;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,kCAAkC,GAAG,CAAC,OAAO,EAAE;aACtD,CAAC,CAAC;YAEH,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEO,kBAAkB;QACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC;QAEhC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YAEvC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,kBAAkB,EAAE,CAAC;gBACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBAErD,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;oBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;oBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;oBACzB,eAAe,EAAE,IAAI;oBACrB,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,kDAAkD;iBACzD,CAAC,CAAC;gBAEH,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;gBACvC,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAEzB,OAAO;YACR,CAAC;YAED,IAAI,CAAC,IAAA,eAAU,EAAC,WAAW,CAAC,EAAE,CAAC;gBAC9B,OAAO;YACR,CAAC;YAED,IAAI,CAAC;gBACJ,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;gBAEzD,IAAI,UAAU,CAAC,MAAM,KAAK,mCAAgB,CAAC,MAAM,EAAE,CAAC;oBACnD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,UAAU,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAC;oBAElF,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;wBAC5B,MAAM,EAAE,mCAAgB,CAAC,MAAM;wBAC/B,KAAK,EAAE,8BAAW,CAAC,MAAM;wBACzB,eAAe,EAAE,IAAI;wBACrB,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,kCAAkC;qBAC7D,CAAC,CAAC;oBAEH,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;oBACvC,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC1B,CAAC;qBAAM,IAAI,UAAU,CAAC,MAAM,KAAK,mCAAgB,CAAC,QAAQ,EAAE,CAAC;oBAC5D,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;wBAC5B,MAAM,EAAE,mCAAgB,CAAC,QAAQ;wBACjC,KAAK,EAAE,8BAAW,CAAC,QAAQ;wBAC3B,eAAe,EAAE,GAAG;wBACpB,OAAO,EAAE,2BAA2B,UAAU,CAAC,aAAa,EAAE;wBAC9D,KAAK,EAAE,IAAI;qBACX,CAAC,CAAC;oBAEH,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,CAAC;oBACvC,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBAIP,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;oBAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,WAAW,CAAC,CAAC;oBAEnE,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC;oBAEtC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;wBAC5B,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,mCAAgB,CAAC,WAAW;wBACzD,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,8BAAW,CAAC,WAAW;wBAClD,eAAe,EAAE,QAAQ;wBACzB,OAAO,EAAE,uBAAuB,UAAU,CAAC,KAAK,KAAK;wBACrD,KAAK,EAAE,IAAI;qBACX,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACF,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAC7B,CAAC;IAEO,iBAAiB;QACxB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC7B,CAAC;IACF,CAAC;IAEO,eAAe,CAAC,MAA0B;QACjD,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,WAAW,CAAC,CAAC;YAEjC,IAAI,CAAC,IAAA,eAAU,EAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,CAAC;YAGD,MAAM,OAAO,GAAG,GAAG,WAAW,MAAM,CAAC;YAErC,IAAA,kBAAa,EAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAE5E,IAAA,eAAU,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,KAAc,CAAC;YAE3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACF,CAAC;CACD,CAAA;AAjUY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAMgC,8BAAa;GAL7C,qBAAqB,CAiUjC"}
|
|
@@ -34,6 +34,8 @@ export declare class HomeAssistantHttpService {
|
|
|
34
34
|
private get apiKey();
|
|
35
35
|
private get hostname();
|
|
36
36
|
private get baseUrl();
|
|
37
|
+
private readonly HTTP_TIMEOUT_MS;
|
|
38
|
+
private fetchWithTimeout;
|
|
37
39
|
private ensureApiKey;
|
|
38
40
|
private toDiscoveredDeviceModel;
|
|
39
41
|
private toStateModel;
|
|
@@ -48,6 +48,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
48
48
|
this.supervisorService = supervisorService;
|
|
49
49
|
this.logger = (0, extension_logger_service_1.createExtensionLogger)(devices_home_assistant_constants_1.DEVICES_HOME_ASSISTANT_PLUGIN_NAME, 'HomeAssistantHttpService');
|
|
50
50
|
this.pluginConfig = null;
|
|
51
|
+
this.HTTP_TIMEOUT_MS = 15_000;
|
|
51
52
|
}
|
|
52
53
|
async getDiscoveredDevice(id) {
|
|
53
54
|
this.ensureApiKey();
|
|
@@ -492,6 +493,16 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
492
493
|
}
|
|
493
494
|
return `http://${this.hostname}`;
|
|
494
495
|
}
|
|
496
|
+
async fetchWithTimeout(url, init) {
|
|
497
|
+
const controller = new AbortController();
|
|
498
|
+
const timeoutId = setTimeout(() => controller.abort(), this.HTTP_TIMEOUT_MS);
|
|
499
|
+
try {
|
|
500
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
501
|
+
}
|
|
502
|
+
finally {
|
|
503
|
+
clearTimeout(timeoutId);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
495
506
|
ensureApiKey() {
|
|
496
507
|
if (this.apiKey === null) {
|
|
497
508
|
this.logger.warn('Missing API key for Home Assistant HTTP service');
|
|
@@ -524,7 +535,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
524
535
|
async fetchSingleHaDevice(id) {
|
|
525
536
|
try {
|
|
526
537
|
const url = new URL(`${this.baseUrl}/api/template`);
|
|
527
|
-
const response = await
|
|
538
|
+
const response = await this.fetchWithTimeout(url, {
|
|
528
539
|
method: 'POST',
|
|
529
540
|
headers: {
|
|
530
541
|
Authorization: `Bearer ${this.apiKey}`,
|
|
@@ -567,7 +578,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
567
578
|
async fetchListHaDevices() {
|
|
568
579
|
try {
|
|
569
580
|
const url = new URL(`${this.baseUrl}/api/template`);
|
|
570
|
-
const response = await
|
|
581
|
+
const response = await this.fetchWithTimeout(url, {
|
|
571
582
|
method: 'POST',
|
|
572
583
|
headers: {
|
|
573
584
|
Authorization: `Bearer ${this.apiKey}`,
|
|
@@ -604,7 +615,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
604
615
|
async fetchSingleHaState(entityId) {
|
|
605
616
|
try {
|
|
606
617
|
const url = new URL(`${this.baseUrl}/api/states/${entityId}`);
|
|
607
|
-
const response = await
|
|
618
|
+
const response = await this.fetchWithTimeout(url, {
|
|
608
619
|
method: 'GET',
|
|
609
620
|
headers: {
|
|
610
621
|
Authorization: `Bearer ${this.apiKey}`,
|
|
@@ -638,7 +649,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
638
649
|
async fetchListHaStates() {
|
|
639
650
|
try {
|
|
640
651
|
const url = new URL(`${this.baseUrl}/api/states`);
|
|
641
|
-
const response = await
|
|
652
|
+
const response = await this.fetchWithTimeout(url, {
|
|
642
653
|
method: 'GET',
|
|
643
654
|
headers: {
|
|
644
655
|
Authorization: `Bearer ${this.apiKey}`,
|
|
@@ -672,7 +683,7 @@ let HomeAssistantHttpService = class HomeAssistantHttpService {
|
|
|
672
683
|
async fetchListHaHelpers() {
|
|
673
684
|
try {
|
|
674
685
|
const url = new URL(`${this.baseUrl}/api/template`);
|
|
675
|
-
const response = await
|
|
686
|
+
const response = await this.fetchWithTimeout(url, {
|
|
676
687
|
method: 'POST',
|
|
677
688
|
headers: {
|
|
678
689
|
Authorization: `Bearer ${this.apiKey}`,
|