@valbuild/server 0.60.16 → 0.60.17
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.
@@ -32,9 +32,9 @@ export declare abstract class ValServer implements IValServer {
|
|
32
32
|
patch?: string;
|
33
33
|
schema?: string;
|
34
34
|
source?: string;
|
35
|
-
}, cookies: ValCookies<VAL_SESSION_COOKIE
|
36
|
-
postValidate(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE
|
37
|
-
postCommit(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE
|
35
|
+
}, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiTreeResponse>>;
|
36
|
+
postValidate(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiPostValidationResponse | ApiPostValidationErrorResponse>>;
|
37
|
+
postCommit(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiCommitResponse, ApiPostValidationErrorResponse>>;
|
38
38
|
private applyAllPatchesThenValidate;
|
39
39
|
private revalidateImageAndFileValidation;
|
40
40
|
protected sortPatchIds(patchesByModule: Record<ModuleId, {
|
@@ -69,7 +69,7 @@ export declare abstract class ValServer implements IValServer {
|
|
69
69
|
} | ValServerError>;
|
70
70
|
abstract getFiles(filePath: string, query: {
|
71
71
|
sha256?: string;
|
72
|
-
}, cookies: ValCookies<VAL_SESSION_COOKIE
|
72
|
+
}, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerResult<never, ReadableStream<Uint8Array>> | ValServerRedirectResult<VAL_ENABLE_COOKIE_NAME>>;
|
73
73
|
abstract session(cookies: ValCookies<VAL_SESSION_COOKIE>): Promise<ValServerJsonResult<ValSession>>;
|
74
74
|
abstract authorize(query: {
|
75
75
|
redirect_to?: string;
|
@@ -129,7 +129,7 @@ export interface IValServer {
|
|
129
129
|
patch?: string;
|
130
130
|
schema?: string;
|
131
131
|
source?: string;
|
132
|
-
}, cookies: ValCookies<VAL_SESSION_COOKIE
|
132
|
+
}, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiTreeResponse>>;
|
133
133
|
getPatches(query: {
|
134
134
|
id?: string[];
|
135
135
|
}, cookies: ValCookies<VAL_SESSION_COOKIE>): Promise<ValServerJsonResult<ApiGetPatchResponse>>;
|
@@ -137,11 +137,11 @@ export interface IValServer {
|
|
137
137
|
deletePatches(query: {
|
138
138
|
id?: string[];
|
139
139
|
}, cookies: ValCookies<VAL_SESSION_COOKIE>): Promise<ValServerJsonResult<ApiDeletePatchResponse>>;
|
140
|
-
postValidate(body: unknown, cookies: ValCookies<VAL_SESSION_COOKIE
|
141
|
-
postCommit(body: unknown, cookies: ValCookies<VAL_SESSION_COOKIE
|
140
|
+
postValidate(body: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiPostValidationResponse | ApiPostValidationErrorResponse>>;
|
141
|
+
postCommit(body: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiCommitResponse, ApiPostValidationErrorResponse>>;
|
142
142
|
getFiles(filePath: string, query: {
|
143
143
|
sha256?: string;
|
144
|
-
}, cookies: ValCookies<VAL_SESSION_COOKIE
|
144
|
+
}, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerResult<never, ReadableStream<Uint8Array>> | ValServerRedirectResult<VAL_ENABLE_COOKIE_NAME>>;
|
145
145
|
}
|
146
146
|
export declare function guessMimeTypeFromPath(filePath: string): string | null;
|
147
147
|
export declare function isCachedPatchFileOp(op: Operation): op is {
|
@@ -152,3 +152,7 @@ export declare function isCachedPatchFileOp(op: Operation): op is {
|
|
152
152
|
sha256: string;
|
153
153
|
};
|
154
154
|
};
|
155
|
+
export type RequestHeaders = {
|
156
|
+
host?: string | null;
|
157
|
+
"x-forwarded-proto"?: string | null;
|
158
|
+
};
|
@@ -1032,7 +1032,7 @@ export const IS_DEV = false;
|
|
1032
1032
|
}
|
1033
1033
|
if (modulePath.startsWith("react/jsx-runtime")) {
|
1034
1034
|
return {
|
1035
|
-
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1035
|
+
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export const Fragment = () => { throw Error(`Cannot use 'Fragment' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1036
1036
|
};
|
1037
1037
|
}
|
1038
1038
|
if (modulePath.startsWith("react")) {
|
@@ -1419,7 +1419,7 @@ class ValServer {
|
|
1419
1419
|
}
|
1420
1420
|
async getTree(treePath,
|
1421
1421
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1422
|
-
query, cookies) {
|
1422
|
+
query, cookies, requestHeaders) {
|
1423
1423
|
const ensureRes = await this.ensureRemoteFSInitialized("getTree", cookies);
|
1424
1424
|
if (fp.result.isErr(ensureRes)) {
|
1425
1425
|
return ensureRes.error;
|
@@ -1445,7 +1445,7 @@ class ValServer {
|
|
1445
1445
|
fileUpdates = res.value.fileUpdates;
|
1446
1446
|
}
|
1447
1447
|
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1448
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies);
|
1448
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders);
|
1449
1449
|
}));
|
1450
1450
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1451
1451
|
const module = {
|
@@ -1464,19 +1464,19 @@ class ValServer {
|
|
1464
1464
|
json: apiTreeResponse
|
1465
1465
|
};
|
1466
1466
|
}
|
1467
|
-
async postValidate(rawBody, cookies) {
|
1467
|
+
async postValidate(rawBody, cookies, requestHeaders) {
|
1468
1468
|
const ensureRes = await this.ensureRemoteFSInitialized("postValidate", cookies);
|
1469
1469
|
if (fp.result.isErr(ensureRes)) {
|
1470
1470
|
return ensureRes.error;
|
1471
1471
|
}
|
1472
|
-
return this.validateThenMaybeCommit(rawBody, false, cookies);
|
1472
|
+
return this.validateThenMaybeCommit(rawBody, false, cookies, requestHeaders);
|
1473
1473
|
}
|
1474
|
-
async postCommit(rawBody, cookies) {
|
1474
|
+
async postCommit(rawBody, cookies, requestHeaders) {
|
1475
1475
|
const ensureRes = await this.ensureRemoteFSInitialized("postCommit", cookies);
|
1476
1476
|
if (fp.result.isErr(ensureRes)) {
|
1477
1477
|
return ensureRes.error;
|
1478
1478
|
}
|
1479
|
-
const res = await this.validateThenMaybeCommit(rawBody, true, cookies);
|
1479
|
+
const res = await this.validateThenMaybeCommit(rawBody, true, cookies, requestHeaders);
|
1480
1480
|
if (res.status === 200) {
|
1481
1481
|
if (res.json.validationErrors) {
|
1482
1482
|
return {
|
@@ -1499,7 +1499,7 @@ class ValServer {
|
|
1499
1499
|
|
1500
1500
|
/* */
|
1501
1501
|
|
1502
|
-
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies) {
|
1502
|
+
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders) {
|
1503
1503
|
const serializedModuleContent = await this.getModule(moduleId);
|
1504
1504
|
const schema = serializedModuleContent.schema;
|
1505
1505
|
const maybeSource = serializedModuleContent.source;
|
@@ -1543,7 +1543,7 @@ class ValServer {
|
|
1543
1543
|
}
|
1544
1544
|
const validationErrors = core.deserializeSchema(schema).validate(moduleId, source);
|
1545
1545
|
if (validationErrors) {
|
1546
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies);
|
1546
|
+
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1547
1547
|
return {
|
1548
1548
|
path: moduleId,
|
1549
1549
|
schema,
|
@@ -1566,7 +1566,7 @@ class ValServer {
|
|
1566
1566
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
1567
1567
|
// which does not have access to the filesystem, at least not at the time of writing this comment.
|
1568
1568
|
// If you are reading this, and we still are not using QuickJS to validate, this assumption might be wrong.
|
1569
|
-
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies) {
|
1569
|
+
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders) {
|
1570
1570
|
const revalidatedValidationErrors = {};
|
1571
1571
|
for (const pathStr in validationErrors) {
|
1572
1572
|
const errorSourcePath = pathStr;
|
@@ -1588,7 +1588,7 @@ class ValServer {
|
|
1588
1588
|
if (updatedFileMetadata) {
|
1589
1589
|
const fileRes = await this.getFiles(fileRef, {
|
1590
1590
|
sha256: updatedFileMetadata.sha256
|
1591
|
-
}, cookies);
|
1591
|
+
}, cookies, requestHeaders);
|
1592
1592
|
if (fileRes.status === 200 && fileRes.body) {
|
1593
1593
|
const res = new Response(fileRes.body);
|
1594
1594
|
fileBuffer = Buffer.from(await res.arrayBuffer());
|
@@ -1724,7 +1724,7 @@ class ValServer {
|
|
1724
1724
|
});
|
1725
1725
|
}
|
1726
1726
|
}
|
1727
|
-
async validateThenMaybeCommit(rawBody, commit, cookies) {
|
1727
|
+
async validateThenMaybeCommit(rawBody, commit, cookies, requestHeaders) {
|
1728
1728
|
const filterPatchesByModuleIdRes = z.z.object({
|
1729
1729
|
patches: z.z.record(z.z.array(z.z.string())).optional()
|
1730
1730
|
}).safeParse(rawBody);
|
@@ -1752,7 +1752,7 @@ class ValServer {
|
|
1752
1752
|
const moduleId = moduleIdStr;
|
1753
1753
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1754
1754
|
// TODO: refine to ModuleId and PatchId when parsing
|
1755
|
-
patchIdsByModuleId, patchesById, fileUpdates, true, cookies);
|
1755
|
+
patchIdsByModuleId, patchesById, fileUpdates, true, cookies, requestHeaders);
|
1756
1756
|
if (serializedModuleContent.errors) {
|
1757
1757
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1758
1758
|
}
|
@@ -2970,7 +2970,7 @@ class ProxyValServer extends ValServer {
|
|
2970
2970
|
}
|
2971
2971
|
});
|
2972
2972
|
}
|
2973
|
-
async getFiles(filePath, query, cookies) {
|
2973
|
+
async getFiles(filePath, query, cookies, reqHeaders) {
|
2974
2974
|
return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
|
2975
2975
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2976
2976
|
if (typeof query.sha256 === "string") {
|
@@ -3002,41 +3002,19 @@ class ProxyValServer extends ValServer {
|
|
3002
3002
|
};
|
3003
3003
|
}
|
3004
3004
|
} else {
|
3005
|
-
|
3006
|
-
let buffer;
|
3007
|
-
if (fileExists) {
|
3008
|
-
buffer = await this.readStaticBinaryFile(path__namespace["default"].join(this.cwd, filePath));
|
3009
|
-
}
|
3010
|
-
if (!buffer) {
|
3005
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
3011
3006
|
return {
|
3012
|
-
status:
|
3007
|
+
status: 500,
|
3013
3008
|
json: {
|
3014
|
-
message: "
|
3009
|
+
message: "Missing host or x-forwarded-proto header"
|
3015
3010
|
}
|
3016
3011
|
};
|
3017
3012
|
}
|
3018
|
-
const
|
3019
|
-
|
3020
|
-
const sha256 = getSha256(mimeType, buffer);
|
3021
|
-
if (sha256 === query.sha256) {
|
3022
|
-
return {
|
3023
|
-
status: 200,
|
3024
|
-
headers: {
|
3025
|
-
"Content-Type": mimeType,
|
3026
|
-
"Content-Length": buffer.byteLength.toString(),
|
3027
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
3028
|
-
},
|
3029
|
-
body: bufferToReadableStream(buffer)
|
3030
|
-
};
|
3031
|
-
}
|
3032
|
-
}
|
3013
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
3014
|
+
const fileUrl = filePath.slice("/public".length);
|
3033
3015
|
return {
|
3034
|
-
status:
|
3035
|
-
|
3036
|
-
"Content-Type": mimeType,
|
3037
|
-
"Content-Length": buffer.byteLength.toString()
|
3038
|
-
},
|
3039
|
-
body: bufferToReadableStream(buffer)
|
3016
|
+
status: 302,
|
3017
|
+
redirectTo: new URL(fileUrl, host).toString()
|
3040
3018
|
};
|
3041
3019
|
}
|
3042
3020
|
});
|
@@ -3359,8 +3337,10 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3359
3337
|
return async req => {
|
3360
3338
|
var _req$method;
|
3361
3339
|
const valServer = await valServerPromise;
|
3362
|
-
|
3363
|
-
|
3340
|
+
const requestHeaders = {
|
3341
|
+
host: req.headers.get("host"),
|
3342
|
+
"x-forwarded-proto": req.headers.get("x-forwarded-proto")
|
3343
|
+
};
|
3364
3344
|
const url = new URL(req.url);
|
3365
3345
|
if (!url.pathname.startsWith(route)) {
|
3366
3346
|
const error = {
|
@@ -3423,16 +3403,16 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3423
3403
|
}));
|
3424
3404
|
} else if (method === "POST" && path === "/commit") {
|
3425
3405
|
const body = await req.json();
|
3426
|
-
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3406
|
+
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3427
3407
|
} else if (method === "POST" && path === "/validate") {
|
3428
3408
|
const body = await req.json();
|
3429
|
-
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3409
|
+
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3430
3410
|
} else if (method === "GET" && path.startsWith(TREE_PATH_PREFIX)) {
|
3431
3411
|
return withTreePath(path, TREE_PATH_PREFIX)(async treePath => convert(await valServer.getTree(treePath, {
|
3432
3412
|
patch: url.searchParams.get("patch") || undefined,
|
3433
3413
|
schema: url.searchParams.get("schema") || undefined,
|
3434
3414
|
source: url.searchParams.get("source") || undefined
|
3435
|
-
}, getCookies(req, [VAL_SESSION_COOKIE]))));
|
3415
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders)));
|
3436
3416
|
} else if (method === "GET" && path.startsWith(PATCHES_PATH_PREFIX)) {
|
3437
3417
|
return withTreePath(path, PATCHES_PATH_PREFIX)(async () => convert(await valServer.getPatches({
|
3438
3418
|
id: url.searchParams.getAll("id")
|
@@ -3448,7 +3428,7 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3448
3428
|
const treePath = path.slice(FILES_PATH_PREFIX.length);
|
3449
3429
|
return convert(await valServer.getFiles(treePath, {
|
3450
3430
|
sha256: url.searchParams.get("sha256") || undefined
|
3451
|
-
}, getCookies(req, [VAL_SESSION_COOKIE])));
|
3431
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3452
3432
|
} else {
|
3453
3433
|
return convert({
|
3454
3434
|
status: 404,
|
@@ -1032,7 +1032,7 @@ export const IS_DEV = false;
|
|
1032
1032
|
}
|
1033
1033
|
if (modulePath.startsWith("react/jsx-runtime")) {
|
1034
1034
|
return {
|
1035
|
-
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1035
|
+
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export const Fragment = () => { throw Error(`Cannot use 'Fragment' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1036
1036
|
};
|
1037
1037
|
}
|
1038
1038
|
if (modulePath.startsWith("react")) {
|
@@ -1419,7 +1419,7 @@ class ValServer {
|
|
1419
1419
|
}
|
1420
1420
|
async getTree(treePath,
|
1421
1421
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1422
|
-
query, cookies) {
|
1422
|
+
query, cookies, requestHeaders) {
|
1423
1423
|
const ensureRes = await this.ensureRemoteFSInitialized("getTree", cookies);
|
1424
1424
|
if (fp.result.isErr(ensureRes)) {
|
1425
1425
|
return ensureRes.error;
|
@@ -1445,7 +1445,7 @@ class ValServer {
|
|
1445
1445
|
fileUpdates = res.value.fileUpdates;
|
1446
1446
|
}
|
1447
1447
|
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1448
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies);
|
1448
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders);
|
1449
1449
|
}));
|
1450
1450
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1451
1451
|
const module = {
|
@@ -1464,19 +1464,19 @@ class ValServer {
|
|
1464
1464
|
json: apiTreeResponse
|
1465
1465
|
};
|
1466
1466
|
}
|
1467
|
-
async postValidate(rawBody, cookies) {
|
1467
|
+
async postValidate(rawBody, cookies, requestHeaders) {
|
1468
1468
|
const ensureRes = await this.ensureRemoteFSInitialized("postValidate", cookies);
|
1469
1469
|
if (fp.result.isErr(ensureRes)) {
|
1470
1470
|
return ensureRes.error;
|
1471
1471
|
}
|
1472
|
-
return this.validateThenMaybeCommit(rawBody, false, cookies);
|
1472
|
+
return this.validateThenMaybeCommit(rawBody, false, cookies, requestHeaders);
|
1473
1473
|
}
|
1474
|
-
async postCommit(rawBody, cookies) {
|
1474
|
+
async postCommit(rawBody, cookies, requestHeaders) {
|
1475
1475
|
const ensureRes = await this.ensureRemoteFSInitialized("postCommit", cookies);
|
1476
1476
|
if (fp.result.isErr(ensureRes)) {
|
1477
1477
|
return ensureRes.error;
|
1478
1478
|
}
|
1479
|
-
const res = await this.validateThenMaybeCommit(rawBody, true, cookies);
|
1479
|
+
const res = await this.validateThenMaybeCommit(rawBody, true, cookies, requestHeaders);
|
1480
1480
|
if (res.status === 200) {
|
1481
1481
|
if (res.json.validationErrors) {
|
1482
1482
|
return {
|
@@ -1499,7 +1499,7 @@ class ValServer {
|
|
1499
1499
|
|
1500
1500
|
/* */
|
1501
1501
|
|
1502
|
-
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies) {
|
1502
|
+
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders) {
|
1503
1503
|
const serializedModuleContent = await this.getModule(moduleId);
|
1504
1504
|
const schema = serializedModuleContent.schema;
|
1505
1505
|
const maybeSource = serializedModuleContent.source;
|
@@ -1543,7 +1543,7 @@ class ValServer {
|
|
1543
1543
|
}
|
1544
1544
|
const validationErrors = core.deserializeSchema(schema).validate(moduleId, source);
|
1545
1545
|
if (validationErrors) {
|
1546
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies);
|
1546
|
+
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1547
1547
|
return {
|
1548
1548
|
path: moduleId,
|
1549
1549
|
schema,
|
@@ -1566,7 +1566,7 @@ class ValServer {
|
|
1566
1566
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
1567
1567
|
// which does not have access to the filesystem, at least not at the time of writing this comment.
|
1568
1568
|
// If you are reading this, and we still are not using QuickJS to validate, this assumption might be wrong.
|
1569
|
-
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies) {
|
1569
|
+
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders) {
|
1570
1570
|
const revalidatedValidationErrors = {};
|
1571
1571
|
for (const pathStr in validationErrors) {
|
1572
1572
|
const errorSourcePath = pathStr;
|
@@ -1588,7 +1588,7 @@ class ValServer {
|
|
1588
1588
|
if (updatedFileMetadata) {
|
1589
1589
|
const fileRes = await this.getFiles(fileRef, {
|
1590
1590
|
sha256: updatedFileMetadata.sha256
|
1591
|
-
}, cookies);
|
1591
|
+
}, cookies, requestHeaders);
|
1592
1592
|
if (fileRes.status === 200 && fileRes.body) {
|
1593
1593
|
const res = new Response(fileRes.body);
|
1594
1594
|
fileBuffer = Buffer.from(await res.arrayBuffer());
|
@@ -1724,7 +1724,7 @@ class ValServer {
|
|
1724
1724
|
});
|
1725
1725
|
}
|
1726
1726
|
}
|
1727
|
-
async validateThenMaybeCommit(rawBody, commit, cookies) {
|
1727
|
+
async validateThenMaybeCommit(rawBody, commit, cookies, requestHeaders) {
|
1728
1728
|
const filterPatchesByModuleIdRes = z.z.object({
|
1729
1729
|
patches: z.z.record(z.z.array(z.z.string())).optional()
|
1730
1730
|
}).safeParse(rawBody);
|
@@ -1752,7 +1752,7 @@ class ValServer {
|
|
1752
1752
|
const moduleId = moduleIdStr;
|
1753
1753
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1754
1754
|
// TODO: refine to ModuleId and PatchId when parsing
|
1755
|
-
patchIdsByModuleId, patchesById, fileUpdates, true, cookies);
|
1755
|
+
patchIdsByModuleId, patchesById, fileUpdates, true, cookies, requestHeaders);
|
1756
1756
|
if (serializedModuleContent.errors) {
|
1757
1757
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1758
1758
|
}
|
@@ -2970,7 +2970,7 @@ class ProxyValServer extends ValServer {
|
|
2970
2970
|
}
|
2971
2971
|
});
|
2972
2972
|
}
|
2973
|
-
async getFiles(filePath, query, cookies) {
|
2973
|
+
async getFiles(filePath, query, cookies, reqHeaders) {
|
2974
2974
|
return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
|
2975
2975
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2976
2976
|
if (typeof query.sha256 === "string") {
|
@@ -3002,41 +3002,19 @@ class ProxyValServer extends ValServer {
|
|
3002
3002
|
};
|
3003
3003
|
}
|
3004
3004
|
} else {
|
3005
|
-
|
3006
|
-
let buffer;
|
3007
|
-
if (fileExists) {
|
3008
|
-
buffer = await this.readStaticBinaryFile(path__namespace["default"].join(this.cwd, filePath));
|
3009
|
-
}
|
3010
|
-
if (!buffer) {
|
3005
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
3011
3006
|
return {
|
3012
|
-
status:
|
3007
|
+
status: 500,
|
3013
3008
|
json: {
|
3014
|
-
message: "
|
3009
|
+
message: "Missing host or x-forwarded-proto header"
|
3015
3010
|
}
|
3016
3011
|
};
|
3017
3012
|
}
|
3018
|
-
const
|
3019
|
-
|
3020
|
-
const sha256 = getSha256(mimeType, buffer);
|
3021
|
-
if (sha256 === query.sha256) {
|
3022
|
-
return {
|
3023
|
-
status: 200,
|
3024
|
-
headers: {
|
3025
|
-
"Content-Type": mimeType,
|
3026
|
-
"Content-Length": buffer.byteLength.toString(),
|
3027
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
3028
|
-
},
|
3029
|
-
body: bufferToReadableStream(buffer)
|
3030
|
-
};
|
3031
|
-
}
|
3032
|
-
}
|
3013
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
3014
|
+
const fileUrl = filePath.slice("/public".length);
|
3033
3015
|
return {
|
3034
|
-
status:
|
3035
|
-
|
3036
|
-
"Content-Type": mimeType,
|
3037
|
-
"Content-Length": buffer.byteLength.toString()
|
3038
|
-
},
|
3039
|
-
body: bufferToReadableStream(buffer)
|
3016
|
+
status: 302,
|
3017
|
+
redirectTo: new URL(fileUrl, host).toString()
|
3040
3018
|
};
|
3041
3019
|
}
|
3042
3020
|
});
|
@@ -3359,8 +3337,10 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3359
3337
|
return async req => {
|
3360
3338
|
var _req$method;
|
3361
3339
|
const valServer = await valServerPromise;
|
3362
|
-
|
3363
|
-
|
3340
|
+
const requestHeaders = {
|
3341
|
+
host: req.headers.get("host"),
|
3342
|
+
"x-forwarded-proto": req.headers.get("x-forwarded-proto")
|
3343
|
+
};
|
3364
3344
|
const url = new URL(req.url);
|
3365
3345
|
if (!url.pathname.startsWith(route)) {
|
3366
3346
|
const error = {
|
@@ -3423,16 +3403,16 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3423
3403
|
}));
|
3424
3404
|
} else if (method === "POST" && path === "/commit") {
|
3425
3405
|
const body = await req.json();
|
3426
|
-
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3406
|
+
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3427
3407
|
} else if (method === "POST" && path === "/validate") {
|
3428
3408
|
const body = await req.json();
|
3429
|
-
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3409
|
+
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3430
3410
|
} else if (method === "GET" && path.startsWith(TREE_PATH_PREFIX)) {
|
3431
3411
|
return withTreePath(path, TREE_PATH_PREFIX)(async treePath => convert(await valServer.getTree(treePath, {
|
3432
3412
|
patch: url.searchParams.get("patch") || undefined,
|
3433
3413
|
schema: url.searchParams.get("schema") || undefined,
|
3434
3414
|
source: url.searchParams.get("source") || undefined
|
3435
|
-
}, getCookies(req, [VAL_SESSION_COOKIE]))));
|
3415
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders)));
|
3436
3416
|
} else if (method === "GET" && path.startsWith(PATCHES_PATH_PREFIX)) {
|
3437
3417
|
return withTreePath(path, PATCHES_PATH_PREFIX)(async () => convert(await valServer.getPatches({
|
3438
3418
|
id: url.searchParams.getAll("id")
|
@@ -3448,7 +3428,7 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3448
3428
|
const treePath = path.slice(FILES_PATH_PREFIX.length);
|
3449
3429
|
return convert(await valServer.getFiles(treePath, {
|
3450
3430
|
sha256: url.searchParams.get("sha256") || undefined
|
3451
|
-
}, getCookies(req, [VAL_SESSION_COOKIE])));
|
3431
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3452
3432
|
} else {
|
3453
3433
|
return convert({
|
3454
3434
|
status: 404,
|
@@ -1001,7 +1001,7 @@ export const IS_DEV = false;
|
|
1001
1001
|
}
|
1002
1002
|
if (modulePath.startsWith("react/jsx-runtime")) {
|
1003
1003
|
return {
|
1004
|
-
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1004
|
+
value: "export const jsx = () => { throw Error(`Cannot use 'jsx' in this type of file`) }; export const Fragment = () => { throw Error(`Cannot use 'Fragment' in this type of file`) }; export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } ); export const jsxs = () => { throw Error(`Cannot use 'jsxs' in this type of file`) };"
|
1005
1005
|
};
|
1006
1006
|
}
|
1007
1007
|
if (modulePath.startsWith("react")) {
|
@@ -1388,7 +1388,7 @@ class ValServer {
|
|
1388
1388
|
}
|
1389
1389
|
async getTree(treePath,
|
1390
1390
|
// TODO: use the params: patch, schema, source now we return everything, every time
|
1391
|
-
query, cookies) {
|
1391
|
+
query, cookies, requestHeaders) {
|
1392
1392
|
const ensureRes = await this.ensureRemoteFSInitialized("getTree", cookies);
|
1393
1393
|
if (result.isErr(ensureRes)) {
|
1394
1394
|
return ensureRes.error;
|
@@ -1414,7 +1414,7 @@ class ValServer {
|
|
1414
1414
|
fileUpdates = res.value.fileUpdates;
|
1415
1415
|
}
|
1416
1416
|
const possiblyPatchedContent = await Promise.all(moduleIds.map(async moduleId => {
|
1417
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies);
|
1417
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders);
|
1418
1418
|
}));
|
1419
1419
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1420
1420
|
const module = {
|
@@ -1433,19 +1433,19 @@ class ValServer {
|
|
1433
1433
|
json: apiTreeResponse
|
1434
1434
|
};
|
1435
1435
|
}
|
1436
|
-
async postValidate(rawBody, cookies) {
|
1436
|
+
async postValidate(rawBody, cookies, requestHeaders) {
|
1437
1437
|
const ensureRes = await this.ensureRemoteFSInitialized("postValidate", cookies);
|
1438
1438
|
if (result.isErr(ensureRes)) {
|
1439
1439
|
return ensureRes.error;
|
1440
1440
|
}
|
1441
|
-
return this.validateThenMaybeCommit(rawBody, false, cookies);
|
1441
|
+
return this.validateThenMaybeCommit(rawBody, false, cookies, requestHeaders);
|
1442
1442
|
}
|
1443
|
-
async postCommit(rawBody, cookies) {
|
1443
|
+
async postCommit(rawBody, cookies, requestHeaders) {
|
1444
1444
|
const ensureRes = await this.ensureRemoteFSInitialized("postCommit", cookies);
|
1445
1445
|
if (result.isErr(ensureRes)) {
|
1446
1446
|
return ensureRes.error;
|
1447
1447
|
}
|
1448
|
-
const res = await this.validateThenMaybeCommit(rawBody, true, cookies);
|
1448
|
+
const res = await this.validateThenMaybeCommit(rawBody, true, cookies, requestHeaders);
|
1449
1449
|
if (res.status === 200) {
|
1450
1450
|
if (res.json.validationErrors) {
|
1451
1451
|
return {
|
@@ -1468,7 +1468,7 @@ class ValServer {
|
|
1468
1468
|
|
1469
1469
|
/* */
|
1470
1470
|
|
1471
|
-
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies) {
|
1471
|
+
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, applyPatches, cookies, requestHeaders) {
|
1472
1472
|
const serializedModuleContent = await this.getModule(moduleId);
|
1473
1473
|
const schema = serializedModuleContent.schema;
|
1474
1474
|
const maybeSource = serializedModuleContent.source;
|
@@ -1512,7 +1512,7 @@ class ValServer {
|
|
1512
1512
|
}
|
1513
1513
|
const validationErrors = deserializeSchema(schema).validate(moduleId, source);
|
1514
1514
|
if (validationErrors) {
|
1515
|
-
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies);
|
1515
|
+
const revalidated = await this.revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders);
|
1516
1516
|
return {
|
1517
1517
|
path: moduleId,
|
1518
1518
|
schema,
|
@@ -1535,7 +1535,7 @@ class ValServer {
|
|
1535
1535
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
1536
1536
|
// which does not have access to the filesystem, at least not at the time of writing this comment.
|
1537
1537
|
// If you are reading this, and we still are not using QuickJS to validate, this assumption might be wrong.
|
1538
|
-
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies) {
|
1538
|
+
async revalidateImageAndFileValidation(validationErrors, fileUpdates, cookies, requestHeaders) {
|
1539
1539
|
const revalidatedValidationErrors = {};
|
1540
1540
|
for (const pathStr in validationErrors) {
|
1541
1541
|
const errorSourcePath = pathStr;
|
@@ -1557,7 +1557,7 @@ class ValServer {
|
|
1557
1557
|
if (updatedFileMetadata) {
|
1558
1558
|
const fileRes = await this.getFiles(fileRef, {
|
1559
1559
|
sha256: updatedFileMetadata.sha256
|
1560
|
-
}, cookies);
|
1560
|
+
}, cookies, requestHeaders);
|
1561
1561
|
if (fileRes.status === 200 && fileRes.body) {
|
1562
1562
|
const res = new Response(fileRes.body);
|
1563
1563
|
fileBuffer = Buffer.from(await res.arrayBuffer());
|
@@ -1693,7 +1693,7 @@ class ValServer {
|
|
1693
1693
|
});
|
1694
1694
|
}
|
1695
1695
|
}
|
1696
|
-
async validateThenMaybeCommit(rawBody, commit, cookies) {
|
1696
|
+
async validateThenMaybeCommit(rawBody, commit, cookies, requestHeaders) {
|
1697
1697
|
const filterPatchesByModuleIdRes = z$1.object({
|
1698
1698
|
patches: z$1.record(z$1.array(z$1.string())).optional()
|
1699
1699
|
}).safeParse(rawBody);
|
@@ -1721,7 +1721,7 @@ class ValServer {
|
|
1721
1721
|
const moduleId = moduleIdStr;
|
1722
1722
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1723
1723
|
// TODO: refine to ModuleId and PatchId when parsing
|
1724
|
-
patchIdsByModuleId, patchesById, fileUpdates, true, cookies);
|
1724
|
+
patchIdsByModuleId, patchesById, fileUpdates, true, cookies, requestHeaders);
|
1725
1725
|
if (serializedModuleContent.errors) {
|
1726
1726
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1727
1727
|
}
|
@@ -2939,7 +2939,7 @@ class ProxyValServer extends ValServer {
|
|
2939
2939
|
}
|
2940
2940
|
});
|
2941
2941
|
}
|
2942
|
-
async getFiles(filePath, query, cookies) {
|
2942
|
+
async getFiles(filePath, query, cookies, reqHeaders) {
|
2943
2943
|
return withAuth(this.options.valSecret, cookies, "getFiles", async data => {
|
2944
2944
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2945
2945
|
if (typeof query.sha256 === "string") {
|
@@ -2971,41 +2971,19 @@ class ProxyValServer extends ValServer {
|
|
2971
2971
|
};
|
2972
2972
|
}
|
2973
2973
|
} else {
|
2974
|
-
|
2975
|
-
let buffer;
|
2976
|
-
if (fileExists) {
|
2977
|
-
buffer = await this.readStaticBinaryFile(path__default.join(this.cwd, filePath));
|
2978
|
-
}
|
2979
|
-
if (!buffer) {
|
2974
|
+
if (!(reqHeaders.host && reqHeaders["x-forwarded-proto"])) {
|
2980
2975
|
return {
|
2981
|
-
status:
|
2976
|
+
status: 500,
|
2982
2977
|
json: {
|
2983
|
-
message: "
|
2978
|
+
message: "Missing host or x-forwarded-proto header"
|
2984
2979
|
}
|
2985
2980
|
};
|
2986
2981
|
}
|
2987
|
-
const
|
2988
|
-
|
2989
|
-
const sha256 = getSha256(mimeType, buffer);
|
2990
|
-
if (sha256 === query.sha256) {
|
2991
|
-
return {
|
2992
|
-
status: 200,
|
2993
|
-
headers: {
|
2994
|
-
"Content-Type": mimeType,
|
2995
|
-
"Content-Length": buffer.byteLength.toString(),
|
2996
|
-
"Cache-Control": "public, max-age=31536000, immutable"
|
2997
|
-
},
|
2998
|
-
body: bufferToReadableStream(buffer)
|
2999
|
-
};
|
3000
|
-
}
|
3001
|
-
}
|
2982
|
+
const host = `${reqHeaders["x-forwarded-proto"]}://${reqHeaders["host"]}`;
|
2983
|
+
const fileUrl = filePath.slice("/public".length);
|
3002
2984
|
return {
|
3003
|
-
status:
|
3004
|
-
|
3005
|
-
"Content-Type": mimeType,
|
3006
|
-
"Content-Length": buffer.byteLength.toString()
|
3007
|
-
},
|
3008
|
-
body: bufferToReadableStream(buffer)
|
2985
|
+
status: 302,
|
2986
|
+
redirectTo: new URL(fileUrl, host).toString()
|
3009
2987
|
};
|
3010
2988
|
}
|
3011
2989
|
});
|
@@ -3328,8 +3306,10 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3328
3306
|
return async req => {
|
3329
3307
|
var _req$method;
|
3330
3308
|
const valServer = await valServerPromise;
|
3331
|
-
|
3332
|
-
|
3309
|
+
const requestHeaders = {
|
3310
|
+
host: req.headers.get("host"),
|
3311
|
+
"x-forwarded-proto": req.headers.get("x-forwarded-proto")
|
3312
|
+
};
|
3333
3313
|
const url = new URL(req.url);
|
3334
3314
|
if (!url.pathname.startsWith(route)) {
|
3335
3315
|
const error = {
|
@@ -3392,16 +3372,16 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3392
3372
|
}));
|
3393
3373
|
} else if (method === "POST" && path === "/commit") {
|
3394
3374
|
const body = await req.json();
|
3395
|
-
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3375
|
+
return convert(await valServer.postCommit(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3396
3376
|
} else if (method === "POST" && path === "/validate") {
|
3397
3377
|
const body = await req.json();
|
3398
|
-
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE])));
|
3378
|
+
return convert(await valServer.postValidate(body, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3399
3379
|
} else if (method === "GET" && path.startsWith(TREE_PATH_PREFIX)) {
|
3400
3380
|
return withTreePath(path, TREE_PATH_PREFIX)(async treePath => convert(await valServer.getTree(treePath, {
|
3401
3381
|
patch: url.searchParams.get("patch") || undefined,
|
3402
3382
|
schema: url.searchParams.get("schema") || undefined,
|
3403
3383
|
source: url.searchParams.get("source") || undefined
|
3404
|
-
}, getCookies(req, [VAL_SESSION_COOKIE]))));
|
3384
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders)));
|
3405
3385
|
} else if (method === "GET" && path.startsWith(PATCHES_PATH_PREFIX)) {
|
3406
3386
|
return withTreePath(path, PATCHES_PATH_PREFIX)(async () => convert(await valServer.getPatches({
|
3407
3387
|
id: url.searchParams.getAll("id")
|
@@ -3417,7 +3397,7 @@ function createValApiRouter(route, valServerPromise, convert) {
|
|
3417
3397
|
const treePath = path.slice(FILES_PATH_PREFIX.length);
|
3418
3398
|
return convert(await valServer.getFiles(treePath, {
|
3419
3399
|
sha256: url.searchParams.get("sha256") || undefined
|
3420
|
-
}, getCookies(req, [VAL_SESSION_COOKIE])));
|
3400
|
+
}, getCookies(req, [VAL_SESSION_COOKIE]), requestHeaders));
|
3421
3401
|
} else {
|
3422
3402
|
return convert({
|
3423
3403
|
status: 404,
|
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.17",
|
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.17",
|
28
|
+
"@valbuild/shared": "~0.60.17",
|
29
|
+
"@valbuild/ui": "~0.60.17",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"minimatch": "^3.0.4",
|