@valbuild/server 0.48.1 → 0.49.0
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.
@@ -31,7 +31,7 @@ export declare class LocalValServer implements ValServer {
|
|
31
31
|
private badRequest;
|
32
32
|
postCommit(): Promise<ValServerJsonResult<{}>>;
|
33
33
|
authorize(): Promise<ValServerRedirectResult<VAL_STATE_COOKIE>>;
|
34
|
-
callback(): Promise<ValServerRedirectResult<VAL_STATE_COOKIE | VAL_SESSION_COOKIE>>;
|
34
|
+
callback(): Promise<ValServerRedirectResult<VAL_STATE_COOKIE | VAL_SESSION_COOKIE | VAL_ENABLE_COOKIE_NAME>>;
|
35
35
|
logout(): Promise<ValServerResult<VAL_STATE_COOKIE | VAL_SESSION_COOKIE>>;
|
36
36
|
getFiles(): Promise<ValServerResult<never, ReadableStream<Uint8Array>>>;
|
37
37
|
getPatches(): Promise<ValServerJsonResult<ApiGetPatchResponse>>;
|
@@ -22,7 +22,7 @@ export interface ValServer {
|
|
22
22
|
callback(query: {
|
23
23
|
code?: string;
|
24
24
|
state?: string;
|
25
|
-
}, cookies: ValCookies<VAL_STATE_COOKIE>): Promise<ValServerRedirectResult<VAL_STATE_COOKIE | VAL_SESSION_COOKIE>>;
|
25
|
+
}, cookies: ValCookies<VAL_STATE_COOKIE>): Promise<ValServerRedirectResult<VAL_STATE_COOKIE | VAL_SESSION_COOKIE | VAL_ENABLE_COOKIE_NAME>>;
|
26
26
|
enable(query: {
|
27
27
|
redirect_to?: string;
|
28
28
|
}): Promise<ValServerRedirectResult<VAL_ENABLE_COOKIE_NAME>>;
|
@@ -1422,12 +1422,12 @@ class ProxyValServer {
|
|
1422
1422
|
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
1423
1423
|
"Content-Length": fetchRes.headers.get("Content-Length") || "0"
|
1424
1424
|
},
|
1425
|
-
|
1425
|
+
json: fetchRes.body
|
1426
1426
|
};
|
1427
1427
|
} else {
|
1428
1428
|
return {
|
1429
1429
|
status: 500,
|
1430
|
-
|
1430
|
+
json: {
|
1431
1431
|
message: "No body in response"
|
1432
1432
|
}
|
1433
1433
|
};
|
@@ -1435,7 +1435,7 @@ class ProxyValServer {
|
|
1435
1435
|
} else {
|
1436
1436
|
return {
|
1437
1437
|
status: fetchRes.status,
|
1438
|
-
|
1438
|
+
json: {
|
1439
1439
|
message: "Failed to get files"
|
1440
1440
|
}
|
1441
1441
|
};
|
@@ -1542,6 +1542,7 @@ class ProxyValServer {
|
|
1542
1542
|
[internal.VAL_STATE_COOKIE]: {
|
1543
1543
|
value: null
|
1544
1544
|
},
|
1545
|
+
[internal.VAL_ENABLE_COOKIE_NAME]: ENABLE_COOKIE_VALUE,
|
1545
1546
|
[internal.VAL_SESSION_COOKIE]: {
|
1546
1547
|
value: cookie,
|
1547
1548
|
options: {
|
@@ -1596,7 +1597,7 @@ class ProxyValServer {
|
|
1596
1597
|
console.error(`Failed while processing: ${errorMessageType}`, err);
|
1597
1598
|
return {
|
1598
1599
|
status: 500,
|
1599
|
-
|
1600
|
+
json: {
|
1600
1601
|
message: err.message
|
1601
1602
|
}
|
1602
1603
|
};
|
@@ -1628,8 +1629,9 @@ class ProxyValServer {
|
|
1628
1629
|
} else {
|
1629
1630
|
return {
|
1630
1631
|
status: fetchRes.status,
|
1631
|
-
|
1632
|
-
message: "Failed to
|
1632
|
+
json: {
|
1633
|
+
message: "Failed to authorize",
|
1634
|
+
...(await fetchRes.json())
|
1633
1635
|
}
|
1634
1636
|
};
|
1635
1637
|
}
|
@@ -1646,7 +1648,7 @@ class ProxyValServer {
|
|
1646
1648
|
if (!commit) {
|
1647
1649
|
return {
|
1648
1650
|
status: 400,
|
1649
|
-
|
1651
|
+
json: {
|
1650
1652
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1651
1653
|
}
|
1652
1654
|
};
|
@@ -1690,7 +1692,7 @@ class ProxyValServer {
|
|
1690
1692
|
} catch (err) {
|
1691
1693
|
return {
|
1692
1694
|
status: 500,
|
1693
|
-
|
1695
|
+
json: {
|
1694
1696
|
message: "Failed to fetch: check network connection"
|
1695
1697
|
}
|
1696
1698
|
};
|
@@ -1705,7 +1707,7 @@ class ProxyValServer {
|
|
1705
1707
|
if (!commit) {
|
1706
1708
|
return {
|
1707
1709
|
status: 400,
|
1708
|
-
|
1710
|
+
json: {
|
1709
1711
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1710
1712
|
}
|
1711
1713
|
};
|
@@ -1726,7 +1728,7 @@ class ProxyValServer {
|
|
1726
1728
|
} else {
|
1727
1729
|
return {
|
1728
1730
|
status: fetchRes.status,
|
1729
|
-
|
1731
|
+
json: {
|
1730
1732
|
message: "Failed to get patches"
|
1731
1733
|
}
|
1732
1734
|
};
|
@@ -1754,7 +1756,7 @@ class ProxyValServer {
|
|
1754
1756
|
if (!patchJSON.success) {
|
1755
1757
|
return {
|
1756
1758
|
status: 400,
|
1757
|
-
|
1759
|
+
json: {
|
1758
1760
|
message: "Invalid patch",
|
1759
1761
|
details: patchJSON.error.issues
|
1760
1762
|
}
|
@@ -2273,7 +2275,17 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2273
2275
|
const filename = path__namespace["default"].join(config.projectRoot, maybeRef);
|
2274
2276
|
const buffer = fs__default["default"].readFileSync(filename);
|
2275
2277
|
const imageSize = sizeOf__default["default"](buffer);
|
2276
|
-
|
2278
|
+
let mimeType = null;
|
2279
|
+
if (imageSize.type) {
|
2280
|
+
const possibleMimeType = `image/${imageSize.type}`;
|
2281
|
+
if (internal.MIME_TYPES_TO_EXT[possibleMimeType]) {
|
2282
|
+
mimeType = possibleMimeType;
|
2283
|
+
}
|
2284
|
+
const filenameBasedLookup = internal.filenameToMimeType(filename);
|
2285
|
+
if (filenameBasedLookup) {
|
2286
|
+
mimeType = filenameBasedLookup;
|
2287
|
+
}
|
2288
|
+
}
|
2277
2289
|
if (!mimeType) {
|
2278
2290
|
throw Error("Cannot determine mimetype of image");
|
2279
2291
|
}
|
@@ -2294,6 +2306,26 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2294
2306
|
mimeType
|
2295
2307
|
};
|
2296
2308
|
}
|
2309
|
+
async function getFileMetadata() {
|
2310
|
+
const maybeRef = validationError.value && typeof validationError.value === "object" && core.FILE_REF_PROP in validationError.value && typeof validationError.value[core.FILE_REF_PROP] === "string" ? validationError.value[core.FILE_REF_PROP] : undefined;
|
2311
|
+
if (!maybeRef) {
|
2312
|
+
// TODO:
|
2313
|
+
throw Error("Cannot fix image without a file reference");
|
2314
|
+
}
|
2315
|
+
const filename = path__namespace["default"].join(config.projectRoot, maybeRef);
|
2316
|
+
const buffer = fs__default["default"].readFileSync(filename);
|
2317
|
+
let mimeType = internal.filenameToMimeType(filename);
|
2318
|
+
if (!mimeType) {
|
2319
|
+
mimeType = "application/octet-stream";
|
2320
|
+
}
|
2321
|
+
const sha256 = core.Internal.getSHA256Hash(textEncoder.encode(
|
2322
|
+
// TODO: we should probably store the mimetype in the metadata and reuse it here
|
2323
|
+
`data:${mimeType};base64,${buffer.toString("base64")}`));
|
2324
|
+
return {
|
2325
|
+
sha256,
|
2326
|
+
mimeType
|
2327
|
+
};
|
2328
|
+
}
|
2297
2329
|
const remainingErrors = [];
|
2298
2330
|
const patch$1 = [];
|
2299
2331
|
for (const fix of validationError.fixes || []) {
|
@@ -2379,6 +2411,72 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2379
2411
|
}
|
2380
2412
|
});
|
2381
2413
|
}
|
2414
|
+
} else if (fix === "file:add-metadata" || fix === "file:check-metadata") {
|
2415
|
+
const fileMetadata = await getFileMetadata();
|
2416
|
+
if (fileMetadata.sha256 === undefined) {
|
2417
|
+
remainingErrors.push({
|
2418
|
+
...validationError,
|
2419
|
+
message: "Failed to get image metadata",
|
2420
|
+
fixes: undefined
|
2421
|
+
});
|
2422
|
+
} else if (fix === "file:check-metadata") {
|
2423
|
+
const currentValue = validationError.value;
|
2424
|
+
const metadataIsCorrect =
|
2425
|
+
// metadata is a prop that is an object
|
2426
|
+
typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object" &&
|
2427
|
+
// sha256 is correct
|
2428
|
+
"sha256" in currentValue.metadata && currentValue.metadata.sha256 === fileMetadata.sha256 &&
|
2429
|
+
// mimeType is correct
|
2430
|
+
"mimeType" in currentValue.metadata && currentValue.metadata.mimeType === fileMetadata.mimeType;
|
2431
|
+
|
2432
|
+
// skips if the metadata is already correct
|
2433
|
+
if (!metadataIsCorrect) {
|
2434
|
+
if (apply) {
|
2435
|
+
patch$1.push({
|
2436
|
+
op: "replace",
|
2437
|
+
path: patch.sourceToPatchPath(sourcePath).concat("metadata"),
|
2438
|
+
value: {
|
2439
|
+
sha256: fileMetadata.sha256,
|
2440
|
+
...(fileMetadata.mimeType ? {
|
2441
|
+
mimeType: fileMetadata.mimeType
|
2442
|
+
} : {})
|
2443
|
+
}
|
2444
|
+
});
|
2445
|
+
} else {
|
2446
|
+
if (typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object") {
|
2447
|
+
if (!("sha256" in currentValue.metadata) || currentValue.metadata.sha256 !== fileMetadata.sha256) {
|
2448
|
+
remainingErrors.push({
|
2449
|
+
message: "File metadata sha256 is incorrect! Found: " + ("sha256" in currentValue.metadata ? currentValue.metadata.sha256 : "<empty>") + ". Expected: " + fileMetadata.sha256 + ".",
|
2450
|
+
fixes: undefined
|
2451
|
+
});
|
2452
|
+
}
|
2453
|
+
if (!("mimeType" in currentValue.metadata) || currentValue.metadata.mimeType !== fileMetadata.mimeType) {
|
2454
|
+
remainingErrors.push({
|
2455
|
+
message: "File metadata mimeType is incorrect! Found: " + ("mimeType" in currentValue.metadata ? currentValue.metadata.mimeType : "<empty>") + ". Expected: " + fileMetadata.mimeType,
|
2456
|
+
fixes: undefined
|
2457
|
+
});
|
2458
|
+
}
|
2459
|
+
} else {
|
2460
|
+
remainingErrors.push({
|
2461
|
+
...validationError,
|
2462
|
+
message: "Image metadata is not an object!",
|
2463
|
+
fixes: undefined
|
2464
|
+
});
|
2465
|
+
}
|
2466
|
+
}
|
2467
|
+
}
|
2468
|
+
} else if (fix === "file:add-metadata") {
|
2469
|
+
patch$1.push({
|
2470
|
+
op: "add",
|
2471
|
+
path: patch.sourceToPatchPath(sourcePath).concat("metadata"),
|
2472
|
+
value: {
|
2473
|
+
sha256: fileMetadata.sha256,
|
2474
|
+
...(fileMetadata.mimeType ? {
|
2475
|
+
mimeType: fileMetadata.mimeType
|
2476
|
+
} : {})
|
2477
|
+
}
|
2478
|
+
});
|
2479
|
+
}
|
2382
2480
|
}
|
2383
2481
|
}
|
2384
2482
|
if (!validationError.fixes || validationError.fixes.length === 0) {
|
@@ -1422,12 +1422,12 @@ class ProxyValServer {
|
|
1422
1422
|
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
1423
1423
|
"Content-Length": fetchRes.headers.get("Content-Length") || "0"
|
1424
1424
|
},
|
1425
|
-
|
1425
|
+
json: fetchRes.body
|
1426
1426
|
};
|
1427
1427
|
} else {
|
1428
1428
|
return {
|
1429
1429
|
status: 500,
|
1430
|
-
|
1430
|
+
json: {
|
1431
1431
|
message: "No body in response"
|
1432
1432
|
}
|
1433
1433
|
};
|
@@ -1435,7 +1435,7 @@ class ProxyValServer {
|
|
1435
1435
|
} else {
|
1436
1436
|
return {
|
1437
1437
|
status: fetchRes.status,
|
1438
|
-
|
1438
|
+
json: {
|
1439
1439
|
message: "Failed to get files"
|
1440
1440
|
}
|
1441
1441
|
};
|
@@ -1542,6 +1542,7 @@ class ProxyValServer {
|
|
1542
1542
|
[internal.VAL_STATE_COOKIE]: {
|
1543
1543
|
value: null
|
1544
1544
|
},
|
1545
|
+
[internal.VAL_ENABLE_COOKIE_NAME]: ENABLE_COOKIE_VALUE,
|
1545
1546
|
[internal.VAL_SESSION_COOKIE]: {
|
1546
1547
|
value: cookie,
|
1547
1548
|
options: {
|
@@ -1596,7 +1597,7 @@ class ProxyValServer {
|
|
1596
1597
|
console.error(`Failed while processing: ${errorMessageType}`, err);
|
1597
1598
|
return {
|
1598
1599
|
status: 500,
|
1599
|
-
|
1600
|
+
json: {
|
1600
1601
|
message: err.message
|
1601
1602
|
}
|
1602
1603
|
};
|
@@ -1628,8 +1629,9 @@ class ProxyValServer {
|
|
1628
1629
|
} else {
|
1629
1630
|
return {
|
1630
1631
|
status: fetchRes.status,
|
1631
|
-
|
1632
|
-
message: "Failed to
|
1632
|
+
json: {
|
1633
|
+
message: "Failed to authorize",
|
1634
|
+
...(await fetchRes.json())
|
1633
1635
|
}
|
1634
1636
|
};
|
1635
1637
|
}
|
@@ -1646,7 +1648,7 @@ class ProxyValServer {
|
|
1646
1648
|
if (!commit) {
|
1647
1649
|
return {
|
1648
1650
|
status: 400,
|
1649
|
-
|
1651
|
+
json: {
|
1650
1652
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1651
1653
|
}
|
1652
1654
|
};
|
@@ -1690,7 +1692,7 @@ class ProxyValServer {
|
|
1690
1692
|
} catch (err) {
|
1691
1693
|
return {
|
1692
1694
|
status: 500,
|
1693
|
-
|
1695
|
+
json: {
|
1694
1696
|
message: "Failed to fetch: check network connection"
|
1695
1697
|
}
|
1696
1698
|
};
|
@@ -1705,7 +1707,7 @@ class ProxyValServer {
|
|
1705
1707
|
if (!commit) {
|
1706
1708
|
return {
|
1707
1709
|
status: 400,
|
1708
|
-
|
1710
|
+
json: {
|
1709
1711
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1710
1712
|
}
|
1711
1713
|
};
|
@@ -1726,7 +1728,7 @@ class ProxyValServer {
|
|
1726
1728
|
} else {
|
1727
1729
|
return {
|
1728
1730
|
status: fetchRes.status,
|
1729
|
-
|
1731
|
+
json: {
|
1730
1732
|
message: "Failed to get patches"
|
1731
1733
|
}
|
1732
1734
|
};
|
@@ -1754,7 +1756,7 @@ class ProxyValServer {
|
|
1754
1756
|
if (!patchJSON.success) {
|
1755
1757
|
return {
|
1756
1758
|
status: 400,
|
1757
|
-
|
1759
|
+
json: {
|
1758
1760
|
message: "Invalid patch",
|
1759
1761
|
details: patchJSON.error.issues
|
1760
1762
|
}
|
@@ -2273,7 +2275,17 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2273
2275
|
const filename = path__namespace["default"].join(config.projectRoot, maybeRef);
|
2274
2276
|
const buffer = fs__default["default"].readFileSync(filename);
|
2275
2277
|
const imageSize = sizeOf__default["default"](buffer);
|
2276
|
-
|
2278
|
+
let mimeType = null;
|
2279
|
+
if (imageSize.type) {
|
2280
|
+
const possibleMimeType = `image/${imageSize.type}`;
|
2281
|
+
if (internal.MIME_TYPES_TO_EXT[possibleMimeType]) {
|
2282
|
+
mimeType = possibleMimeType;
|
2283
|
+
}
|
2284
|
+
const filenameBasedLookup = internal.filenameToMimeType(filename);
|
2285
|
+
if (filenameBasedLookup) {
|
2286
|
+
mimeType = filenameBasedLookup;
|
2287
|
+
}
|
2288
|
+
}
|
2277
2289
|
if (!mimeType) {
|
2278
2290
|
throw Error("Cannot determine mimetype of image");
|
2279
2291
|
}
|
@@ -2294,6 +2306,26 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2294
2306
|
mimeType
|
2295
2307
|
};
|
2296
2308
|
}
|
2309
|
+
async function getFileMetadata() {
|
2310
|
+
const maybeRef = validationError.value && typeof validationError.value === "object" && core.FILE_REF_PROP in validationError.value && typeof validationError.value[core.FILE_REF_PROP] === "string" ? validationError.value[core.FILE_REF_PROP] : undefined;
|
2311
|
+
if (!maybeRef) {
|
2312
|
+
// TODO:
|
2313
|
+
throw Error("Cannot fix image without a file reference");
|
2314
|
+
}
|
2315
|
+
const filename = path__namespace["default"].join(config.projectRoot, maybeRef);
|
2316
|
+
const buffer = fs__default["default"].readFileSync(filename);
|
2317
|
+
let mimeType = internal.filenameToMimeType(filename);
|
2318
|
+
if (!mimeType) {
|
2319
|
+
mimeType = "application/octet-stream";
|
2320
|
+
}
|
2321
|
+
const sha256 = core.Internal.getSHA256Hash(textEncoder.encode(
|
2322
|
+
// TODO: we should probably store the mimetype in the metadata and reuse it here
|
2323
|
+
`data:${mimeType};base64,${buffer.toString("base64")}`));
|
2324
|
+
return {
|
2325
|
+
sha256,
|
2326
|
+
mimeType
|
2327
|
+
};
|
2328
|
+
}
|
2297
2329
|
const remainingErrors = [];
|
2298
2330
|
const patch$1 = [];
|
2299
2331
|
for (const fix of validationError.fixes || []) {
|
@@ -2379,6 +2411,72 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2379
2411
|
}
|
2380
2412
|
});
|
2381
2413
|
}
|
2414
|
+
} else if (fix === "file:add-metadata" || fix === "file:check-metadata") {
|
2415
|
+
const fileMetadata = await getFileMetadata();
|
2416
|
+
if (fileMetadata.sha256 === undefined) {
|
2417
|
+
remainingErrors.push({
|
2418
|
+
...validationError,
|
2419
|
+
message: "Failed to get image metadata",
|
2420
|
+
fixes: undefined
|
2421
|
+
});
|
2422
|
+
} else if (fix === "file:check-metadata") {
|
2423
|
+
const currentValue = validationError.value;
|
2424
|
+
const metadataIsCorrect =
|
2425
|
+
// metadata is a prop that is an object
|
2426
|
+
typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object" &&
|
2427
|
+
// sha256 is correct
|
2428
|
+
"sha256" in currentValue.metadata && currentValue.metadata.sha256 === fileMetadata.sha256 &&
|
2429
|
+
// mimeType is correct
|
2430
|
+
"mimeType" in currentValue.metadata && currentValue.metadata.mimeType === fileMetadata.mimeType;
|
2431
|
+
|
2432
|
+
// skips if the metadata is already correct
|
2433
|
+
if (!metadataIsCorrect) {
|
2434
|
+
if (apply) {
|
2435
|
+
patch$1.push({
|
2436
|
+
op: "replace",
|
2437
|
+
path: patch.sourceToPatchPath(sourcePath).concat("metadata"),
|
2438
|
+
value: {
|
2439
|
+
sha256: fileMetadata.sha256,
|
2440
|
+
...(fileMetadata.mimeType ? {
|
2441
|
+
mimeType: fileMetadata.mimeType
|
2442
|
+
} : {})
|
2443
|
+
}
|
2444
|
+
});
|
2445
|
+
} else {
|
2446
|
+
if (typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object") {
|
2447
|
+
if (!("sha256" in currentValue.metadata) || currentValue.metadata.sha256 !== fileMetadata.sha256) {
|
2448
|
+
remainingErrors.push({
|
2449
|
+
message: "File metadata sha256 is incorrect! Found: " + ("sha256" in currentValue.metadata ? currentValue.metadata.sha256 : "<empty>") + ". Expected: " + fileMetadata.sha256 + ".",
|
2450
|
+
fixes: undefined
|
2451
|
+
});
|
2452
|
+
}
|
2453
|
+
if (!("mimeType" in currentValue.metadata) || currentValue.metadata.mimeType !== fileMetadata.mimeType) {
|
2454
|
+
remainingErrors.push({
|
2455
|
+
message: "File metadata mimeType is incorrect! Found: " + ("mimeType" in currentValue.metadata ? currentValue.metadata.mimeType : "<empty>") + ". Expected: " + fileMetadata.mimeType,
|
2456
|
+
fixes: undefined
|
2457
|
+
});
|
2458
|
+
}
|
2459
|
+
} else {
|
2460
|
+
remainingErrors.push({
|
2461
|
+
...validationError,
|
2462
|
+
message: "Image metadata is not an object!",
|
2463
|
+
fixes: undefined
|
2464
|
+
});
|
2465
|
+
}
|
2466
|
+
}
|
2467
|
+
}
|
2468
|
+
} else if (fix === "file:add-metadata") {
|
2469
|
+
patch$1.push({
|
2470
|
+
op: "add",
|
2471
|
+
path: patch.sourceToPatchPath(sourcePath).concat("metadata"),
|
2472
|
+
value: {
|
2473
|
+
sha256: fileMetadata.sha256,
|
2474
|
+
...(fileMetadata.mimeType ? {
|
2475
|
+
mimeType: fileMetadata.mimeType
|
2476
|
+
} : {})
|
2477
|
+
}
|
2478
|
+
});
|
2479
|
+
}
|
2382
2480
|
}
|
2383
2481
|
}
|
2384
2482
|
if (!validationError.fixes || validationError.fixes.length === 0) {
|
@@ -8,7 +8,7 @@ import path__default from 'path';
|
|
8
8
|
import fs, { promises } from 'fs';
|
9
9
|
import { transform } from 'sucrase';
|
10
10
|
import z, { z as z$1 } from 'zod';
|
11
|
-
import { VAL_ENABLE_COOKIE_NAME, VAL_STATE_COOKIE as VAL_STATE_COOKIE$1, VAL_SESSION_COOKIE as VAL_SESSION_COOKIE$1,
|
11
|
+
import { VAL_ENABLE_COOKIE_NAME, VAL_STATE_COOKIE as VAL_STATE_COOKIE$1, VAL_SESSION_COOKIE as VAL_SESSION_COOKIE$1, MIME_TYPES_TO_EXT, filenameToMimeType } from '@valbuild/shared/internal';
|
12
12
|
import crypto from 'crypto';
|
13
13
|
import { createUIRequestHandler } from '@valbuild/ui/server';
|
14
14
|
import sizeOf from 'image-size';
|
@@ -1392,12 +1392,12 @@ class ProxyValServer {
|
|
1392
1392
|
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
1393
1393
|
"Content-Length": fetchRes.headers.get("Content-Length") || "0"
|
1394
1394
|
},
|
1395
|
-
|
1395
|
+
json: fetchRes.body
|
1396
1396
|
};
|
1397
1397
|
} else {
|
1398
1398
|
return {
|
1399
1399
|
status: 500,
|
1400
|
-
|
1400
|
+
json: {
|
1401
1401
|
message: "No body in response"
|
1402
1402
|
}
|
1403
1403
|
};
|
@@ -1405,7 +1405,7 @@ class ProxyValServer {
|
|
1405
1405
|
} else {
|
1406
1406
|
return {
|
1407
1407
|
status: fetchRes.status,
|
1408
|
-
|
1408
|
+
json: {
|
1409
1409
|
message: "Failed to get files"
|
1410
1410
|
}
|
1411
1411
|
};
|
@@ -1512,6 +1512,7 @@ class ProxyValServer {
|
|
1512
1512
|
[VAL_STATE_COOKIE$1]: {
|
1513
1513
|
value: null
|
1514
1514
|
},
|
1515
|
+
[VAL_ENABLE_COOKIE_NAME]: ENABLE_COOKIE_VALUE,
|
1515
1516
|
[VAL_SESSION_COOKIE$1]: {
|
1516
1517
|
value: cookie,
|
1517
1518
|
options: {
|
@@ -1566,7 +1567,7 @@ class ProxyValServer {
|
|
1566
1567
|
console.error(`Failed while processing: ${errorMessageType}`, err);
|
1567
1568
|
return {
|
1568
1569
|
status: 500,
|
1569
|
-
|
1570
|
+
json: {
|
1570
1571
|
message: err.message
|
1571
1572
|
}
|
1572
1573
|
};
|
@@ -1598,8 +1599,9 @@ class ProxyValServer {
|
|
1598
1599
|
} else {
|
1599
1600
|
return {
|
1600
1601
|
status: fetchRes.status,
|
1601
|
-
|
1602
|
-
message: "Failed to
|
1602
|
+
json: {
|
1603
|
+
message: "Failed to authorize",
|
1604
|
+
...(await fetchRes.json())
|
1603
1605
|
}
|
1604
1606
|
};
|
1605
1607
|
}
|
@@ -1616,7 +1618,7 @@ class ProxyValServer {
|
|
1616
1618
|
if (!commit) {
|
1617
1619
|
return {
|
1618
1620
|
status: 400,
|
1619
|
-
|
1621
|
+
json: {
|
1620
1622
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1621
1623
|
}
|
1622
1624
|
};
|
@@ -1660,7 +1662,7 @@ class ProxyValServer {
|
|
1660
1662
|
} catch (err) {
|
1661
1663
|
return {
|
1662
1664
|
status: 500,
|
1663
|
-
|
1665
|
+
json: {
|
1664
1666
|
message: "Failed to fetch: check network connection"
|
1665
1667
|
}
|
1666
1668
|
};
|
@@ -1675,7 +1677,7 @@ class ProxyValServer {
|
|
1675
1677
|
if (!commit) {
|
1676
1678
|
return {
|
1677
1679
|
status: 400,
|
1678
|
-
|
1680
|
+
json: {
|
1679
1681
|
message: "Could not detect the git commit. Check if env is missing VAL_GIT_COMMIT."
|
1680
1682
|
}
|
1681
1683
|
};
|
@@ -1696,7 +1698,7 @@ class ProxyValServer {
|
|
1696
1698
|
} else {
|
1697
1699
|
return {
|
1698
1700
|
status: fetchRes.status,
|
1699
|
-
|
1701
|
+
json: {
|
1700
1702
|
message: "Failed to get patches"
|
1701
1703
|
}
|
1702
1704
|
};
|
@@ -1724,7 +1726,7 @@ class ProxyValServer {
|
|
1724
1726
|
if (!patchJSON.success) {
|
1725
1727
|
return {
|
1726
1728
|
status: 400,
|
1727
|
-
|
1729
|
+
json: {
|
1728
1730
|
message: "Invalid patch",
|
1729
1731
|
details: patchJSON.error.issues
|
1730
1732
|
}
|
@@ -2243,7 +2245,17 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2243
2245
|
const filename = path__default.join(config.projectRoot, maybeRef);
|
2244
2246
|
const buffer = fs.readFileSync(filename);
|
2245
2247
|
const imageSize = sizeOf(buffer);
|
2246
|
-
|
2248
|
+
let mimeType = null;
|
2249
|
+
if (imageSize.type) {
|
2250
|
+
const possibleMimeType = `image/${imageSize.type}`;
|
2251
|
+
if (MIME_TYPES_TO_EXT[possibleMimeType]) {
|
2252
|
+
mimeType = possibleMimeType;
|
2253
|
+
}
|
2254
|
+
const filenameBasedLookup = filenameToMimeType(filename);
|
2255
|
+
if (filenameBasedLookup) {
|
2256
|
+
mimeType = filenameBasedLookup;
|
2257
|
+
}
|
2258
|
+
}
|
2247
2259
|
if (!mimeType) {
|
2248
2260
|
throw Error("Cannot determine mimetype of image");
|
2249
2261
|
}
|
@@ -2264,6 +2276,26 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2264
2276
|
mimeType
|
2265
2277
|
};
|
2266
2278
|
}
|
2279
|
+
async function getFileMetadata() {
|
2280
|
+
const maybeRef = validationError.value && typeof validationError.value === "object" && FILE_REF_PROP in validationError.value && typeof validationError.value[FILE_REF_PROP] === "string" ? validationError.value[FILE_REF_PROP] : undefined;
|
2281
|
+
if (!maybeRef) {
|
2282
|
+
// TODO:
|
2283
|
+
throw Error("Cannot fix image without a file reference");
|
2284
|
+
}
|
2285
|
+
const filename = path__default.join(config.projectRoot, maybeRef);
|
2286
|
+
const buffer = fs.readFileSync(filename);
|
2287
|
+
let mimeType = filenameToMimeType(filename);
|
2288
|
+
if (!mimeType) {
|
2289
|
+
mimeType = "application/octet-stream";
|
2290
|
+
}
|
2291
|
+
const sha256 = Internal.getSHA256Hash(textEncoder.encode(
|
2292
|
+
// TODO: we should probably store the mimetype in the metadata and reuse it here
|
2293
|
+
`data:${mimeType};base64,${buffer.toString("base64")}`));
|
2294
|
+
return {
|
2295
|
+
sha256,
|
2296
|
+
mimeType
|
2297
|
+
};
|
2298
|
+
}
|
2267
2299
|
const remainingErrors = [];
|
2268
2300
|
const patch = [];
|
2269
2301
|
for (const fix of validationError.fixes || []) {
|
@@ -2349,6 +2381,72 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
2349
2381
|
}
|
2350
2382
|
});
|
2351
2383
|
}
|
2384
|
+
} else if (fix === "file:add-metadata" || fix === "file:check-metadata") {
|
2385
|
+
const fileMetadata = await getFileMetadata();
|
2386
|
+
if (fileMetadata.sha256 === undefined) {
|
2387
|
+
remainingErrors.push({
|
2388
|
+
...validationError,
|
2389
|
+
message: "Failed to get image metadata",
|
2390
|
+
fixes: undefined
|
2391
|
+
});
|
2392
|
+
} else if (fix === "file:check-metadata") {
|
2393
|
+
const currentValue = validationError.value;
|
2394
|
+
const metadataIsCorrect =
|
2395
|
+
// metadata is a prop that is an object
|
2396
|
+
typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object" &&
|
2397
|
+
// sha256 is correct
|
2398
|
+
"sha256" in currentValue.metadata && currentValue.metadata.sha256 === fileMetadata.sha256 &&
|
2399
|
+
// mimeType is correct
|
2400
|
+
"mimeType" in currentValue.metadata && currentValue.metadata.mimeType === fileMetadata.mimeType;
|
2401
|
+
|
2402
|
+
// skips if the metadata is already correct
|
2403
|
+
if (!metadataIsCorrect) {
|
2404
|
+
if (apply) {
|
2405
|
+
patch.push({
|
2406
|
+
op: "replace",
|
2407
|
+
path: sourceToPatchPath(sourcePath).concat("metadata"),
|
2408
|
+
value: {
|
2409
|
+
sha256: fileMetadata.sha256,
|
2410
|
+
...(fileMetadata.mimeType ? {
|
2411
|
+
mimeType: fileMetadata.mimeType
|
2412
|
+
} : {})
|
2413
|
+
}
|
2414
|
+
});
|
2415
|
+
} else {
|
2416
|
+
if (typeof currentValue === "object" && currentValue && "metadata" in currentValue && currentValue.metadata && typeof currentValue.metadata === "object") {
|
2417
|
+
if (!("sha256" in currentValue.metadata) || currentValue.metadata.sha256 !== fileMetadata.sha256) {
|
2418
|
+
remainingErrors.push({
|
2419
|
+
message: "File metadata sha256 is incorrect! Found: " + ("sha256" in currentValue.metadata ? currentValue.metadata.sha256 : "<empty>") + ". Expected: " + fileMetadata.sha256 + ".",
|
2420
|
+
fixes: undefined
|
2421
|
+
});
|
2422
|
+
}
|
2423
|
+
if (!("mimeType" in currentValue.metadata) || currentValue.metadata.mimeType !== fileMetadata.mimeType) {
|
2424
|
+
remainingErrors.push({
|
2425
|
+
message: "File metadata mimeType is incorrect! Found: " + ("mimeType" in currentValue.metadata ? currentValue.metadata.mimeType : "<empty>") + ". Expected: " + fileMetadata.mimeType,
|
2426
|
+
fixes: undefined
|
2427
|
+
});
|
2428
|
+
}
|
2429
|
+
} else {
|
2430
|
+
remainingErrors.push({
|
2431
|
+
...validationError,
|
2432
|
+
message: "Image metadata is not an object!",
|
2433
|
+
fixes: undefined
|
2434
|
+
});
|
2435
|
+
}
|
2436
|
+
}
|
2437
|
+
}
|
2438
|
+
} else if (fix === "file:add-metadata") {
|
2439
|
+
patch.push({
|
2440
|
+
op: "add",
|
2441
|
+
path: sourceToPatchPath(sourcePath).concat("metadata"),
|
2442
|
+
value: {
|
2443
|
+
sha256: fileMetadata.sha256,
|
2444
|
+
...(fileMetadata.mimeType ? {
|
2445
|
+
mimeType: fileMetadata.mimeType
|
2446
|
+
} : {})
|
2447
|
+
}
|
2448
|
+
});
|
2449
|
+
}
|
2352
2450
|
}
|
2353
2451
|
}
|
2354
2452
|
if (!validationError.fixes || validationError.fixes.length === 0) {
|
package/package.json
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
"./package.json": "./package.json"
|
13
13
|
},
|
14
14
|
"types": "dist/valbuild-server.cjs.d.ts",
|
15
|
-
"version": "0.
|
15
|
+
"version": "0.49.0",
|
16
16
|
"scripts": {
|
17
17
|
"typecheck": "tsc --noEmit",
|
18
18
|
"test": "jest",
|
@@ -24,9 +24,9 @@
|
|
24
24
|
"concurrently": "^7.6.0"
|
25
25
|
},
|
26
26
|
"dependencies": {
|
27
|
-
"@valbuild/core": "~0.
|
28
|
-
"@valbuild/shared": "~0.
|
29
|
-
"@valbuild/ui": "~0.
|
27
|
+
"@valbuild/core": "~0.49.0",
|
28
|
+
"@valbuild/shared": "~0.49.0",
|
29
|
+
"@valbuild/ui": "~0.49.0",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"queue": "^6.0.2",
|