@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.
@@ -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, valConfigPath: string, patch: Patch, sourceFileHandler: ValSourceFileHandler, runtime: QuickJSRuntime) => Promise<void>;
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, valConfigPath, patch$1, sourceFileHandler, runtime) => {
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(valConfigPath, `.${id}.val`);
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, execValidations, includeSource, includeSchema);
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, 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, "", options);
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, valConfigPath, patch$1, sourceFileHandler, runtime) => {
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(valConfigPath, `.${id}.val`);
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, execValidations, includeSource, includeSchema);
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, 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, "", options);
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, valConfigPath, patch, sourceFileHandler, runtime) => {
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(valConfigPath, `.${id}.val`);
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, execValidations, includeSource, includeSchema);
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, 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, "", options);
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.23",
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.23",
28
- "@valbuild/shared": "~0.60.23",
29
- "@valbuild/ui": "~0.60.23",
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",