@trops/dash-core 0.1.231 → 0.1.233

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.
@@ -32248,7 +32248,7 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
32248
32248
 
32249
32249
  const contentType = response.headers.get("content-type") || "";
32250
32250
  const arrayBuffer = await response.arrayBuffer();
32251
- const zipBuffer = Buffer.from(arrayBuffer);
32251
+ let zipBuffer = Buffer.from(arrayBuffer);
32252
32252
  console.log(`${TAG} [3/5 Download] size=${zipBuffer.length} bytes`);
32253
32253
 
32254
32254
  if (zipBuffer.length === 0) {
@@ -32258,74 +32258,135 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
32258
32258
  };
32259
32259
  }
32260
32260
 
32261
- // Check if the response is actually a ZIP (not an HTML error page or JSON error)
32262
- if (
32263
- contentType.includes("text/html") ||
32264
- contentType.includes("application/json")
32265
- ) {
32261
+ // Reject HTML error pages
32262
+ if (contentType.includes("text/html")) {
32266
32263
  const body = zipBuffer.toString("utf-8").slice(0, 200);
32267
- console.log(
32268
- `${TAG} [3/5 Download] FAIL — unexpected content type "${contentType}": ${body}`,
32269
- );
32264
+ console.log(`${TAG} [3/5 Download] FAIL — HTML response: ${body}`);
32270
32265
  return {
32271
32266
  success: false,
32272
- error: `Download failed: registry returned ${contentType} instead of a ZIP file. The download URL may be incorrect.`,
32267
+ error: `Download failed: registry returned an HTML page instead of theme data.`,
32273
32268
  };
32274
32269
  }
32275
32270
 
32276
- // Stage 4: ZIP extraction
32277
- let zip;
32278
- try {
32279
- zip = new AdmZip$1(zipBuffer);
32280
- } catch (zipErr) {
32271
+ // Stage 4: Extract theme data (JSON or ZIP)
32272
+ let themeData;
32273
+
32274
+ if (contentType.includes("application/json")) {
32275
+ // Registry returns JSON with a downloadUrl pointing to the actual ZIP
32281
32276
  console.log(
32282
- `${TAG} [4/5 ZIP Extraction] FAILinvalid ZIP: ${zipErr.message}`,
32277
+ `${TAG} [3/5 Download] JSON response checking for downloadUrl`,
32283
32278
  );
32284
- return {
32285
- success: false,
32286
- error: `ZIP extraction failed: the downloaded file is not a valid ZIP archive (${zipErr.message}).`,
32287
- };
32279
+ let jsonData;
32280
+ try {
32281
+ jsonData = JSON.parse(zipBuffer.toString("utf-8"));
32282
+ } catch (parseErr) {
32283
+ return {
32284
+ success: false,
32285
+ error: `Download failed: registry returned invalid JSON (${parseErr.message}).`,
32286
+ };
32287
+ }
32288
+ if (jsonData.error) {
32289
+ console.log(
32290
+ `${TAG} [3/5 Download] FAIL — JSON error: ${jsonData.error}`,
32291
+ );
32292
+ return {
32293
+ success: false,
32294
+ error: `Download failed: ${jsonData.error}`,
32295
+ };
32296
+ }
32297
+ if (jsonData.downloadUrl) {
32298
+ // Follow the pre-signed URL to get the actual ZIP
32299
+ console.log(`${TAG} [3/5 Download] following downloadUrl to fetch ZIP`);
32300
+ let zipResponse;
32301
+ try {
32302
+ zipResponse = await fetch(jsonData.downloadUrl);
32303
+ } catch (fetchErr) {
32304
+ return {
32305
+ success: false,
32306
+ error: `Download failed: could not fetch ZIP from storage (${fetchErr.message}).`,
32307
+ };
32308
+ }
32309
+ if (!zipResponse.ok) {
32310
+ return {
32311
+ success: false,
32312
+ error: `Download failed: storage returned ${zipResponse.status} ${zipResponse.statusText}`,
32313
+ };
32314
+ }
32315
+ const zipArrayBuffer = await zipResponse.arrayBuffer();
32316
+ zipBuffer = Buffer.from(zipArrayBuffer);
32317
+ console.log(
32318
+ `${TAG} [3/5 Download] ZIP fetched, size=${zipBuffer.length} bytes`,
32319
+ );
32320
+ if (zipBuffer.length === 0) {
32321
+ return {
32322
+ success: false,
32323
+ error: "Download failed: storage returned an empty ZIP file.",
32324
+ };
32325
+ }
32326
+ } else {
32327
+ // No downloadUrl — treat as direct theme data
32328
+ console.log(
32329
+ `${TAG} [4/5 Extract] JSON response with no downloadUrl — using as theme data`,
32330
+ );
32331
+ themeData = jsonData.data || jsonData.theme || jsonData;
32332
+ }
32288
32333
  }
32289
- const entries = zip.getEntries();
32290
- const entryNames = entries.map((e) => e.entryName);
32291
- const themeEntry = entries.find((entry) =>
32292
- entry.entryName.endsWith(".theme.json"),
32293
- );
32294
- console.log(
32295
- `${TAG} [4/5 ZIP Extraction] files=[${entryNames.join(", ")}] hasThemeJson=${!!themeEntry}`,
32296
- );
32297
32334
 
32298
- if (!themeEntry) {
32335
+ if (!themeData) {
32336
+ // ZIP response — extract .theme.json from archive
32337
+ let zip;
32338
+ try {
32339
+ zip = new AdmZip$1(zipBuffer);
32340
+ } catch (zipErr) {
32341
+ console.log(
32342
+ `${TAG} [4/5 ZIP Extraction] FAIL — invalid ZIP: ${zipErr.message}`,
32343
+ );
32344
+ return {
32345
+ success: false,
32346
+ error: `ZIP extraction failed: the downloaded file is not a valid ZIP archive (${zipErr.message}).`,
32347
+ };
32348
+ }
32349
+ const entries = zip.getEntries();
32350
+ const entryNames = entries.map((e) => e.entryName);
32351
+ const themeEntry = entries.find((entry) =>
32352
+ entry.entryName.endsWith(".theme.json"),
32353
+ );
32299
32354
  console.log(
32300
- `${TAG} [4/5 ZIP Extraction] FAIL — no .theme.json in archive`,
32355
+ `${TAG} [4/5 ZIP Extraction] files=[${entryNames.join(", ")}] hasThemeJson=${!!themeEntry}`,
32301
32356
  );
32302
- return {
32303
- success: false,
32304
- error: `ZIP extraction failed: no .theme.json file found in archive. Files present: [${entryNames.join(", ")}]`,
32305
- };
32306
- }
32307
32357
 
32308
- // Validate entry path (security: prevent path traversal)
32309
- if (
32310
- themeEntry.entryName.includes("..") ||
32311
- path$2.isAbsolute(themeEntry.entryName)
32312
- ) {
32313
- return {
32314
- success: false,
32315
- error: "ZIP extraction failed: invalid file path detected in archive.",
32316
- };
32317
- }
32358
+ if (!themeEntry) {
32359
+ console.log(
32360
+ `${TAG} [4/5 ZIP Extraction] FAIL — no .theme.json in archive`,
32361
+ );
32362
+ return {
32363
+ success: false,
32364
+ error: `ZIP extraction failed: no .theme.json file found in archive. Files present: [${entryNames.join(", ")}]`,
32365
+ };
32366
+ }
32318
32367
 
32319
- // Parse theme data
32320
- const themeJson = themeEntry.getData().toString("utf-8");
32321
- let themeData;
32322
- try {
32323
- themeData = JSON.parse(themeJson);
32324
- } catch (parseErr) {
32325
- return {
32326
- success: false,
32327
- error: `ZIP extraction failed: ${themeEntry.entryName} contains invalid JSON (${parseErr.message}).`,
32328
- };
32368
+ // Validate entry path (security: prevent path traversal)
32369
+ if (
32370
+ themeEntry.entryName.includes("..") ||
32371
+ path$2.isAbsolute(themeEntry.entryName)
32372
+ ) {
32373
+ return {
32374
+ success: false,
32375
+ error:
32376
+ "ZIP extraction failed: invalid file path detected in archive.",
32377
+ };
32378
+ }
32379
+
32380
+ // Parse theme data from ZIP entry
32381
+ const themeJson = themeEntry.getData().toString("utf-8");
32382
+ try {
32383
+ themeData = JSON.parse(themeJson);
32384
+ } catch (parseErr) {
32385
+ return {
32386
+ success: false,
32387
+ error: `ZIP extraction failed: ${themeEntry.entryName} contains invalid JSON (${parseErr.message}).`,
32388
+ };
32389
+ }
32329
32390
  }
32330
32391
 
32331
32392
  // Add registry metadata