sitevision-cli 1.0.0-beta.8 → 1.0.0-beta.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/utils/sitevision-api.js +30 -9
- package/package.json +1 -1
|
@@ -160,16 +160,36 @@ async function delay(ms) {
|
|
|
160
160
|
*/
|
|
161
161
|
export function summarizeErrorBody(body, headers) {
|
|
162
162
|
const contentType = headers['content-type'] ?? 'unknown';
|
|
163
|
-
const
|
|
163
|
+
const declaredText = contentType.includes('text') ||
|
|
164
164
|
contentType.includes('json') ||
|
|
165
165
|
contentType.includes('xml');
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
const text = body.toString('utf8');
|
|
167
|
+
// Show the body when the server declares it text OR the bytes decode to
|
|
168
|
+
// mostly-printable text. Sitevision sometimes returns a text/JSON error with
|
|
169
|
+
// a missing or non-text content-type, and hiding it obscures the real cause.
|
|
170
|
+
if (declaredText || isMostlyPrintable(text)) {
|
|
171
|
+
const collapsed = text.replaceAll(/\s+/g, ' ').trim();
|
|
172
|
+
const max = 300;
|
|
173
|
+
const summary = collapsed.length > max ? collapsed.slice(0, max) + '…' : collapsed;
|
|
174
|
+
if (summary.length > 0)
|
|
175
|
+
return summary;
|
|
168
176
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
177
|
+
return `(${contentType}, ${body.length} bytes)`;
|
|
178
|
+
}
|
|
179
|
+
/** Heuristic: a decoded string is text if <10% of chars are control/undecodable. */
|
|
180
|
+
function isMostlyPrintable(text) {
|
|
181
|
+
if (text.length === 0)
|
|
182
|
+
return false;
|
|
183
|
+
let bad = 0;
|
|
184
|
+
for (const ch of text) {
|
|
185
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
186
|
+
// Undecodable byte (replacement char), or a control char other than
|
|
187
|
+
// tab/newline/vertical-tab/form-feed/carriage-return.
|
|
188
|
+
if (code === 0xff_fd || code < 9 || (code > 13 && code < 32)) {
|
|
189
|
+
bad++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return bad / text.length < 0.1;
|
|
173
193
|
}
|
|
174
194
|
/** ZIP local-file-header magic bytes: "PK\x03\x04". */
|
|
175
195
|
const ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
|
|
@@ -316,9 +336,10 @@ export async function deployApp(zipPath, config, appType, force = false) {
|
|
|
316
336
|
if (force) {
|
|
317
337
|
url += '?force=true';
|
|
318
338
|
}
|
|
319
|
-
//
|
|
339
|
+
// The import endpoints expect the archive in a multipart part named "data"
|
|
340
|
+
// (per the webAppImport/restAppImport docs). Signing uses "file" separately.
|
|
320
341
|
const boundary = generateBoundary();
|
|
321
|
-
const { body, contentType } = createMultipartFormData(zipPath, '
|
|
342
|
+
const { body, contentType } = createMultipartFormData(zipPath, 'data', boundary);
|
|
322
343
|
const { auth, kind } = configAuth(config);
|
|
323
344
|
try {
|
|
324
345
|
const response = await makeRequest(url, {
|