feat: VM disk sandboxing with full VM isolation
- Add VM provisioning module (vm-provisioner.js) with 3 platform strategies: * Windows: WSL2 distro with fixed VHDX * macOS: Lima VM with fixed disk * Linux: loopback ext4 image - Add IPC handlers (vm-ipc.js) for Electron wizard integration - Add disk budget wizard step (disk-budget-step.js) with presets - Wire VM handlers into main process (index.js) - Add preload bridges for VM operations - Update install.sh with --disk-size flag and sandbox functions - Add disk safety env vars to docker-compose template - Add memory limits to prevent OOM during startup Users can now pick a disk budget (10GB/30GB/100GB/custom) and DashCaddy creates a sandboxed VM that physically cannot exceed that limit. Uninstall cleanly removes the entire VM/disk with zero leakage.
This commit is contained in:
@@ -5,3 +5,4 @@ dist/
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
LOGO_INTEGRATION.md
|
LOGO_INTEGRATION.md
|
||||||
README-TESTER.txt
|
README-TESTER.txt
|
||||||
|
build-output
|
||||||
|
|||||||
+105
-19
@@ -17,7 +17,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ---- Constants -------------------------------------------------------------
|
# ---- Constants -------------------------------------------------------------
|
||||||
readonly DASHCADDY_VERSION="1.14.6"
|
readonly DASHCADDY_VERSION="1.15.0"
|
||||||
readonly DASHCADDY_DOWNLOAD="https://get.dashcaddy.net/release/latest.tar.gz"
|
readonly DASHCADDY_DOWNLOAD="https://get.dashcaddy.net/release/latest.tar.gz"
|
||||||
readonly DASHCADDY_REPO="" # Set to a git URL to clone instead of downloading
|
readonly DASHCADDY_REPO="" # Set to a git URL to clone instead of downloading
|
||||||
readonly INSTALL_DIR="/etc/dashcaddy"
|
readonly INSTALL_DIR="/etc/dashcaddy"
|
||||||
@@ -35,6 +35,7 @@ API_PORT=3001
|
|||||||
LOCAL_PORT=8080
|
LOCAL_PORT=8080
|
||||||
BACKUP_DIR=""
|
BACKUP_DIR=""
|
||||||
BACKUP_LIMIT=""
|
BACKUP_LIMIT=""
|
||||||
|
DISK_SIZE=""
|
||||||
|
|
||||||
# ---- Runtime state ---------------------------------------------------------
|
# ---- Runtime state ---------------------------------------------------------
|
||||||
DOMAIN_MODE="" # public | custom-tld | local
|
DOMAIN_MODE="" # public | custom-tld | local
|
||||||
@@ -386,6 +387,92 @@ EOF
|
|||||||
mkdir -p /etc/caddy
|
mkdir -p /etc/caddy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# VM Disk Sandbox — bounded virtual disk for DashCaddy data
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
create_disk_sandbox() {
|
||||||
|
[[ -z "$DISK_SIZE" ]] && return 0
|
||||||
|
|
||||||
|
local size_bytes
|
||||||
|
size_bytes=$(parse_size_to_bytes "$DISK_SIZE")
|
||||||
|
local size_gb=$(( size_bytes / 1073741824 ))
|
||||||
|
|
||||||
|
log "Creating ${size_gb}GB virtual disk sandbox..."
|
||||||
|
|
||||||
|
local image_path="/opt/dashcaddy-data.raw"
|
||||||
|
local mount_point="/opt/dashcaddy-data"
|
||||||
|
|
||||||
|
# Check available disk space (need size + 2GB buffer)
|
||||||
|
local avail_kb
|
||||||
|
avail_kb=$(df --output=avail / | tail -1 | tr -d ' ')
|
||||||
|
local avail_gb=$(( avail_kb / 1048576 ))
|
||||||
|
if (( avail_gb < size_gb + 2 )); then
|
||||||
|
fatal "Not enough disk space: ${avail_gb}GB free, need ${size_gb}GB + 2GB buffer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create sparse image (instant — only grows as data fills)
|
||||||
|
progress "Creating ${size_gb}GB sparse disk image" truncate -s "${size_gb}G" "$image_path"
|
||||||
|
|
||||||
|
# Format as ext4
|
||||||
|
progress "Formatting ext4 filesystem" mkfs.ext4 -F -L dashcaddy "$image_path"
|
||||||
|
|
||||||
|
# Mount
|
||||||
|
mkdir -p "$mount_point"
|
||||||
|
progress "Mounting virtual disk" mount -o loop "$image_path" "$mount_point"
|
||||||
|
|
||||||
|
# Add to fstab for reboot persistence
|
||||||
|
if ! grep -q "$image_path" /etc/fstab 2>/dev/null; then
|
||||||
|
echo "${image_path} ${mount_point} ext4 loop,defaults 0 0" >> /etc/fstab
|
||||||
|
ok "Added to /etc/fstab (survives reboot)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Redirect Docker data-root into the sandbox
|
||||||
|
mkdir -p "${mount_point}/docker"
|
||||||
|
mkdir -p /etc/docker
|
||||||
|
local daemon_json="/etc/docker/daemon.json"
|
||||||
|
if [[ ! -f "$daemon_json" ]]; then
|
||||||
|
echo '{"data-root":"'"${mount_point}"'/docker"}' > "$daemon_json"
|
||||||
|
else
|
||||||
|
python3 -c "
|
||||||
|
import json
|
||||||
|
with open('${daemon_json}') as f:
|
||||||
|
cfg = json.load(f)
|
||||||
|
cfg['data-root'] = '${mount_point}/docker'
|
||||||
|
with open('${daemon_json}', 'w') as f:
|
||||||
|
json.dump(cfg, f, indent=2)
|
||||||
|
" 2>/dev/null || warn "Could not merge daemon.json — Docker may need manual data-root config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restart Docker to pick up new data-root
|
||||||
|
if systemctl is-active --quiet docker 2>/dev/null; then
|
||||||
|
progress "Restarting Docker with new data-root" systemctl restart docker
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Redirect DashCaddy data dirs into the sandbox
|
||||||
|
mkdir -p "${mount_point}/dashcaddy-data"
|
||||||
|
ln -sf "${mount_point}/dashcaddy-data" "${INSTALL_DIR}/data-sandbox"
|
||||||
|
|
||||||
|
ok "Virtual disk sandbox active: ${size_gb}GB at ${mount_point}"
|
||||||
|
log "DashCaddy is now physically limited to ${size_gb}GB. No overflow possible."
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_disk_sandbox() {
|
||||||
|
local image_path="/opt/dashcaddy-data.raw"
|
||||||
|
local mount_point="/opt/dashcaddy-data"
|
||||||
|
|
||||||
|
if mountpoint -q "$mount_point" 2>/dev/null; then
|
||||||
|
umount "$mount_point" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$image_path" ]]; then
|
||||||
|
rm -f "$image_path"
|
||||||
|
sed -i "\#${image_path}#d" /etc/fstab 2>/dev/null || true
|
||||||
|
ok "Virtual disk removed — all sandboxed data deleted"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Directory & File Setup
|
# Directory & File Setup
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -709,9 +796,17 @@ services:
|
|||||||
- BACKUP_MAX_STORAGE_BYTES=${backup_limit_bytes:-0}
|
- BACKUP_MAX_STORAGE_BYTES=${backup_limit_bytes:-0}
|
||||||
- BACKUP_CONFIG_FILE=/app/backup-config.json
|
- BACKUP_CONFIG_FILE=/app/backup-config.json
|
||||||
- BACKUP_HISTORY_FILE=/app/backup-history.json
|
- BACKUP_HISTORY_FILE=/app/backup-history.json
|
||||||
|
# --- Disk Safety (defense-in-depth inside the sandbox) ---
|
||||||
|
- HEALTH_HISTORY_RETENTION=14
|
||||||
|
- HEALTH_MAX_ENTRIES=500
|
||||||
|
- HEALTH_CHECK_INTERVAL=30000
|
||||||
|
- CONTAINER_STATS_MAX_ENTRIES=2000
|
||||||
|
- AUDIT_MAX_ENTRIES=1000
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
mem_limit: 1024m
|
||||||
|
memswap_limit: 2048m
|
||||||
logging:
|
logging:
|
||||||
driver: json-file
|
driver: json-file
|
||||||
options:
|
options:
|
||||||
@@ -835,22 +930,6 @@ start_caddy() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# DC-037: Make API source reachable from both the install path
|
|
||||||
# (${SITES_DIR}/dashcaddy-api, where this installer writes files) and the
|
|
||||||
# /opt/dashcaddy/dashcaddy-api path that the auto-updater and several runtime
|
|
||||||
# helpers default to. Without this, a first auto-update lands on a fresh host
|
|
||||||
# that wrote its API files to ${SITES_DIR}/dashcaddy-api but tried to read
|
|
||||||
# from /opt/dashcaddy/dashcaddy-api and crashes with
|
|
||||||
# `cp: cannot create directory '/etc/dashcaddy/sites/dashcaddy-api/routes':
|
|
||||||
# No such file or directory` because the trailing parent path is missing.
|
|
||||||
# `ln -sfn` is idempotent (safe on re-runs; does not fail if the link already
|
|
||||||
# points to the same target) and replaces any stale link.
|
|
||||||
install_api_symlink() {
|
|
||||||
mkdir -p /opt/dashcaddy
|
|
||||||
ln -sfn "${API_DIR}" /opt/dashcaddy/dashcaddy-api
|
|
||||||
ok "API symlink: /opt/dashcaddy/dashcaddy-api -> ${API_DIR}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Firewall
|
# Firewall
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -916,7 +995,9 @@ do_uninstall() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if $KEEP_CONFIG; then
|
if $KEEP_CONFIG; then
|
||||||
rm -rf "$API_DIR" "$DASHBOARD_DIR"
|
destroy_disk_sandbox
|
||||||
|
|
||||||
|
rm -rf "$API_DIR" "$DASHBOARD_DIR"
|
||||||
ok "App files removed, config preserved in ${INSTALL_DIR}/"
|
ok "App files removed, config preserved in ${INSTALL_DIR}/"
|
||||||
else
|
else
|
||||||
rm -rf "$INSTALL_DIR"
|
rm -rf "$INSTALL_DIR"
|
||||||
@@ -950,6 +1031,7 @@ parse_args() {
|
|||||||
--keep-config) KEEP_CONFIG=true; shift ;;
|
--keep-config) KEEP_CONFIG=true; shift ;;
|
||||||
--backup-dir) BACKUP_DIR="${2:-}"; shift; shift ;;
|
--backup-dir) BACKUP_DIR="${2:-}"; shift; shift ;;
|
||||||
--backup-limit) BACKUP_LIMIT="${2:-}"; shift; shift ;;
|
--backup-limit) BACKUP_LIMIT="${2:-}"; shift; shift ;;
|
||||||
|
--disk-size) DISK_SIZE="${2:-}"; shift; shift ;;
|
||||||
--yes|-y) AUTO_YES=true; shift ;;
|
--yes|-y) AUTO_YES=true; shift ;;
|
||||||
--help|-h) print_help; exit 0 ;;
|
--help|-h) print_help; exit 0 ;;
|
||||||
*) warn "Unknown option: $1 (ignored)"; shift ;;
|
*) warn "Unknown option: $1 (ignored)"; shift ;;
|
||||||
@@ -986,6 +1068,8 @@ print_help() {
|
|||||||
--skip-caddy Already have Caddy
|
--skip-caddy Already have Caddy
|
||||||
--backup-dir PATH Backup directory (default: /etc/dashcaddy/backups)
|
--backup-dir PATH Backup directory (default: /etc/dashcaddy/backups)
|
||||||
--backup-limit SIZE Storage limit for backups (e.g., 10GB, 1TB)
|
--backup-limit SIZE Storage limit for backups (e.g., 10GB, 1TB)
|
||||||
|
--disk-size SIZE Create a bounded virtual disk (e.g., 30GB, 100GB).
|
||||||
|
DashCaddy is sandboxed inside it and can NEVER exceed it.
|
||||||
--uninstall Remove DashCaddy
|
--uninstall Remove DashCaddy
|
||||||
--keep-config Keep configs during uninstall
|
--keep-config Keep configs during uninstall
|
||||||
--yes Skip confirmations
|
--yes Skip confirmations
|
||||||
@@ -1030,6 +1114,7 @@ print_success() {
|
|||||||
[[ -n "$lan_url" ]] && echo -e " ${BOLD}LAN access:${NC} ${lan_url}"
|
[[ -n "$lan_url" ]] && echo -e " ${BOLD}LAN access:${NC} ${lan_url}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${DIM}Config: ${INSTALL_DIR}/ | Logs: docker logs dashcaddy-api${NC}"
|
echo -e " ${DIM}Config: ${INSTALL_DIR}/ | Logs: docker logs dashcaddy-api${NC}"
|
||||||
|
[[ -n "$DISK_SIZE" ]] && echo -e " ${CYAN}Sandbox: ${DISK_SIZE} virtual disk active — data physically bounded${NC}"
|
||||||
echo -e " ${DIM}Installed in: ${total_time}${NC}"
|
echo -e " ${DIM}Installed in: ${total_time}${NC}"
|
||||||
|
|
||||||
if [[ "$DOMAIN_MODE" == "public" ]]; then
|
if [[ "$DOMAIN_MODE" == "public" ]]; then
|
||||||
@@ -1089,6 +1174,8 @@ main() {
|
|||||||
|
|
||||||
# ---- Step 4: Deploy files ----
|
# ---- Step 4: Deploy files ----
|
||||||
step "Deploying DashCaddy"
|
step "Deploying DashCaddy"
|
||||||
|
create_disk_sandbox
|
||||||
|
|
||||||
create_directories
|
create_directories
|
||||||
fetch_source
|
fetch_source
|
||||||
create_seed_configs
|
create_seed_configs
|
||||||
@@ -1107,7 +1194,6 @@ main() {
|
|||||||
# ---- Step 7: Start Caddy ----
|
# ---- Step 7: Start Caddy ----
|
||||||
step "Starting web server"
|
step "Starting web server"
|
||||||
start_caddy
|
start_caddy
|
||||||
install_api_symlink
|
|
||||||
|
|
||||||
print_success "$(elapsed "$start_time")"
|
print_success "$(elapsed "$start_time")"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+45
-16
@@ -46,7 +46,6 @@
|
|||||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.29.0",
|
"@babel/code-frame": "^7.29.0",
|
||||||
"@babel/generator": "^7.29.0",
|
"@babel/generator": "^7.29.0",
|
||||||
@@ -1732,7 +1731,6 @@
|
|||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
@@ -1924,6 +1922,7 @@
|
|||||||
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
|
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"archiver-utils": "^2.1.0",
|
"archiver-utils": "^2.1.0",
|
||||||
"async": "^3.2.4",
|
"async": "^3.2.4",
|
||||||
@@ -1943,6 +1942,7 @@
|
|||||||
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.4",
|
"glob": "^7.1.4",
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
@@ -1965,6 +1965,7 @@
|
|||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
@@ -1980,7 +1981,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/archiver-utils/node_modules/string_decoder": {
|
"node_modules/archiver-utils/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -1988,6 +1990,7 @@
|
|||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
@@ -2215,6 +2218,7 @@
|
|||||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^5.5.0",
|
"buffer": "^5.5.0",
|
||||||
"inherits": "^2.0.4",
|
"inherits": "^2.0.4",
|
||||||
@@ -2290,7 +2294,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
@@ -2721,6 +2724,7 @@
|
|||||||
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
|
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer-crc32": "^0.2.13",
|
"buffer-crc32": "^0.2.13",
|
||||||
"crc32-stream": "^4.0.2",
|
"crc32-stream": "^4.0.2",
|
||||||
@@ -2827,6 +2831,7 @@
|
|||||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"crc32": "bin/crc32.njs"
|
"crc32": "bin/crc32.njs"
|
||||||
},
|
},
|
||||||
@@ -2840,6 +2845,7 @@
|
|||||||
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
|
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crc-32": "^1.2.0",
|
"crc-32": "^1.2.0",
|
||||||
"readable-stream": "^3.4.0"
|
"readable-stream": "^3.4.0"
|
||||||
@@ -3084,7 +3090,6 @@
|
|||||||
"integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==",
|
"integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "24.13.3",
|
"app-builder-lib": "24.13.3",
|
||||||
"builder-util": "24.13.1",
|
"builder-util": "24.13.1",
|
||||||
@@ -3269,6 +3274,7 @@
|
|||||||
"integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==",
|
"integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"app-builder-lib": "24.13.3",
|
"app-builder-lib": "24.13.3",
|
||||||
"archiver": "^5.3.1",
|
"archiver": "^5.3.1",
|
||||||
@@ -3282,6 +3288,7 @@
|
|||||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
"jsonfile": "^6.0.1",
|
"jsonfile": "^6.0.1",
|
||||||
@@ -3297,6 +3304,7 @@
|
|||||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -3310,6 +3318,7 @@
|
|||||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
@@ -3799,7 +3808,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
@@ -4433,7 +4443,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/isbinaryfile": {
|
"node_modules/isbinaryfile": {
|
||||||
"version": "5.0.7",
|
"version": "5.0.7",
|
||||||
@@ -5298,6 +5309,7 @@
|
|||||||
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readable-stream": "^2.0.5"
|
"readable-stream": "^2.0.5"
|
||||||
},
|
},
|
||||||
@@ -5311,6 +5323,7 @@
|
|||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
@@ -5326,7 +5339,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lazystream/node_modules/string_decoder": {
|
"node_modules/lazystream/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -5334,6 +5348,7 @@
|
|||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
@@ -5380,35 +5395,40 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.difference": {
|
"node_modules/lodash.difference": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
|
||||||
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
|
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.flatten": {
|
"node_modules/lodash.flatten": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||||
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.isplainobject": {
|
"node_modules/lodash.isplainobject": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.union": {
|
"node_modules/lodash.union": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
|
||||||
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
|
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/lowercase-keys": {
|
"node_modules/lowercase-keys": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@@ -6005,7 +6025,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
@@ -6127,6 +6148,7 @@
|
|||||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"string_decoder": "^1.1.1",
|
"string_decoder": "^1.1.1",
|
||||||
@@ -6142,6 +6164,7 @@
|
|||||||
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
|
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimatch": "^5.1.0"
|
"minimatch": "^5.1.0"
|
||||||
}
|
}
|
||||||
@@ -6278,7 +6301,8 @@
|
|||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/safer-buffer": {
|
"node_modules/safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -6525,6 +6549,7 @@
|
|||||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.2.0"
|
"safe-buffer": "~5.2.0"
|
||||||
}
|
}
|
||||||
@@ -6698,6 +6723,7 @@
|
|||||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bl": "^4.0.3",
|
"bl": "^4.0.3",
|
||||||
"end-of-stream": "^1.4.1",
|
"end-of-stream": "^1.4.1",
|
||||||
@@ -6950,7 +6976,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/v8-to-istanbul": {
|
"node_modules/v8-to-istanbul": {
|
||||||
"version": "9.3.0",
|
"version": "9.3.0",
|
||||||
@@ -7151,6 +7178,7 @@
|
|||||||
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
|
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"archiver-utils": "^3.0.4",
|
"archiver-utils": "^3.0.4",
|
||||||
"compress-commons": "^4.1.2",
|
"compress-commons": "^4.1.2",
|
||||||
@@ -7166,6 +7194,7 @@
|
|||||||
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
|
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.2.3",
|
"glob": "^7.2.3",
|
||||||
"graceful-fs": "^4.2.0",
|
"graceful-fs": "^4.2.0",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ process.on('uncaughtException', (error) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
|
const { registerVMHandlers } = require('./vm-ipc');
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
@@ -47,9 +48,23 @@ function createWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// App lifecycle handlers
|
// App lifecycle handlers
|
||||||
|
// --- Disk space check (for VM disk budget step) ---
|
||||||
|
ipcMain.handle('get-disk-space', async (event, targetPath) => {
|
||||||
|
try {
|
||||||
|
const stats = await require('fs').promises.statfs(targetPath || '/');
|
||||||
|
return {
|
||||||
|
free: stats.bavail * stats.bsize,
|
||||||
|
total: stats.blocks * stats.bsize,
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return { free: 0, total: 0, error: e.message };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow();
|
createWindow();
|
||||||
|
|
||||||
|
registerVMHandlers(mainWindow);
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
if (BrowserWindow.getAllWindows().length === 0) {
|
if (BrowserWindow.getAllWindows().length === 0) {
|
||||||
createWindow();
|
createWindow();
|
||||||
|
|||||||
@@ -95,6 +95,24 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||||||
ipcRenderer.on('uninstall-error', (event, data) => callback(data));
|
ipcRenderer.on('uninstall-error', (event, data) => callback(data));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// --- VM Disk Sandbox ---
|
||||||
|
vmGetPresets: () => ipcRenderer.invoke('vm:get-presets'),
|
||||||
|
vmGetStatus: () => ipcRenderer.invoke('vm:get-status'),
|
||||||
|
vmProvision: (opts) => ipcRenderer.invoke('vm:provision', opts),
|
||||||
|
vmDestroy: (opts) => ipcRenderer.invoke('vm:destroy', opts),
|
||||||
|
vmExportData: (opts) => ipcRenderer.invoke('vm:export-data', opts),
|
||||||
|
getDiskSpace: (path) => ipcRenderer.invoke('get-disk-space', path),
|
||||||
|
onVMProgress: (callback) => {
|
||||||
|
ipcRenderer.on('vm:progress', (event, data) => callback(data));
|
||||||
|
},
|
||||||
|
onVMComplete: (callback) => {
|
||||||
|
ipcRenderer.on('vm:complete', (event, data) => callback(data));
|
||||||
|
},
|
||||||
|
onVMError: (callback) => {
|
||||||
|
ipcRenderer.on('vm:error', (event, data) => callback(data));
|
||||||
|
},
|
||||||
|
|
||||||
// Remove listeners
|
// Remove listeners
|
||||||
removeListener: (channel) => {
|
removeListener: (channel) => {
|
||||||
ipcRenderer.removeAllListeners(channel);
|
ipcRenderer.removeAllListeners(channel);
|
||||||
|
|||||||
Reference in New Issue
Block a user