@valbuild/server 0.60.22 → 0.60.23
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.
@@ -1452,7 +1452,7 @@ class ValServer {
|
|
1452
1452
|
async getTree(treePath,
|
1453
1453
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1454
1454
|
query, cookies, requestHeaders) {
|
1455
|
-
const ensureRes = await this.ensureInitialized("getTree", cookies);
|
1455
|
+
const ensureRes = await debugTiming("ensureInitialized", () => this.ensureInitialized("getTree", cookies));
|
1456
1456
|
if (fp.result.isErr(ensureRes)) {
|
1457
1457
|
return ensureRes.error;
|
1458
1458
|
}
|
@@ -1460,7 +1460,7 @@ class ValServer {
|
|
1460
1460
|
const execValidations = query.validate === "true";
|
1461
1461
|
const includeSource = query.source === "true";
|
1462
1462
|
const includeSchema = query.schema === "true";
|
1463
|
-
const moduleIds = await this.getAllModules(treePath);
|
1463
|
+
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
1464
1464
|
let {
|
1465
1465
|
patchIdsByModuleId,
|
1466
1466
|
patchesById,
|
@@ -1471,7 +1471,7 @@ class ValServer {
|
|
1471
1471
|
fileUpdates: {}
|
1472
1472
|
};
|
1473
1473
|
if (applyPatches) {
|
1474
|
-
const res = await this.readPatches(cookies);
|
1474
|
+
const res = await debugTiming("readPatches", () => this.readPatches(cookies));
|
1475
1475
|
if (fp.result.isErr(res)) {
|
1476
1476
|
return res.error;
|
1477
1477
|
}
|
@@ -1479,9 +1479,9 @@ class ValServer {
|
|
1479
1479
|
patchesById = res.value.patchesById;
|
1480
1480
|
fileUpdates = res.value.fileUpdates;
|
1481
1481
|
}
|
1482
|
-
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1482
|
+
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1483
1483
|
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, execValidations, includeSource, includeSchema);
|
1484
|
-
}));
|
1484
|
+
})));
|
1485
1485
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1486
1486
|
const module = {
|
1487
1487
|
schema: serializedModuleContent.schema,
|
@@ -1551,38 +1551,40 @@ class ValServer {
|
|
1551
1551
|
return serializedModuleContent;
|
1552
1552
|
}
|
1553
1553
|
let source = maybeSource;
|
1554
|
-
|
1555
|
-
const
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1554
|
+
await debugTiming("applyPatches:" + moduleId, async () => {
|
1555
|
+
for (const patchId of patchIdsByModuleId[moduleId] ?? []) {
|
1556
|
+
const patch$1 = patchesById[patchId];
|
1557
|
+
if (!patch$1) {
|
1558
|
+
continue;
|
1559
|
+
}
|
1560
|
+
const patchRes = patch.applyPatch(source, ops, patch$1.filter(core.Internal.notFileOp));
|
1561
|
+
if (fp.result.isOk(patchRes)) {
|
1562
|
+
source = patchRes.value;
|
1563
|
+
} else {
|
1564
|
+
console.error("Val: got an unexpected error while applying patch. Is there a mismatch in Val versions? Perhaps Val is misconfigured?", {
|
1565
|
+
patchId,
|
1566
|
+
moduleId,
|
1567
|
+
patch: JSON.stringify(patch$1, null, 2),
|
1568
|
+
error: patchRes.error
|
1569
|
+
});
|
1570
|
+
return {
|
1571
|
+
path: moduleId,
|
1572
|
+
schema,
|
1573
|
+
source,
|
1574
|
+
errors: {
|
1575
|
+
fatal: [{
|
1576
|
+
message: "Unexpected error applying patch",
|
1577
|
+
type: "invalid-patch"
|
1578
|
+
}]
|
1579
|
+
}
|
1580
|
+
};
|
1581
|
+
}
|
1580
1582
|
}
|
1581
|
-
}
|
1583
|
+
});
|
1582
1584
|
if (validate) {
|
1583
|
-
const validationErrors = core.deserializeSchema(schema).validate(moduleId, source);
|
1585
|
+
const validationErrors = await debugTiming("validate:" + moduleId, async () => core.deserializeSchema(schema).validate(moduleId, source));
|
1584
1586
|
if (validationErrors) {
|
1585
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1587
|
+
const revalidated = await debugTiming("revalidate image/file:" + moduleId, async () => this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders));
|
1586
1588
|
return {
|
1587
1589
|
path: moduleId,
|
1588
1590
|
schema,
|
@@ -2034,6 +2036,16 @@ function guessMimeTypeFromPath(filePath) {
|
|
2034
2036
|
function isCachedPatchFileOp(op) {
|
2035
2037
|
return !!(op.op === "file" && typeof op.filePath === "string" && op.value && typeof op.value === "object" && !Array.isArray(op.value) && "sha256" in op.value && typeof op.value.sha256 === "string");
|
2036
2038
|
}
|
2039
|
+
async function debugTiming(id, fn) {
|
2040
|
+
if (process.env["VAL_DEBUG_TIMING"] === "true") {
|
2041
|
+
const start = Date.now();
|
2042
|
+
const r = await fn();
|
2043
|
+
console.log(`Timing: ${id} took: ${Date.now() - start}ms (${new Date().toISOString()})`);
|
2044
|
+
return r;
|
2045
|
+
} else {
|
2046
|
+
return fn();
|
2047
|
+
}
|
2048
|
+
}
|
2037
2049
|
|
2038
2050
|
const textEncoder = new TextEncoder();
|
2039
2051
|
class LocalValServer extends ValServer {
|
@@ -2824,76 +2836,51 @@ class ProxyValServer extends ValServer {
|
|
2824
2836
|
}
|
2825
2837
|
});
|
2826
2838
|
}
|
2827
|
-
async getFiles(filePath, query,
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2839
|
+
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2840
|
+
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2841
|
+
if (typeof query.sha256 === "string") {
|
2842
|
+
url.searchParams.append("sha256", query.sha256);
|
2843
|
+
}
|
2844
|
+
const fetchRes = await fetch(url);
|
2845
|
+
if (fetchRes.status === 200) {
|
2846
|
+
// TODO: does this stream data?
|
2847
|
+
if (fetchRes.body) {
|
2848
|
+
return {
|
2849
|
+
status: fetchRes.status,
|
2850
|
+
headers: {
|
2851
|
+
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2852
|
+
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2853
|
+
"Cache-Control": fetchRes.headers.get("Cache-Control") || ""
|
2854
|
+
},
|
2855
|
+
body: fetchRes.body
|
2856
|
+
};
|
2832
2857
|
} else {
|
2833
|
-
|
2858
|
+
return {
|
2859
|
+
status: 500,
|
2860
|
+
json: {
|
2861
|
+
message: "No body in response"
|
2862
|
+
}
|
2863
|
+
};
|
2834
2864
|
}
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
return {
|
2842
|
-
status: fetchRes.status,
|
2843
|
-
headers: {
|
2844
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2845
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2846
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2847
|
-
},
|
2848
|
-
body: fetchRes.body
|
2849
|
-
};
|
2850
|
-
} else {
|
2851
|
-
return {
|
2852
|
-
status: 500,
|
2853
|
-
json: {
|
2854
|
-
message: "No body in response"
|
2855
|
-
}
|
2856
|
-
};
|
2857
|
-
}
|
2858
|
-
} else {
|
2859
|
-
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2860
|
-
return {
|
2861
|
-
status: 500,
|
2862
|
-
json: {
|
2863
|
-
message: "Missing host or x-forwarded-proto header"
|
2864
|
-
}
|
2865
|
-
};
|
2866
|
-
}
|
2867
|
-
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2868
|
-
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2869
|
-
const fetchRes = await fetch(staticPublicUrl, {
|
2870
|
-
headers: getAuthHeaders(data.token)
|
2871
|
-
});
|
2872
|
-
if (fetchRes.status === 200) {
|
2873
|
-
// TODO: does this stream data?
|
2874
|
-
if (fetchRes.body) {
|
2875
|
-
return {
|
2876
|
-
status: fetchRes.status,
|
2877
|
-
headers: {
|
2878
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2879
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2880
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2881
|
-
},
|
2882
|
-
body: fetchRes.body
|
2883
|
-
};
|
2884
|
-
} else {
|
2885
|
-
return {
|
2886
|
-
status: 500,
|
2887
|
-
json: {
|
2888
|
-
message: "No body in response"
|
2889
|
-
}
|
2890
|
-
};
|
2865
|
+
} else {
|
2866
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2867
|
+
return {
|
2868
|
+
status: 500,
|
2869
|
+
json: {
|
2870
|
+
message: "Missing host or x-forwarded-proto header"
|
2891
2871
|
}
|
2892
|
-
}
|
2893
|
-
throw new Error("Failed to fetch file: " + filePath);
|
2894
|
-
}
|
2872
|
+
};
|
2895
2873
|
}
|
2896
|
-
|
2874
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2875
|
+
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2876
|
+
const fetchRes = await fetch(staticPublicUrl);
|
2877
|
+
return {
|
2878
|
+
status: fetchRes.status,
|
2879
|
+
// forward headers from static public url
|
2880
|
+
headers: Object.fromEntries(fetchRes.headers.entries()),
|
2881
|
+
body: fetchRes.body
|
2882
|
+
};
|
2883
|
+
}
|
2897
2884
|
}
|
2898
2885
|
}
|
2899
2886
|
function verifyCallbackReq(stateCookie, queryParams) {
|
@@ -1452,7 +1452,7 @@ class ValServer {
|
|
1452
1452
|
async getTree(treePath,
|
1453
1453
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1454
1454
|
query, cookies, requestHeaders) {
|
1455
|
-
const ensureRes = await this.ensureInitialized("getTree", cookies);
|
1455
|
+
const ensureRes = await debugTiming("ensureInitialized", () => this.ensureInitialized("getTree", cookies));
|
1456
1456
|
if (fp.result.isErr(ensureRes)) {
|
1457
1457
|
return ensureRes.error;
|
1458
1458
|
}
|
@@ -1460,7 +1460,7 @@ class ValServer {
|
|
1460
1460
|
const execValidations = query.validate === "true";
|
1461
1461
|
const includeSource = query.source === "true";
|
1462
1462
|
const includeSchema = query.schema === "true";
|
1463
|
-
const moduleIds = await this.getAllModules(treePath);
|
1463
|
+
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
1464
1464
|
let {
|
1465
1465
|
patchIdsByModuleId,
|
1466
1466
|
patchesById,
|
@@ -1471,7 +1471,7 @@ class ValServer {
|
|
1471
1471
|
fileUpdates: {}
|
1472
1472
|
};
|
1473
1473
|
if (applyPatches) {
|
1474
|
-
const res = await this.readPatches(cookies);
|
1474
|
+
const res = await debugTiming("readPatches", () => this.readPatches(cookies));
|
1475
1475
|
if (fp.result.isErr(res)) {
|
1476
1476
|
return res.error;
|
1477
1477
|
}
|
@@ -1479,9 +1479,9 @@ class ValServer {
|
|
1479
1479
|
patchesById = res.value.patchesById;
|
1480
1480
|
fileUpdates = res.value.fileUpdates;
|
1481
1481
|
}
|
1482
|
-
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1482
|
+
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1483
1483
|
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, execValidations, includeSource, includeSchema);
|
1484
|
-
}));
|
1484
|
+
})));
|
1485
1485
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1486
1486
|
const module = {
|
1487
1487
|
schema: serializedModuleContent.schema,
|
@@ -1551,38 +1551,40 @@ class ValServer {
|
|
1551
1551
|
return serializedModuleContent;
|
1552
1552
|
}
|
1553
1553
|
let source = maybeSource;
|
1554
|
-
|
1555
|
-
const
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1554
|
+
await debugTiming("applyPatches:" + moduleId, async () => {
|
1555
|
+
for (const patchId of patchIdsByModuleId[moduleId] ?? []) {
|
1556
|
+
const patch$1 = patchesById[patchId];
|
1557
|
+
if (!patch$1) {
|
1558
|
+
continue;
|
1559
|
+
}
|
1560
|
+
const patchRes = patch.applyPatch(source, ops, patch$1.filter(core.Internal.notFileOp));
|
1561
|
+
if (fp.result.isOk(patchRes)) {
|
1562
|
+
source = patchRes.value;
|
1563
|
+
} else {
|
1564
|
+
console.error("Val: got an unexpected error while applying patch. Is there a mismatch in Val versions? Perhaps Val is misconfigured?", {
|
1565
|
+
patchId,
|
1566
|
+
moduleId,
|
1567
|
+
patch: JSON.stringify(patch$1, null, 2),
|
1568
|
+
error: patchRes.error
|
1569
|
+
});
|
1570
|
+
return {
|
1571
|
+
path: moduleId,
|
1572
|
+
schema,
|
1573
|
+
source,
|
1574
|
+
errors: {
|
1575
|
+
fatal: [{
|
1576
|
+
message: "Unexpected error applying patch",
|
1577
|
+
type: "invalid-patch"
|
1578
|
+
}]
|
1579
|
+
}
|
1580
|
+
};
|
1581
|
+
}
|
1580
1582
|
}
|
1581
|
-
}
|
1583
|
+
});
|
1582
1584
|
if (validate) {
|
1583
|
-
const validationErrors = core.deserializeSchema(schema).validate(moduleId, source);
|
1585
|
+
const validationErrors = await debugTiming("validate:" + moduleId, async () => core.deserializeSchema(schema).validate(moduleId, source));
|
1584
1586
|
if (validationErrors) {
|
1585
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1587
|
+
const revalidated = await debugTiming("revalidate image/file:" + moduleId, async () => this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders));
|
1586
1588
|
return {
|
1587
1589
|
path: moduleId,
|
1588
1590
|
schema,
|
@@ -2034,6 +2036,16 @@ function guessMimeTypeFromPath(filePath) {
|
|
2034
2036
|
function isCachedPatchFileOp(op) {
|
2035
2037
|
return !!(op.op === "file" && typeof op.filePath === "string" && op.value && typeof op.value === "object" && !Array.isArray(op.value) && "sha256" in op.value && typeof op.value.sha256 === "string");
|
2036
2038
|
}
|
2039
|
+
async function debugTiming(id, fn) {
|
2040
|
+
if (process.env["VAL_DEBUG_TIMING"] === "true") {
|
2041
|
+
const start = Date.now();
|
2042
|
+
const r = await fn();
|
2043
|
+
console.log(`Timing: ${id} took: ${Date.now() - start}ms (${new Date().toISOString()})`);
|
2044
|
+
return r;
|
2045
|
+
} else {
|
2046
|
+
return fn();
|
2047
|
+
}
|
2048
|
+
}
|
2037
2049
|
|
2038
2050
|
const textEncoder = new TextEncoder();
|
2039
2051
|
class LocalValServer extends ValServer {
|
@@ -2824,76 +2836,51 @@ class ProxyValServer extends ValServer {
|
|
2824
2836
|
}
|
2825
2837
|
});
|
2826
2838
|
}
|
2827
|
-
async getFiles(filePath, query,
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2839
|
+
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2840
|
+
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2841
|
+
if (typeof query.sha256 === "string") {
|
2842
|
+
url.searchParams.append("sha256", query.sha256);
|
2843
|
+
}
|
2844
|
+
const fetchRes = await fetch(url);
|
2845
|
+
if (fetchRes.status === 200) {
|
2846
|
+
// TODO: does this stream data?
|
2847
|
+
if (fetchRes.body) {
|
2848
|
+
return {
|
2849
|
+
status: fetchRes.status,
|
2850
|
+
headers: {
|
2851
|
+
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2852
|
+
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2853
|
+
"Cache-Control": fetchRes.headers.get("Cache-Control") || ""
|
2854
|
+
},
|
2855
|
+
body: fetchRes.body
|
2856
|
+
};
|
2832
2857
|
} else {
|
2833
|
-
|
2858
|
+
return {
|
2859
|
+
status: 500,
|
2860
|
+
json: {
|
2861
|
+
message: "No body in response"
|
2862
|
+
}
|
2863
|
+
};
|
2834
2864
|
}
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
return {
|
2842
|
-
status: fetchRes.status,
|
2843
|
-
headers: {
|
2844
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2845
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2846
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2847
|
-
},
|
2848
|
-
body: fetchRes.body
|
2849
|
-
};
|
2850
|
-
} else {
|
2851
|
-
return {
|
2852
|
-
status: 500,
|
2853
|
-
json: {
|
2854
|
-
message: "No body in response"
|
2855
|
-
}
|
2856
|
-
};
|
2857
|
-
}
|
2858
|
-
} else {
|
2859
|
-
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2860
|
-
return {
|
2861
|
-
status: 500,
|
2862
|
-
json: {
|
2863
|
-
message: "Missing host or x-forwarded-proto header"
|
2864
|
-
}
|
2865
|
-
};
|
2866
|
-
}
|
2867
|
-
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2868
|
-
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2869
|
-
const fetchRes = await fetch(staticPublicUrl, {
|
2870
|
-
headers: getAuthHeaders(data.token)
|
2871
|
-
});
|
2872
|
-
if (fetchRes.status === 200) {
|
2873
|
-
// TODO: does this stream data?
|
2874
|
-
if (fetchRes.body) {
|
2875
|
-
return {
|
2876
|
-
status: fetchRes.status,
|
2877
|
-
headers: {
|
2878
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2879
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2880
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2881
|
-
},
|
2882
|
-
body: fetchRes.body
|
2883
|
-
};
|
2884
|
-
} else {
|
2885
|
-
return {
|
2886
|
-
status: 500,
|
2887
|
-
json: {
|
2888
|
-
message: "No body in response"
|
2889
|
-
}
|
2890
|
-
};
|
2865
|
+
} else {
|
2866
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2867
|
+
return {
|
2868
|
+
status: 500,
|
2869
|
+
json: {
|
2870
|
+
message: "Missing host or x-forwarded-proto header"
|
2891
2871
|
}
|
2892
|
-
}
|
2893
|
-
throw new Error("Failed to fetch file: " + filePath);
|
2894
|
-
}
|
2872
|
+
};
|
2895
2873
|
}
|
2896
|
-
|
2874
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2875
|
+
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2876
|
+
const fetchRes = await fetch(staticPublicUrl);
|
2877
|
+
return {
|
2878
|
+
status: fetchRes.status,
|
2879
|
+
// forward headers from static public url
|
2880
|
+
headers: Object.fromEntries(fetchRes.headers.entries()),
|
2881
|
+
body: fetchRes.body
|
2882
|
+
};
|
2883
|
+
}
|
2897
2884
|
}
|
2898
2885
|
}
|
2899
2886
|
function verifyCallbackReq(stateCookie, queryParams) {
|
@@ -1422,7 +1422,7 @@ class ValServer {
|
|
1422
1422
|
async getTree(treePath,
|
1423
1423
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1424
1424
|
query, cookies, requestHeaders) {
|
1425
|
-
const ensureRes = await this.ensureInitialized("getTree", cookies);
|
1425
|
+
const ensureRes = await debugTiming("ensureInitialized", () => this.ensureInitialized("getTree", cookies));
|
1426
1426
|
if (result.isErr(ensureRes)) {
|
1427
1427
|
return ensureRes.error;
|
1428
1428
|
}
|
@@ -1430,7 +1430,7 @@ class ValServer {
|
|
1430
1430
|
const execValidations = query.validate === "true";
|
1431
1431
|
const includeSource = query.source === "true";
|
1432
1432
|
const includeSchema = query.schema === "true";
|
1433
|
-
const moduleIds = await this.getAllModules(treePath);
|
1433
|
+
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
1434
1434
|
let {
|
1435
1435
|
patchIdsByModuleId,
|
1436
1436
|
patchesById,
|
@@ -1441,7 +1441,7 @@ class ValServer {
|
|
1441
1441
|
fileUpdates: {}
|
1442
1442
|
};
|
1443
1443
|
if (applyPatches) {
|
1444
|
-
const res = await this.readPatches(cookies);
|
1444
|
+
const res = await debugTiming("readPatches", () => this.readPatches(cookies));
|
1445
1445
|
if (result.isErr(res)) {
|
1446
1446
|
return res.error;
|
1447
1447
|
}
|
@@ -1449,9 +1449,9 @@ class ValServer {
|
|
1449
1449
|
patchesById = res.value.patchesById;
|
1450
1450
|
fileUpdates = res.value.fileUpdates;
|
1451
1451
|
}
|
1452
|
-
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1452
|
+
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1453
1453
|
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, execValidations, includeSource, includeSchema);
|
1454
|
-
}));
|
1454
|
+
})));
|
1455
1455
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1456
1456
|
const module = {
|
1457
1457
|
schema: serializedModuleContent.schema,
|
@@ -1521,38 +1521,40 @@ class ValServer {
|
|
1521
1521
|
return serializedModuleContent;
|
1522
1522
|
}
|
1523
1523
|
let source = maybeSource;
|
1524
|
-
|
1525
|
-
const
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1524
|
+
await debugTiming("applyPatches:" + moduleId, async () => {
|
1525
|
+
for (const patchId of patchIdsByModuleId[moduleId] ?? []) {
|
1526
|
+
const patch = patchesById[patchId];
|
1527
|
+
if (!patch) {
|
1528
|
+
continue;
|
1529
|
+
}
|
1530
|
+
const patchRes = applyPatch(source, ops, patch.filter(Internal.notFileOp));
|
1531
|
+
if (result.isOk(patchRes)) {
|
1532
|
+
source = patchRes.value;
|
1533
|
+
} else {
|
1534
|
+
console.error("Val: got an unexpected error while applying patch. Is there a mismatch in Val versions? Perhaps Val is misconfigured?", {
|
1535
|
+
patchId,
|
1536
|
+
moduleId,
|
1537
|
+
patch: JSON.stringify(patch, null, 2),
|
1538
|
+
error: patchRes.error
|
1539
|
+
});
|
1540
|
+
return {
|
1541
|
+
path: moduleId,
|
1542
|
+
schema,
|
1543
|
+
source,
|
1544
|
+
errors: {
|
1545
|
+
fatal: [{
|
1546
|
+
message: "Unexpected error applying patch",
|
1547
|
+
type: "invalid-patch"
|
1548
|
+
}]
|
1549
|
+
}
|
1550
|
+
};
|
1551
|
+
}
|
1550
1552
|
}
|
1551
|
-
}
|
1553
|
+
});
|
1552
1554
|
if (validate) {
|
1553
|
-
const validationErrors = deserializeSchema(schema).validate(moduleId, source);
|
1555
|
+
const validationErrors = await debugTiming("validate:" + moduleId, async () => deserializeSchema(schema).validate(moduleId, source));
|
1554
1556
|
if (validationErrors) {
|
1555
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1557
|
+
const revalidated = await debugTiming("revalidate image/file:" + moduleId, async () => this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders));
|
1556
1558
|
return {
|
1557
1559
|
path: moduleId,
|
1558
1560
|
schema,
|
@@ -2004,6 +2006,16 @@ function guessMimeTypeFromPath(filePath) {
|
|
2004
2006
|
function isCachedPatchFileOp(op) {
|
2005
2007
|
return !!(op.op === "file" && typeof op.filePath === "string" && op.value && typeof op.value === "object" && !Array.isArray(op.value) && "sha256" in op.value && typeof op.value.sha256 === "string");
|
2006
2008
|
}
|
2009
|
+
async function debugTiming(id, fn) {
|
2010
|
+
if (process.env["VAL_DEBUG_TIMING"] === "true") {
|
2011
|
+
const start = Date.now();
|
2012
|
+
const r = await fn();
|
2013
|
+
console.log(`Timing: ${id} took: ${Date.now() - start}ms (${new Date().toISOString()})`);
|
2014
|
+
return r;
|
2015
|
+
} else {
|
2016
|
+
return fn();
|
2017
|
+
}
|
2018
|
+
}
|
2007
2019
|
|
2008
2020
|
const textEncoder = new TextEncoder();
|
2009
2021
|
class LocalValServer extends ValServer {
|
@@ -2794,76 +2806,51 @@ class ProxyValServer extends ValServer {
|
|
2794
2806
|
}
|
2795
2807
|
});
|
2796
2808
|
}
|
2797
|
-
async getFiles(filePath, query,
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2809
|
+
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2810
|
+
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2811
|
+
if (typeof query.sha256 === "string") {
|
2812
|
+
url.searchParams.append("sha256", query.sha256);
|
2813
|
+
}
|
2814
|
+
const fetchRes = await fetch(url);
|
2815
|
+
if (fetchRes.status === 200) {
|
2816
|
+
// TODO: does this stream data?
|
2817
|
+
if (fetchRes.body) {
|
2818
|
+
return {
|
2819
|
+
status: fetchRes.status,
|
2820
|
+
headers: {
|
2821
|
+
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2822
|
+
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2823
|
+
"Cache-Control": fetchRes.headers.get("Cache-Control") || ""
|
2824
|
+
},
|
2825
|
+
body: fetchRes.body
|
2826
|
+
};
|
2802
2827
|
} else {
|
2803
|
-
|
2828
|
+
return {
|
2829
|
+
status: 500,
|
2830
|
+
json: {
|
2831
|
+
message: "No body in response"
|
2832
|
+
}
|
2833
|
+
};
|
2804
2834
|
}
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
return {
|
2812
|
-
status: fetchRes.status,
|
2813
|
-
headers: {
|
2814
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2815
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2816
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2817
|
-
},
|
2818
|
-
body: fetchRes.body
|
2819
|
-
};
|
2820
|
-
} else {
|
2821
|
-
return {
|
2822
|
-
status: 500,
|
2823
|
-
json: {
|
2824
|
-
message: "No body in response"
|
2825
|
-
}
|
2826
|
-
};
|
2827
|
-
}
|
2828
|
-
} else {
|
2829
|
-
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2830
|
-
return {
|
2831
|
-
status: 500,
|
2832
|
-
json: {
|
2833
|
-
message: "Missing host or x-forwarded-proto header"
|
2834
|
-
}
|
2835
|
-
};
|
2836
|
-
}
|
2837
|
-
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2838
|
-
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2839
|
-
const fetchRes = await fetch(staticPublicUrl, {
|
2840
|
-
headers: getAuthHeaders(data.token)
|
2841
|
-
});
|
2842
|
-
if (fetchRes.status === 200) {
|
2843
|
-
// TODO: does this stream data?
|
2844
|
-
if (fetchRes.body) {
|
2845
|
-
return {
|
2846
|
-
status: fetchRes.status,
|
2847
|
-
headers: {
|
2848
|
-
"Content-Type": fetchRes.headers.get("Content-Type") || "",
|
2849
|
-
"Content-Length": fetchRes.headers.get("Content-Length") || "0",
|
2850
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2851
|
-
},
|
2852
|
-
body: fetchRes.body
|
2853
|
-
};
|
2854
|
-
} else {
|
2855
|
-
return {
|
2856
|
-
status: 500,
|
2857
|
-
json: {
|
2858
|
-
message: "No body in response"
|
2859
|
-
}
|
2860
|
-
};
|
2835
|
+
} else {
|
2836
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2837
|
+
return {
|
2838
|
+
status: 500,
|
2839
|
+
json: {
|
2840
|
+
message: "Missing host or x-forwarded-proto header"
|
2861
2841
|
}
|
2862
|
-
}
|
2863
|
-
throw new Error("Failed to fetch file: " + filePath);
|
2864
|
-
}
|
2842
|
+
};
|
2865
2843
|
}
|
2866
|
-
|
2844
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2845
|
+
const staticPublicUrl = new URL(filePath.slice("/public".length), host).toString();
|
2846
|
+
const fetchRes = await fetch(staticPublicUrl);
|
2847
|
+
return {
|
2848
|
+
status: fetchRes.status,
|
2849
|
+
// forward headers from static public url
|
2850
|
+
headers: Object.fromEntries(fetchRes.headers.entries()),
|
2851
|
+
body: fetchRes.body
|
2852
|
+
};
|
2853
|
+
}
|
2867
2854
|
}
|
2868
2855
|
}
|
2869
2856
|
function verifyCallbackReq(stateCookie, queryParams) {
|
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.60.
|
15
|
+
"version": "0.60.23",
|
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.60.
|
28
|
-
"@valbuild/shared": "~0.60.
|
29
|
-
"@valbuild/ui": "~0.60.
|
27
|
+
"@valbuild/core": "~0.60.23",
|
28
|
+
"@valbuild/shared": "~0.60.23",
|
29
|
+
"@valbuild/ui": "~0.60.23",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"minimatch": "^3.0.4",
|