moondesk 0.11.0 → 0.11.2
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/npm/install-binary.js +110 -13
- package/npm/moondesk.js +8 -2
- package/package.json +1 -1
package/npm/install-binary.js
CHANGED
|
@@ -103,7 +103,67 @@ function cleanupOldBinaryVersions(options = {}) {
|
|
|
103
103
|
return { removed, skipped };
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
function reportDownloadProgress(callback, downloadedBytes, totalBytes) {
|
|
107
|
+
if (typeof callback !== "function") return;
|
|
108
|
+
try {
|
|
109
|
+
callback({ downloadedBytes, totalBytes });
|
|
110
|
+
} catch {
|
|
111
|
+
// Download reporting is best-effort and must never make a verified install fail.
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function readResponseBuffer(response, url, maxBytes, onProgress) {
|
|
116
|
+
const declaredLength = Number(response.headers.get("content-length"));
|
|
117
|
+
const totalBytes = Number.isFinite(declaredLength) && declaredLength >= 0 ? declaredLength : null;
|
|
118
|
+
if (totalBytes !== null && totalBytes > maxBytes) {
|
|
119
|
+
throw new Error(`${url} is unexpectedly large (${totalBytes} bytes)`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
reportDownloadProgress(onProgress, 0, totalBytes);
|
|
123
|
+
|
|
124
|
+
if (!response.body || typeof response.body.getReader !== "function") {
|
|
125
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
126
|
+
if (buffer.length > maxBytes) {
|
|
127
|
+
throw new Error(`${url} exceeded the ${maxBytes}-byte download limit`);
|
|
128
|
+
}
|
|
129
|
+
reportDownloadProgress(onProgress, buffer.length, totalBytes);
|
|
130
|
+
return buffer;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const reader = response.body.getReader();
|
|
134
|
+
const chunks = [];
|
|
135
|
+
let downloadedBytes = 0;
|
|
136
|
+
try {
|
|
137
|
+
while (true) {
|
|
138
|
+
const { done, value } = await reader.read();
|
|
139
|
+
if (done) break;
|
|
140
|
+
const chunk = Buffer.from(value);
|
|
141
|
+
downloadedBytes += chunk.length;
|
|
142
|
+
if (downloadedBytes > maxBytes) {
|
|
143
|
+
try {
|
|
144
|
+
await reader.cancel();
|
|
145
|
+
} catch {
|
|
146
|
+
// Preserve the size-limit error below if cancellation itself fails.
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`${url} exceeded the ${maxBytes}-byte download limit`);
|
|
149
|
+
}
|
|
150
|
+
chunks.push(chunk);
|
|
151
|
+
reportDownloadProgress(onProgress, downloadedBytes, totalBytes);
|
|
152
|
+
}
|
|
153
|
+
} finally {
|
|
154
|
+
reader.releaseLock?.();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return Buffer.concat(chunks, downloadedBytes);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function fetchRequired(
|
|
161
|
+
fetchImpl,
|
|
162
|
+
url,
|
|
163
|
+
maxBytes,
|
|
164
|
+
timeoutMs = METADATA_TIMEOUT_MS,
|
|
165
|
+
onProgress,
|
|
166
|
+
) {
|
|
107
167
|
const response = await fetchImpl(url, {
|
|
108
168
|
headers: {
|
|
109
169
|
"User-Agent": `moondesk-npm/${version}`,
|
|
@@ -115,17 +175,7 @@ async function fetchRequired(fetchImpl, url, maxBytes, timeoutMs = METADATA_TIME
|
|
|
115
175
|
throw new Error(`${url} returned HTTP ${response.status}`);
|
|
116
176
|
}
|
|
117
177
|
|
|
118
|
-
|
|
119
|
-
if (Number.isFinite(contentLength) && contentLength > maxBytes) {
|
|
120
|
-
throw new Error(`${url} is unexpectedly large (${contentLength} bytes)`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
124
|
-
if (buffer.length > maxBytes) {
|
|
125
|
-
throw new Error(`${url} exceeded the ${maxBytes}-byte download limit`);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return buffer;
|
|
178
|
+
return readResponseBuffer(response, url, maxBytes, onProgress);
|
|
129
179
|
}
|
|
130
180
|
|
|
131
181
|
function expectedSha256(checksums, name) {
|
|
@@ -343,6 +393,7 @@ async function ensureBinary(options = {}) {
|
|
|
343
393
|
`${releaseBaseUrl}/${targetInfo.assetName}`,
|
|
344
394
|
MAX_BINARY_BYTES,
|
|
345
395
|
BINARY_TIMEOUT_MS,
|
|
396
|
+
options.onDownloadProgress,
|
|
346
397
|
);
|
|
347
398
|
const actual = sha256Buffer(binary);
|
|
348
399
|
|
|
@@ -381,8 +432,54 @@ async function ensureBinary(options = {}) {
|
|
|
381
432
|
}
|
|
382
433
|
}
|
|
383
434
|
|
|
435
|
+
function formatMiB(bytes) {
|
|
436
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function createDownloadProgressReporter(logger = console) {
|
|
440
|
+
let started = false;
|
|
441
|
+
let lastPercentBucket = 0;
|
|
442
|
+
let lastUnknownBytes = 0;
|
|
443
|
+
const unknownReportStep = 5 * 1024 * 1024;
|
|
444
|
+
|
|
445
|
+
return ({ downloadedBytes, totalBytes }) => {
|
|
446
|
+
if (!started) {
|
|
447
|
+
started = true;
|
|
448
|
+
if (Number.isFinite(totalBytes) && totalBytes > 0) {
|
|
449
|
+
logger.log?.(
|
|
450
|
+
`Downloading MoonDesk ${version} native binary (${formatMiB(totalBytes)})...`,
|
|
451
|
+
);
|
|
452
|
+
} else {
|
|
453
|
+
logger.log?.(`Downloading MoonDesk ${version} native binary...`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (!Number.isFinite(downloadedBytes) || downloadedBytes <= 0) return;
|
|
458
|
+
|
|
459
|
+
if (Number.isFinite(totalBytes) && totalBytes > 0) {
|
|
460
|
+
const percent = Math.min(100, Math.floor((downloadedBytes / totalBytes) * 100));
|
|
461
|
+
const bucket = percent === 100 ? 100 : Math.floor(percent / 25) * 25;
|
|
462
|
+
if (bucket >= 25 && bucket > lastPercentBucket) {
|
|
463
|
+
lastPercentBucket = bucket;
|
|
464
|
+
logger.log?.(
|
|
465
|
+
`MoonDesk ${version} native binary download: ${bucket}% (${formatMiB(Math.min(downloadedBytes, totalBytes))} / ${formatMiB(totalBytes)})`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (downloadedBytes - lastUnknownBytes >= unknownReportStep) {
|
|
472
|
+
lastUnknownBytes = downloadedBytes;
|
|
473
|
+
logger.log?.(
|
|
474
|
+
`MoonDesk ${version} native binary download: ${formatMiB(downloadedBytes)} downloaded...`,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
384
480
|
module.exports = {
|
|
385
481
|
cleanupOldBinaryVersions,
|
|
482
|
+
createDownloadProgressReporter,
|
|
386
483
|
ensureBinary,
|
|
387
484
|
expectedSha256,
|
|
388
485
|
resolveTarget,
|
|
@@ -390,7 +487,7 @@ module.exports = {
|
|
|
390
487
|
};
|
|
391
488
|
|
|
392
489
|
if (require.main === module) {
|
|
393
|
-
ensureBinary()
|
|
490
|
+
ensureBinary({ onDownloadProgress: createDownloadProgressReporter(console) })
|
|
394
491
|
.then((binaryPath) => {
|
|
395
492
|
console.log(`MoonDesk native binary ready at ${binaryPath}`);
|
|
396
493
|
})
|
package/npm/moondesk.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const { spawn } = require("node:child_process");
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
cleanupOldBinaryVersions,
|
|
7
|
+
createDownloadProgressReporter,
|
|
8
|
+
ensureBinary,
|
|
9
|
+
} = require("./install-binary");
|
|
6
10
|
const {
|
|
7
11
|
UPDATE_EXIT_CODE,
|
|
8
12
|
acquireUpdateLock,
|
|
@@ -176,7 +180,9 @@ async function orchestrate(options = {}) {
|
|
|
176
180
|
|
|
177
181
|
let binaryPath;
|
|
178
182
|
try {
|
|
179
|
-
binaryPath = await ensureBinaryImpl(
|
|
183
|
+
binaryPath = await ensureBinaryImpl({
|
|
184
|
+
onDownloadProgress: createDownloadProgressReporter(logger),
|
|
185
|
+
});
|
|
180
186
|
} catch (error) {
|
|
181
187
|
stopUpdateMonitor();
|
|
182
188
|
cleanupEphemeralUpdateFiles(updateStatePath, updateRequestPath);
|