@valbuild/server 0.60.23 → 0.60.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/declarations/src/LocalValServer.d.ts +2 -2
- package/dist/declarations/src/ValServer.d.ts +2 -3
- package/dist/declarations/src/patchValFile.d.ts +1 -1
- package/dist/valbuild-server.cjs.dev.js +41 -13
- package/dist/valbuild-server.cjs.prod.js +41 -13
- package/dist/valbuild-server.esm.js +41 -13
- package/package.json +4 -4
@@ -2,7 +2,7 @@
|
|
2
2
|
import { Service } from "./Service.js";
|
3
3
|
import { result } from "@valbuild/core/fp";
|
4
4
|
import { Patch } from "./patch/validation.js";
|
5
|
-
import { ApiGetPatchResponse, ApiPostPatchResponse, ModuleId, PatchId, ApiDeletePatchResponse } from "@valbuild/core";
|
5
|
+
import { ApiGetPatchResponse, ApiPostPatchResponse, ModuleId, PatchId, ApiDeletePatchResponse, FileMetadata, ImageMetadata } from "@valbuild/core";
|
6
6
|
import { VAL_ENABLE_COOKIE_NAME, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, ValServerError, ValServerJsonResult, ValServerRedirectResult, ValServerResult, ValSession } from "@valbuild/shared/internal";
|
7
7
|
import { ValServer, ValServerCallbacks } from "./ValServer.js";
|
8
8
|
import { SerializedModuleContent } from "./SerializedModuleContent.js";
|
@@ -32,6 +32,7 @@ export declare class LocalValServer extends ValServer {
|
|
32
32
|
id?: string[];
|
33
33
|
}): Promise<ValServerJsonResult<ApiDeletePatchResponse>>;
|
34
34
|
postPatches(body: unknown): Promise<ValServerJsonResult<ApiPostPatchResponse>>;
|
35
|
+
getMetadata(): Promise<FileMetadata | ImageMetadata | undefined>;
|
35
36
|
getFiles(filePath: string, query: {
|
36
37
|
sha256?: string;
|
37
38
|
}): Promise<ValServerResult<never, ReadableStream<Uint8Array>>>;
|
@@ -44,7 +45,6 @@ export declare class LocalValServer extends ValServer {
|
|
44
45
|
private badRequest;
|
45
46
|
protected ensureInitialized(): Promise<result.Result<undefined, ValServerError>>;
|
46
47
|
protected getModule(moduleId: ModuleId, options: {
|
47
|
-
validate: boolean;
|
48
48
|
source: boolean;
|
49
49
|
schema: boolean;
|
50
50
|
}): Promise<SerializedModuleContent>;
|
@@ -4,7 +4,7 @@ import { VAL_ENABLE_COOKIE_NAME, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, ValCookie
|
|
4
4
|
import { result } from "@valbuild/core/fp";
|
5
5
|
import { Operation } from "@valbuild/core/patch";
|
6
6
|
import { Patch } from "./patch/validation.js";
|
7
|
-
import { ModuleId, PatchId } from "@valbuild/core";
|
7
|
+
import { ModuleId, PatchId, FileMetadata, ImageMetadata } from "@valbuild/core";
|
8
8
|
import { SerializedModuleContent } from "./SerializedModuleContent.js";
|
9
9
|
export type ValServerOptions = {
|
10
10
|
valEnableRedirectUrl?: string;
|
@@ -29,11 +29,11 @@ export declare abstract class ValServer implements IValServer {
|
|
29
29
|
patch?: string;
|
30
30
|
schema?: string;
|
31
31
|
source?: string;
|
32
|
-
validate?: string;
|
33
32
|
}, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiTreeResponse>>;
|
34
33
|
postValidate(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiPostValidationResponse | ApiPostValidationErrorResponse>>;
|
35
34
|
postCommit(rawBody: unknown, cookies: ValCookies<VAL_SESSION_COOKIE>, requestHeaders: RequestHeaders): Promise<ValServerJsonResult<ApiCommitResponse, ApiPostValidationErrorResponse>>;
|
36
35
|
private applyAllPatchesThenValidate;
|
36
|
+
abstract getMetadata(fileRef: string, sha256?: string): Promise<FileMetadata | ImageMetadata | undefined>;
|
37
37
|
private revalidateImageAndFileValidation;
|
38
38
|
protected abstract getAllModules(treePath: string): Promise<ModuleId[]>;
|
39
39
|
protected sortPatchIds(patchesByModule: Record<ModuleId, {
|
@@ -58,7 +58,6 @@ export declare abstract class ValServer implements IValServer {
|
|
58
58
|
* */
|
59
59
|
protected abstract ensureInitialized(errorMessageType: string, cookies: ValCookies<VAL_SESSION_COOKIE>): Promise<result.Result<undefined, ValServerError>>;
|
60
60
|
protected abstract getModule(moduleId: ModuleId, options: {
|
61
|
-
validate: boolean;
|
62
61
|
source: boolean;
|
63
62
|
schema: boolean;
|
64
63
|
}): Promise<SerializedModuleContent>;
|
@@ -4,5 +4,5 @@ import { type ValSyntaxErrorTree } from "./patch/ts/syntax.js";
|
|
4
4
|
import { ValSourceFileHandler } from "./ValSourceFileHandler.js";
|
5
5
|
import { QuickJSRuntime } from "quickjs-emscripten";
|
6
6
|
import ts from "typescript";
|
7
|
-
export declare const patchValFile: (id: string,
|
7
|
+
export declare const patchValFile: (id: string, rootDir: string, patch: Patch, sourceFileHandler: ValSourceFileHandler, runtime: QuickJSRuntime) => Promise<void>;
|
8
8
|
export declare const patchSourceFile: (sourceFile: ts.SourceFile | string, patch: Patch) => result.Result<ts.SourceFile, ValSyntaxErrorTree | PatchError>;
|
@@ -633,6 +633,10 @@ class TSOps {
|
|
633
633
|
}
|
634
634
|
}
|
635
635
|
|
636
|
+
function getSyntheticContainingPath(rootDir) {
|
637
|
+
return path__namespace["default"].join(rootDir, "<val>"); // TODO: this is the synthetic path used when evaluating / patching modules. I am not sure <val> is the best choice: val.ts / js better? But that is weird too. At least now it is clear(er) that it is indeed a synthetic file (i.e. not an actual file)
|
638
|
+
}
|
639
|
+
|
636
640
|
const ops$1 = new TSOps(document => {
|
637
641
|
return fp.pipe(analyzeValModule(document), fp.result.map(({
|
638
642
|
source
|
@@ -640,10 +644,10 @@ const ops$1 = new TSOps(document => {
|
|
640
644
|
});
|
641
645
|
|
642
646
|
// TODO: rename to patchValFiles since we may write multiple files
|
643
|
-
const patchValFile = async (id,
|
647
|
+
const patchValFile = async (id, rootDir, patch$1, sourceFileHandler, runtime) => {
|
644
648
|
// const timeId = randomUUID();
|
645
649
|
// console.time("patchValFile" + timeId);
|
646
|
-
const filePath = sourceFileHandler.resolveSourceModulePath(
|
650
|
+
const filePath = sourceFileHandler.resolveSourceModulePath(getSyntheticContainingPath(rootDir), `.${id}.val`);
|
647
651
|
const sourceFile = sourceFileHandler.getSourceFile(filePath);
|
648
652
|
if (!sourceFile) {
|
649
653
|
throw Error(`Source file ${filePath} not found`);
|
@@ -741,9 +745,7 @@ globalThis.valModule = {
|
|
741
745
|
defaultExport: !!valModule?.default,
|
742
746
|
};
|
743
747
|
`;
|
744
|
-
const result = context.evalCode(code,
|
745
|
-
// Synthetic module name
|
746
|
-
path__namespace["default"].join(rootDirPath, "<val>"));
|
748
|
+
const result = context.evalCode(code, getSyntheticContainingPath(rootDirPath));
|
747
749
|
const fatalErrors = [];
|
748
750
|
if (result.error) {
|
749
751
|
const error = result.error.consume(context.dump);
|
@@ -1457,7 +1459,6 @@ class ValServer {
|
|
1457
1459
|
return ensureRes.error;
|
1458
1460
|
}
|
1459
1461
|
const applyPatches = query.patch === "true";
|
1460
|
-
const execValidations = query.validate === "true";
|
1461
1462
|
const includeSource = query.source === "true";
|
1462
1463
|
const includeSchema = query.schema === "true";
|
1463
1464
|
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
@@ -1479,8 +1480,9 @@ class ValServer {
|
|
1479
1480
|
patchesById = res.value.patchesById;
|
1480
1481
|
fileUpdates = res.value.fileUpdates;
|
1481
1482
|
}
|
1483
|
+
const validate = false;
|
1482
1484
|
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1483
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches,
|
1485
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema);
|
1484
1486
|
})));
|
1485
1487
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1486
1488
|
const module = {
|
@@ -1535,7 +1537,6 @@ class ValServer {
|
|
1535
1537
|
/* */
|
1536
1538
|
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema) {
|
1537
1539
|
const serializedModuleContent = await this.getModule(moduleId, {
|
1538
|
-
validate: validate,
|
1539
1540
|
source: includeSource,
|
1540
1541
|
schema: includeSchema
|
1541
1542
|
});
|
@@ -1602,7 +1603,6 @@ class ValServer {
|
|
1602
1603
|
errors: false
|
1603
1604
|
};
|
1604
1605
|
}
|
1605
|
-
|
1606
1606
|
// TODO: name this better: we need to check for image and file validation errors
|
1607
1607
|
// since they cannot be handled directly inside the validation function.
|
1608
1608
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
@@ -1620,8 +1620,9 @@ class ValServer {
|
|
1620
1620
|
)) {
|
1621
1621
|
const fileRef = getValidationErrorFileRef(error);
|
1622
1622
|
if (fileRef) {
|
1623
|
+
var _fileUpdates$fileRef;
|
1623
1624
|
const filePath = path__namespace["default"].join(this.cwd, fileRef);
|
1624
|
-
let expectedMetadata;
|
1625
|
+
let expectedMetadata = await this.getMetadata(fileRef, (_fileUpdates$fileRef = fileUpdates[fileRef]) === null || _fileUpdates$fileRef === void 0 ? void 0 : _fileUpdates$fileRef.sha256);
|
1625
1626
|
|
1626
1627
|
// if this is a new file or we have an actual FS, we read the file and get the metadata
|
1627
1628
|
if (!expectedMetadata) {
|
@@ -1803,7 +1804,7 @@ class ValServer {
|
|
1803
1804
|
const moduleId = moduleIdStr;
|
1804
1805
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1805
1806
|
// TODO: refine to ModuleId and PatchId when parsing
|
1806
|
-
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true,
|
1807
|
+
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true, commit);
|
1807
1808
|
if (serializedModuleContent.errors) {
|
1808
1809
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1809
1810
|
}
|
@@ -2168,6 +2169,9 @@ class LocalValServer extends ValServer {
|
|
2168
2169
|
json: res
|
2169
2170
|
};
|
2170
2171
|
}
|
2172
|
+
async getMetadata() {
|
2173
|
+
return undefined;
|
2174
|
+
}
|
2171
2175
|
async getFiles(filePath, query) {
|
2172
2176
|
if (query.sha256) {
|
2173
2177
|
const fileExists = this.host.fileExists(this.getFilePath(filePath, query.sha256));
|
@@ -2319,7 +2323,10 @@ class LocalValServer extends ValServer {
|
|
2319
2323
|
return fp.result.ok(undefined);
|
2320
2324
|
}
|
2321
2325
|
getModule(moduleId, options) {
|
2322
|
-
return this.options.service.get(moduleId, "",
|
2326
|
+
return this.options.service.get(moduleId, "", {
|
2327
|
+
...options,
|
2328
|
+
validate: false
|
2329
|
+
});
|
2323
2330
|
}
|
2324
2331
|
async getAllModules(treePath) {
|
2325
2332
|
const moduleIds = this.host.readDirectory(this.cwd, ["ts", "js"], ["node_modules", ".*"], ["**/*.val.ts", "**/*.val.js"]).filter(file => {
|
@@ -2836,12 +2843,33 @@ class ProxyValServer extends ValServer {
|
|
2836
2843
|
}
|
2837
2844
|
});
|
2838
2845
|
}
|
2846
|
+
async getMetadata(filePath, sha256) {
|
2847
|
+
const url = new URL(`/v1/metadata/${this.options.remote}${filePath}?commit=${this.options.git.commit}${sha256 ? `&sha256=${sha256}` : ""}`, this.options.valContentUrl);
|
2848
|
+
const fetchRes = await fetch(url, {
|
2849
|
+
headers: {
|
2850
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2851
|
+
}
|
2852
|
+
});
|
2853
|
+
if (fetchRes.status === 200) {
|
2854
|
+
const json = await fetchRes.json();
|
2855
|
+
if (json.type === "file") {
|
2856
|
+
return json;
|
2857
|
+
} else if (json.type === "image") {
|
2858
|
+
return json;
|
2859
|
+
}
|
2860
|
+
}
|
2861
|
+
return undefined;
|
2862
|
+
}
|
2839
2863
|
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2840
2864
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2841
2865
|
if (typeof query.sha256 === "string") {
|
2842
2866
|
url.searchParams.append("sha256", query.sha256);
|
2843
2867
|
}
|
2844
|
-
const fetchRes = await fetch(url
|
2868
|
+
const fetchRes = await fetch(url, {
|
2869
|
+
headers: {
|
2870
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2871
|
+
}
|
2872
|
+
});
|
2845
2873
|
if (fetchRes.status === 200) {
|
2846
2874
|
// TODO: does this stream data?
|
2847
2875
|
if (fetchRes.body) {
|
@@ -633,6 +633,10 @@ class TSOps {
|
|
633
633
|
}
|
634
634
|
}
|
635
635
|
|
636
|
+
function getSyntheticContainingPath(rootDir) {
|
637
|
+
return path__namespace["default"].join(rootDir, "<val>"); // TODO: this is the synthetic path used when evaluating / patching modules. I am not sure <val> is the best choice: val.ts / js better? But that is weird too. At least now it is clear(er) that it is indeed a synthetic file (i.e. not an actual file)
|
638
|
+
}
|
639
|
+
|
636
640
|
const ops$1 = new TSOps(document => {
|
637
641
|
return fp.pipe(analyzeValModule(document), fp.result.map(({
|
638
642
|
source
|
@@ -640,10 +644,10 @@ const ops$1 = new TSOps(document => {
|
|
640
644
|
});
|
641
645
|
|
642
646
|
// TODO: rename to patchValFiles since we may write multiple files
|
643
|
-
const patchValFile = async (id,
|
647
|
+
const patchValFile = async (id, rootDir, patch$1, sourceFileHandler, runtime) => {
|
644
648
|
// const timeId = randomUUID();
|
645
649
|
// console.time("patchValFile" + timeId);
|
646
|
-
const filePath = sourceFileHandler.resolveSourceModulePath(
|
650
|
+
const filePath = sourceFileHandler.resolveSourceModulePath(getSyntheticContainingPath(rootDir), `.${id}.val`);
|
647
651
|
const sourceFile = sourceFileHandler.getSourceFile(filePath);
|
648
652
|
if (!sourceFile) {
|
649
653
|
throw Error(`Source file ${filePath} not found`);
|
@@ -741,9 +745,7 @@ globalThis.valModule = {
|
|
741
745
|
defaultExport: !!valModule?.default,
|
742
746
|
};
|
743
747
|
`;
|
744
|
-
const result = context.evalCode(code,
|
745
|
-
// Synthetic module name
|
746
|
-
path__namespace["default"].join(rootDirPath, "<val>"));
|
748
|
+
const result = context.evalCode(code, getSyntheticContainingPath(rootDirPath));
|
747
749
|
const fatalErrors = [];
|
748
750
|
if (result.error) {
|
749
751
|
const error = result.error.consume(context.dump);
|
@@ -1457,7 +1459,6 @@ class ValServer {
|
|
1457
1459
|
return ensureRes.error;
|
1458
1460
|
}
|
1459
1461
|
const applyPatches = query.patch === "true";
|
1460
|
-
const execValidations = query.validate === "true";
|
1461
1462
|
const includeSource = query.source === "true";
|
1462
1463
|
const includeSchema = query.schema === "true";
|
1463
1464
|
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
@@ -1479,8 +1480,9 @@ class ValServer {
|
|
1479
1480
|
patchesById = res.value.patchesById;
|
1480
1481
|
fileUpdates = res.value.fileUpdates;
|
1481
1482
|
}
|
1483
|
+
const validate = false;
|
1482
1484
|
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1483
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches,
|
1485
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema);
|
1484
1486
|
})));
|
1485
1487
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1486
1488
|
const module = {
|
@@ -1535,7 +1537,6 @@ class ValServer {
|
|
1535
1537
|
/* */
|
1536
1538
|
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema) {
|
1537
1539
|
const serializedModuleContent = await this.getModule(moduleId, {
|
1538
|
-
validate: validate,
|
1539
1540
|
source: includeSource,
|
1540
1541
|
schema: includeSchema
|
1541
1542
|
});
|
@@ -1602,7 +1603,6 @@ class ValServer {
|
|
1602
1603
|
errors: false
|
1603
1604
|
};
|
1604
1605
|
}
|
1605
|
-
|
1606
1606
|
// TODO: name this better: we need to check for image and file validation errors
|
1607
1607
|
// since they cannot be handled directly inside the validation function.
|
1608
1608
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
@@ -1620,8 +1620,9 @@ class ValServer {
|
|
1620
1620
|
)) {
|
1621
1621
|
const fileRef = getValidationErrorFileRef(error);
|
1622
1622
|
if (fileRef) {
|
1623
|
+
var _fileUpdates$fileRef;
|
1623
1624
|
const filePath = path__namespace["default"].join(this.cwd, fileRef);
|
1624
|
-
let expectedMetadata;
|
1625
|
+
let expectedMetadata = await this.getMetadata(fileRef, (_fileUpdates$fileRef = fileUpdates[fileRef]) === null || _fileUpdates$fileRef === void 0 ? void 0 : _fileUpdates$fileRef.sha256);
|
1625
1626
|
|
1626
1627
|
// if this is a new file or we have an actual FS, we read the file and get the metadata
|
1627
1628
|
if (!expectedMetadata) {
|
@@ -1803,7 +1804,7 @@ class ValServer {
|
|
1803
1804
|
const moduleId = moduleIdStr;
|
1804
1805
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1805
1806
|
// TODO: refine to ModuleId and PatchId when parsing
|
1806
|
-
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true,
|
1807
|
+
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true, commit);
|
1807
1808
|
if (serializedModuleContent.errors) {
|
1808
1809
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1809
1810
|
}
|
@@ -2168,6 +2169,9 @@ class LocalValServer extends ValServer {
|
|
2168
2169
|
json: res
|
2169
2170
|
};
|
2170
2171
|
}
|
2172
|
+
async getMetadata() {
|
2173
|
+
return undefined;
|
2174
|
+
}
|
2171
2175
|
async getFiles(filePath, query) {
|
2172
2176
|
if (query.sha256) {
|
2173
2177
|
const fileExists = this.host.fileExists(this.getFilePath(filePath, query.sha256));
|
@@ -2319,7 +2323,10 @@ class LocalValServer extends ValServer {
|
|
2319
2323
|
return fp.result.ok(undefined);
|
2320
2324
|
}
|
2321
2325
|
getModule(moduleId, options) {
|
2322
|
-
return this.options.service.get(moduleId, "",
|
2326
|
+
return this.options.service.get(moduleId, "", {
|
2327
|
+
...options,
|
2328
|
+
validate: false
|
2329
|
+
});
|
2323
2330
|
}
|
2324
2331
|
async getAllModules(treePath) {
|
2325
2332
|
const moduleIds = this.host.readDirectory(this.cwd, ["ts", "js"], ["node_modules", ".*"], ["**/*.val.ts", "**/*.val.js"]).filter(file => {
|
@@ -2836,12 +2843,33 @@ class ProxyValServer extends ValServer {
|
|
2836
2843
|
}
|
2837
2844
|
});
|
2838
2845
|
}
|
2846
|
+
async getMetadata(filePath, sha256) {
|
2847
|
+
const url = new URL(`/v1/metadata/${this.options.remote}${filePath}?commit=${this.options.git.commit}${sha256 ? `&sha256=${sha256}` : ""}`, this.options.valContentUrl);
|
2848
|
+
const fetchRes = await fetch(url, {
|
2849
|
+
headers: {
|
2850
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2851
|
+
}
|
2852
|
+
});
|
2853
|
+
if (fetchRes.status === 200) {
|
2854
|
+
const json = await fetchRes.json();
|
2855
|
+
if (json.type === "file") {
|
2856
|
+
return json;
|
2857
|
+
} else if (json.type === "image") {
|
2858
|
+
return json;
|
2859
|
+
}
|
2860
|
+
}
|
2861
|
+
return undefined;
|
2862
|
+
}
|
2839
2863
|
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2840
2864
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2841
2865
|
if (typeof query.sha256 === "string") {
|
2842
2866
|
url.searchParams.append("sha256", query.sha256);
|
2843
2867
|
}
|
2844
|
-
const fetchRes = await fetch(url
|
2868
|
+
const fetchRes = await fetch(url, {
|
2869
|
+
headers: {
|
2870
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2871
|
+
}
|
2872
|
+
});
|
2845
2873
|
if (fetchRes.status === 200) {
|
2846
2874
|
// TODO: does this stream data?
|
2847
2875
|
if (fetchRes.body) {
|
@@ -603,6 +603,10 @@ class TSOps {
|
|
603
603
|
}
|
604
604
|
}
|
605
605
|
|
606
|
+
function getSyntheticContainingPath(rootDir) {
|
607
|
+
return path__default.join(rootDir, "<val>"); // TODO: this is the synthetic path used when evaluating / patching modules. I am not sure <val> is the best choice: val.ts / js better? But that is weird too. At least now it is clear(er) that it is indeed a synthetic file (i.e. not an actual file)
|
608
|
+
}
|
609
|
+
|
606
610
|
const ops$1 = new TSOps(document => {
|
607
611
|
return pipe(analyzeValModule(document), result.map(({
|
608
612
|
source
|
@@ -610,10 +614,10 @@ const ops$1 = new TSOps(document => {
|
|
610
614
|
});
|
611
615
|
|
612
616
|
// TODO: rename to patchValFiles since we may write multiple files
|
613
|
-
const patchValFile = async (id,
|
617
|
+
const patchValFile = async (id, rootDir, patch, sourceFileHandler, runtime) => {
|
614
618
|
// const timeId = randomUUID();
|
615
619
|
// console.time("patchValFile" + timeId);
|
616
|
-
const filePath = sourceFileHandler.resolveSourceModulePath(
|
620
|
+
const filePath = sourceFileHandler.resolveSourceModulePath(getSyntheticContainingPath(rootDir), `.${id}.val`);
|
617
621
|
const sourceFile = sourceFileHandler.getSourceFile(filePath);
|
618
622
|
if (!sourceFile) {
|
619
623
|
throw Error(`Source file ${filePath} not found`);
|
@@ -711,9 +715,7 @@ globalThis.valModule = {
|
|
711
715
|
defaultExport: !!valModule?.default,
|
712
716
|
};
|
713
717
|
`;
|
714
|
-
const result = context.evalCode(code,
|
715
|
-
// Synthetic module name
|
716
|
-
path__default.join(rootDirPath, "<val>"));
|
718
|
+
const result = context.evalCode(code, getSyntheticContainingPath(rootDirPath));
|
717
719
|
const fatalErrors = [];
|
718
720
|
if (result.error) {
|
719
721
|
const error = result.error.consume(context.dump);
|
@@ -1427,7 +1429,6 @@ class ValServer {
|
|
1427
1429
|
return ensureRes.error;
|
1428
1430
|
}
|
1429
1431
|
const applyPatches = query.patch === "true";
|
1430
|
-
const execValidations = query.validate === "true";
|
1431
1432
|
const includeSource = query.source === "true";
|
1432
1433
|
const includeSchema = query.schema === "true";
|
1433
1434
|
const moduleIds = await debugTiming("getAllModules", () => this.getAllModules(treePath));
|
@@ -1449,8 +1450,9 @@ class ValServer {
|
|
1449
1450
|
patchesById = res.value.patchesById;
|
1450
1451
|
fileUpdates = res.value.fileUpdates;
|
1451
1452
|
}
|
1453
|
+
const validate = false;
|
1452
1454
|
const possiblyPatchedContent = await debugTiming("applyAllPatchesThenValidate", () => Promise.all(moduleIds.map(async moduleId => {
|
1453
|
-
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches,
|
1455
|
+
return this.applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema);
|
1454
1456
|
})));
|
1455
1457
|
const modules = Object.fromEntries(possiblyPatchedContent.map(serializedModuleContent => {
|
1456
1458
|
const module = {
|
@@ -1505,7 +1507,6 @@ class ValServer {
|
|
1505
1507
|
/* */
|
1506
1508
|
async applyAllPatchesThenValidate(moduleId, patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, applyPatches, validate, includeSource, includeSchema) {
|
1507
1509
|
const serializedModuleContent = await this.getModule(moduleId, {
|
1508
|
-
validate: validate,
|
1509
1510
|
source: includeSource,
|
1510
1511
|
schema: includeSchema
|
1511
1512
|
});
|
@@ -1572,7 +1573,6 @@ class ValServer {
|
|
1572
1573
|
errors: false
|
1573
1574
|
};
|
1574
1575
|
}
|
1575
|
-
|
1576
1576
|
// TODO: name this better: we need to check for image and file validation errors
|
1577
1577
|
// since they cannot be handled directly inside the validation function.
|
1578
1578
|
// The reason is that validate will be called inside QuickJS (in the future, hopefully),
|
@@ -1590,8 +1590,9 @@ class ValServer {
|
|
1590
1590
|
)) {
|
1591
1591
|
const fileRef = getValidationErrorFileRef(error);
|
1592
1592
|
if (fileRef) {
|
1593
|
+
var _fileUpdates$fileRef;
|
1593
1594
|
const filePath = path__default.join(this.cwd, fileRef);
|
1594
|
-
let expectedMetadata;
|
1595
|
+
let expectedMetadata = await this.getMetadata(fileRef, (_fileUpdates$fileRef = fileUpdates[fileRef]) === null || _fileUpdates$fileRef === void 0 ? void 0 : _fileUpdates$fileRef.sha256);
|
1595
1596
|
|
1596
1597
|
// if this is a new file or we have an actual FS, we read the file and get the metadata
|
1597
1598
|
if (!expectedMetadata) {
|
@@ -1773,7 +1774,7 @@ class ValServer {
|
|
1773
1774
|
const moduleId = moduleIdStr;
|
1774
1775
|
const serializedModuleContent = await this.applyAllPatchesThenValidate(moduleId, filterPatchesByModuleIdRes.data.patches ||
|
1775
1776
|
// TODO: refine to ModuleId and PatchId when parsing
|
1776
|
-
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true,
|
1777
|
+
patchIdsByModuleId, patchesById, fileUpdates, cookies, requestHeaders, true, true, true, commit);
|
1777
1778
|
if (serializedModuleContent.errors) {
|
1778
1779
|
validationErrorsByModuleId[moduleId] = serializedModuleContent;
|
1779
1780
|
}
|
@@ -2138,6 +2139,9 @@ class LocalValServer extends ValServer {
|
|
2138
2139
|
json: res
|
2139
2140
|
};
|
2140
2141
|
}
|
2142
|
+
async getMetadata() {
|
2143
|
+
return undefined;
|
2144
|
+
}
|
2141
2145
|
async getFiles(filePath, query) {
|
2142
2146
|
if (query.sha256) {
|
2143
2147
|
const fileExists = this.host.fileExists(this.getFilePath(filePath, query.sha256));
|
@@ -2289,7 +2293,10 @@ class LocalValServer extends ValServer {
|
|
2289
2293
|
return result.ok(undefined);
|
2290
2294
|
}
|
2291
2295
|
getModule(moduleId, options) {
|
2292
|
-
return this.options.service.get(moduleId, "",
|
2296
|
+
return this.options.service.get(moduleId, "", {
|
2297
|
+
...options,
|
2298
|
+
validate: false
|
2299
|
+
});
|
2293
2300
|
}
|
2294
2301
|
async getAllModules(treePath) {
|
2295
2302
|
const moduleIds = this.host.readDirectory(this.cwd, ["ts", "js"], ["node_modules", ".*"], ["**/*.val.ts", "**/*.val.js"]).filter(file => {
|
@@ -2806,12 +2813,33 @@ class ProxyValServer extends ValServer {
|
|
2806
2813
|
}
|
2807
2814
|
});
|
2808
2815
|
}
|
2816
|
+
async getMetadata(filePath, sha256) {
|
2817
|
+
const url = new URL(`/v1/metadata/${this.options.remote}${filePath}?commit=${this.options.git.commit}${sha256 ? `&sha256=${sha256}` : ""}`, this.options.valContentUrl);
|
2818
|
+
const fetchRes = await fetch(url, {
|
2819
|
+
headers: {
|
2820
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2821
|
+
}
|
2822
|
+
});
|
2823
|
+
if (fetchRes.status === 200) {
|
2824
|
+
const json = await fetchRes.json();
|
2825
|
+
if (json.type === "file") {
|
2826
|
+
return json;
|
2827
|
+
} else if (json.type === "image") {
|
2828
|
+
return json;
|
2829
|
+
}
|
2830
|
+
}
|
2831
|
+
return undefined;
|
2832
|
+
}
|
2809
2833
|
async getFiles(filePath, query, _cookies, reqHeaders) {
|
2810
2834
|
const url = new URL(`/v1/files/${this.options.remote}${filePath}`, this.options.valContentUrl);
|
2811
2835
|
if (typeof query.sha256 === "string") {
|
2812
2836
|
url.searchParams.append("sha256", query.sha256);
|
2813
2837
|
}
|
2814
|
-
const fetchRes = await fetch(url
|
2838
|
+
const fetchRes = await fetch(url, {
|
2839
|
+
headers: {
|
2840
|
+
Authorization: `Bearer ${this.options.apiKey}`
|
2841
|
+
}
|
2842
|
+
});
|
2815
2843
|
if (fetchRes.status === 200) {
|
2816
2844
|
// TODO: does this stream data?
|
2817
2845
|
if (fetchRes.body) {
|
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.27",
|
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.27",
|
28
|
+
"@valbuild/shared": "~0.60.27",
|
29
|
+
"@valbuild/ui": "~0.60.27",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"minimatch": "^3.0.4",
|