@valbuild/server 0.133.0 → 0.134.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # @valbuild/server
2
2
 
3
+ ## 0.134.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#708](https://github.com/valbuild/val/pull/708) [`be78a9b`](https://github.com/valbuild/val/commit/be78a9b51678439f7ecb1c7f3887f9e8e1261a13) Thanks [@freekh](https://github.com/freekh)! - Fix `gitCommit` and `gitBranch` in `val.config.ts` never reaching the server,
8
+ and make them the one way to say it.
9
+
10
+ `val.config.ts` has had `gitCommit` and `gitBranch` for as long as it has had
11
+ anything, and a deployed app that set them resolved to no repository at all.
12
+ Nothing failed and nothing was logged: the commit was simply never sent, and
13
+ every patch the project saved recorded none.
14
+
15
+ ```ts
16
+ // val.config.ts — the normal Vercel shape, and it did nothing
17
+ initVal({
18
+ project: "org/project",
19
+ gitCommit: process.env.VERCEL_GIT_COMMIT_SHA,
20
+ gitBranch: process.env.VERCEL_GIT_COMMIT_REF,
21
+ });
22
+ ```
23
+
24
+ The two halves never met. The server wanted a nested
25
+ `git: { commit, branch }`, `val.config.ts` offered two flat keys, and nothing
26
+ mapped one onto the other — so the only thing that worked was
27
+ `VAL_GIT_COMMIT` / `VAL_GIT_BRANCH` in the environment.
28
+
29
+ Rather than teach the server to read both, the nested option is gone:
30
+ `ValApiOptions` and TanStack's `ValHttpMode` now take `gitCommit` and
31
+ `gitBranch`, the same two names `ValConfig` uses. There is one name for this
32
+ now, wherever it is set. The framework bindings already hand the server
33
+ `{ versions, ...config }`, so a project's config keys arrive with nothing to
34
+ map, and a host passing them directly is saying the same thing in the same
35
+ words.
36
+
37
+ Flat because of where these values come from. A platform supplies them as
38
+ `process.env.VERCEL_GIT_COMMIT_SHA` and friends, typed `string | undefined`,
39
+ and two optional strings take that as it comes — a nested object makes every
40
+ caller write the ternary that turns two maybe-strings into one maybe-object.
41
+
42
+ **Breaking for a host that passed `git` itself**, which is the nested option on
43
+ `ValApiOptions` and on TanStack's `http` mode. An app that only configures
44
+ `val.config.ts` or the environment is unaffected.
45
+
46
+ ```ts
47
+ // before
48
+ initValServer(valModules, config, {
49
+ http: { apiKey, valSecret, git: { commit, branch } },
50
+ });
51
+
52
+ // after
53
+ initValServer(valModules, config, {
54
+ http: { apiKey, valSecret, gitCommit: commit, gitBranch: branch },
55
+ });
56
+ ```
57
+
58
+ **What a commit is for**, and why its absence is worth a release rather than a
59
+ shrug: publishing turns pending patches into new `.val.ts` text, and to patch a
60
+ file you must first read it — at a commit. A project with none is a project
61
+ whose publishes read whatever the content service last had, rather than the
62
+ revision the deployed code was built from.
63
+
64
+ **One more behaviour change.** A commit and a branch have always been taken
65
+ together or not at all, and that check now sees config-supplied values too. A
66
+ project that sets exactly one of `gitCommit` and `gitBranch` used to have both
67
+ quietly ignored and will now be refused at startup, naming the missing half.
68
+ That is the configuration that would otherwise fail later, at a publish.
69
+
70
+ - Updated dependencies [[`1c31dcc`](https://github.com/valbuild/val/commit/1c31dcca7f1bb0199350567fd579de29f48bb26d), [`688b9e3`](https://github.com/valbuild/val/commit/688b9e36b821323cda6870cdff03dd36ec3e782f), [`16c49ea`](https://github.com/valbuild/val/commit/16c49ea6dd97c7a96bbfdf211af9bab5884579e2), [`eaa265e`](https://github.com/valbuild/val/commit/eaa265e78d9f6d2a1b685c38901612b8a3704eed)]:
71
+ - @valbuild/ui@0.134.0
72
+ - @valbuild/core@0.134.0
73
+ - @valbuild/shared@0.134.0
74
+
3
75
  ## 0.133.0
4
76
 
5
77
  ### Minor Changes
@@ -106,12 +106,28 @@ type ValServerOverrides = Partial<{
106
106
  * property of those bytes. `VAL_GIT_COMMIT` / `VAL_GIT_BRANCH` supply it
107
107
  * where a build system sets environment variables instead.
108
108
  *
109
- * @example { commit: "e83c5163316f89bfbde7d9ab23ca2e25604af290", branch: "main" }
109
+ * FLAT, and the same two names `val.config.ts` uses, so that there is one
110
+ * way to say this rather than two. An app reads these off its platform --
111
+ * `process.env.VERCEL_GIT_COMMIT_SHA` and friends, which are typed
112
+ * `string | undefined` -- and a pair of optional strings takes that as it
113
+ * comes. A nested `{ commit, branch }` would make every caller write the
114
+ * ternary that turns two maybe-strings into one maybe-object. Sharing the
115
+ * names with `ValConfig` is what makes the bindings' `{ versions,
116
+ * ...config }` carry them here with nothing to map.
117
+ *
118
+ * Taken together or not at all: `initHandlerOptions` refuses one without
119
+ * the other rather than resolving half a repository.
120
+ *
121
+ * @example "e83c5163316f89bfbde7d9ab23ca2e25604af290"
110
122
  */
111
- git?: {
112
- commit: string;
113
- branch: string;
114
- };
123
+ gitCommit?: string;
124
+ /**
125
+ * The branch a publish mirrors into. See {@link ValApiOptions.gitCommit},
126
+ * which this is required with and meaningless without.
127
+ *
128
+ * @example "main"
129
+ */
130
+ gitBranch?: string;
115
131
  /**
116
132
  * The base url of Val.
117
133
  *
@@ -205,6 +205,14 @@ export declare function handleJsonValuesExtractEntry(ctx: FixHandlerContext): Pr
205
205
  * `fixableErrorMessage` rather than a plain error, because the error IS fixable
206
206
  * — just not by this command.
207
207
  */
208
+ /**
209
+ * A view pointer that names a module its schema does not.
210
+ *
211
+ * Nothing to look up and nothing to ask: the schema names the module, so the
212
+ * one correct value is already known. `createFixPatch` writes it — this handler
213
+ * exists to send it there, and to say what `--fix` would do when it is off.
214
+ */
215
+ export declare function handleViewCheckModule(ctx: FixHandlerContext): Promise<FixHandlerResult>;
208
216
  export declare function handleExternalUpload(): Promise<FixHandlerResult>;
209
217
  export declare const currentFixHandlers: Record<Exclude<ValidationFix, "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "record:fill-keys">, FixHandler>;
210
218
  export declare const fixHandlers: Record<string, FixHandler>;
@@ -10913,7 +10913,7 @@ async function initHandlerOptions(route, opts, config) {
10913
10913
  valContentUrl
10914
10914
  });
10915
10915
  if (isProxyMode) {
10916
- var _opts$git, _opts$git2, _opts$versions, _opts$versions2;
10916
+ var _opts$versions, _opts$versions2;
10917
10917
  /*
10918
10918
  * Why this app is in http mode, in the message that says what is missing.
10919
10919
  *
@@ -10945,11 +10945,23 @@ async function initHandlerOptions(route, opts, config) {
10945
10945
  * with no line of work to publish to, and a branch without a commit names
10946
10946
  * a line with no position in it; either alone would be a half-configured
10947
10947
  * repository that fails later, at a publish, rather than here.
10948
+ *
10949
+ * ONE NAME, wherever it comes from. `opts` is the bindings'
10950
+ * `{ versions, ...config }`, so `opts.gitCommit` IS `val.config.ts`'s
10951
+ * `gitCommit` -- there is nothing to map and no second place to look.
10952
+ *
10953
+ * It used to be a nested `git: { commit, branch }` here and two flat keys
10954
+ * in `ValConfig`, and the two never met: nothing mapped one onto the
10955
+ * other, so a project that set the documented config keys -- which is
10956
+ * what every Vercel deployment does, from `VERCEL_GIT_COMMIT_SHA` --
10957
+ * resolved to no repository at all. Nothing failed and nothing was
10958
+ * logged; the commit was simply never sent, and every patch it saved
10959
+ * recorded none.
10948
10960
  */
10949
- const maybeGitCommit = ((_opts$git = opts.git) === null || _opts$git === void 0 ? void 0 : _opts$git.commit) || process.env.VAL_GIT_COMMIT;
10950
- const maybeGitBranch = ((_opts$git2 = opts.git) === null || _opts$git2 === void 0 ? void 0 : _opts$git2.branch) || process.env.VAL_GIT_BRANCH;
10961
+ const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
10962
+ const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
10951
10963
  if (!!maybeGitCommit !== !!maybeGitBranch) {
10952
- throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both (the ` + "`git` option, or VAL_GIT_COMMIT and VAL_GIT_BRANCH) for a project " + "whose content is mirrored into a repository, or neither for one " + "whose content service is the store of record." + because);
10964
+ throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both ` + "(`gitCommit` and `gitBranch` in val.config.ts, or VAL_GIT_COMMIT " + "and VAL_GIT_BRANCH) for a project whose content is mirrored into " + "a repository, or neither for one whose content service is the " + "store of record." + because);
10953
10965
  }
10954
10966
  if (!maybeValProject) {
10955
10967
  throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
@@ -16335,6 +16347,44 @@ async function createFixPatch(config, apply, sourcePath, validationError, remote
16335
16347
  fixes: undefined
16336
16348
  });
16337
16349
  }
16350
+ } else if (fix === "view:check-module") {
16351
+ // The schema is the authority: it names the module, and there is exactly
16352
+ // one valid pointer. So this is written rather than reported — nobody has
16353
+ // a decision to make here.
16354
+ const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
16355
+ if (moduleSource === undefined || moduleSchema === undefined) {
16356
+ remainingErrors.push({
16357
+ ...validationError,
16358
+ message: "Unexpected error while checking a view (no module source or schema)",
16359
+ fixes: undefined
16360
+ });
16361
+ continue;
16362
+ }
16363
+ const {
16364
+ schema: schemaAtPath
16365
+ } = core.Internal.resolvePath(modulePath, moduleSource, moduleSchema);
16366
+ if (schemaAtPath.type !== "view") {
16367
+ remainingErrors.push({
16368
+ ...validationError,
16369
+ message: `Could not fix view: schema at ${sourcePath} is '${schemaAtPath.type}', not a view`,
16370
+ fixes: undefined
16371
+ });
16372
+ continue;
16373
+ }
16374
+ if (apply) {
16375
+ patch$1.push({
16376
+ op: "replace",
16377
+ path: core.Internal.createPatchPath(modulePath),
16378
+ value: {
16379
+ view: schemaAtPath.moduleFilePath
16380
+ }
16381
+ });
16382
+ } else {
16383
+ remainingErrors.push({
16384
+ ...validationError,
16385
+ message: `This view points at the wrong module. Expected '${schemaAtPath.moduleFilePath}'.`
16386
+ });
16387
+ }
16338
16388
  }
16339
16389
  }
16340
16390
  if (!validationError.fixes || validationError.fixes.length === 0) {
@@ -17078,6 +17128,25 @@ async function handleJsonValuesExtractEntry(ctx) {
17078
17128
  * `fixableErrorMessage` rather than a plain error, because the error IS fixable
17079
17129
  * — just not by this command.
17080
17130
  */
17131
+ /**
17132
+ * A view pointer that names a module its schema does not.
17133
+ *
17134
+ * Nothing to look up and nothing to ask: the schema names the module, so the
17135
+ * one correct value is already known. `createFixPatch` writes it — this handler
17136
+ * exists to send it there, and to say what `--fix` would do when it is off.
17137
+ */
17138
+ async function handleViewCheckModule(ctx) {
17139
+ if (!ctx.fix) {
17140
+ return {
17141
+ success: true,
17142
+ fixableErrorMessage: `${ctx.validationError.message}. ` + "Run 'val validate --fix' to point it at the module its schema names."
17143
+ };
17144
+ }
17145
+ return {
17146
+ success: true,
17147
+ shouldApplyPatch: true
17148
+ };
17149
+ }
17081
17150
  async function handleExternalUpload() {
17082
17151
  return {
17083
17152
  success: true,
@@ -17109,7 +17178,8 @@ const currentFixHandlers = {
17109
17178
  "images:check-all-files": handleCheckAllFiles,
17110
17179
  "files:check-all-files": handleCheckAllFiles,
17111
17180
  "jsonValues:extract-entry": handleJsonValuesExtractEntry,
17112
- "external:upload": handleExternalUpload
17181
+ "external:upload": handleExternalUpload,
17182
+ "view:check-module": handleViewCheckModule
17113
17183
  };
17114
17184
  const deprecatedFixHandlers = {
17115
17185
  "image:replace-metadata": handleFileMetadata
@@ -10913,7 +10913,7 @@ async function initHandlerOptions(route, opts, config) {
10913
10913
  valContentUrl
10914
10914
  });
10915
10915
  if (isProxyMode) {
10916
- var _opts$git, _opts$git2, _opts$versions, _opts$versions2;
10916
+ var _opts$versions, _opts$versions2;
10917
10917
  /*
10918
10918
  * Why this app is in http mode, in the message that says what is missing.
10919
10919
  *
@@ -10945,11 +10945,23 @@ async function initHandlerOptions(route, opts, config) {
10945
10945
  * with no line of work to publish to, and a branch without a commit names
10946
10946
  * a line with no position in it; either alone would be a half-configured
10947
10947
  * repository that fails later, at a publish, rather than here.
10948
+ *
10949
+ * ONE NAME, wherever it comes from. `opts` is the bindings'
10950
+ * `{ versions, ...config }`, so `opts.gitCommit` IS `val.config.ts`'s
10951
+ * `gitCommit` -- there is nothing to map and no second place to look.
10952
+ *
10953
+ * It used to be a nested `git: { commit, branch }` here and two flat keys
10954
+ * in `ValConfig`, and the two never met: nothing mapped one onto the
10955
+ * other, so a project that set the documented config keys -- which is
10956
+ * what every Vercel deployment does, from `VERCEL_GIT_COMMIT_SHA` --
10957
+ * resolved to no repository at all. Nothing failed and nothing was
10958
+ * logged; the commit was simply never sent, and every patch it saved
10959
+ * recorded none.
10948
10960
  */
10949
- const maybeGitCommit = ((_opts$git = opts.git) === null || _opts$git === void 0 ? void 0 : _opts$git.commit) || process.env.VAL_GIT_COMMIT;
10950
- const maybeGitBranch = ((_opts$git2 = opts.git) === null || _opts$git2 === void 0 ? void 0 : _opts$git2.branch) || process.env.VAL_GIT_BRANCH;
10961
+ const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
10962
+ const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
10951
10963
  if (!!maybeGitCommit !== !!maybeGitBranch) {
10952
- throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both (the ` + "`git` option, or VAL_GIT_COMMIT and VAL_GIT_BRANCH) for a project " + "whose content is mirrored into a repository, or neither for one " + "whose content service is the store of record." + because);
10964
+ throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both ` + "(`gitCommit` and `gitBranch` in val.config.ts, or VAL_GIT_COMMIT " + "and VAL_GIT_BRANCH) for a project whose content is mirrored into " + "a repository, or neither for one whose content service is the " + "store of record." + because);
10953
10965
  }
10954
10966
  if (!maybeValProject) {
10955
10967
  throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
@@ -16335,6 +16347,44 @@ async function createFixPatch(config, apply, sourcePath, validationError, remote
16335
16347
  fixes: undefined
16336
16348
  });
16337
16349
  }
16350
+ } else if (fix === "view:check-module") {
16351
+ // The schema is the authority: it names the module, and there is exactly
16352
+ // one valid pointer. So this is written rather than reported — nobody has
16353
+ // a decision to make here.
16354
+ const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(sourcePath);
16355
+ if (moduleSource === undefined || moduleSchema === undefined) {
16356
+ remainingErrors.push({
16357
+ ...validationError,
16358
+ message: "Unexpected error while checking a view (no module source or schema)",
16359
+ fixes: undefined
16360
+ });
16361
+ continue;
16362
+ }
16363
+ const {
16364
+ schema: schemaAtPath
16365
+ } = core.Internal.resolvePath(modulePath, moduleSource, moduleSchema);
16366
+ if (schemaAtPath.type !== "view") {
16367
+ remainingErrors.push({
16368
+ ...validationError,
16369
+ message: `Could not fix view: schema at ${sourcePath} is '${schemaAtPath.type}', not a view`,
16370
+ fixes: undefined
16371
+ });
16372
+ continue;
16373
+ }
16374
+ if (apply) {
16375
+ patch$1.push({
16376
+ op: "replace",
16377
+ path: core.Internal.createPatchPath(modulePath),
16378
+ value: {
16379
+ view: schemaAtPath.moduleFilePath
16380
+ }
16381
+ });
16382
+ } else {
16383
+ remainingErrors.push({
16384
+ ...validationError,
16385
+ message: `This view points at the wrong module. Expected '${schemaAtPath.moduleFilePath}'.`
16386
+ });
16387
+ }
16338
16388
  }
16339
16389
  }
16340
16390
  if (!validationError.fixes || validationError.fixes.length === 0) {
@@ -17078,6 +17128,25 @@ async function handleJsonValuesExtractEntry(ctx) {
17078
17128
  * `fixableErrorMessage` rather than a plain error, because the error IS fixable
17079
17129
  * — just not by this command.
17080
17130
  */
17131
+ /**
17132
+ * A view pointer that names a module its schema does not.
17133
+ *
17134
+ * Nothing to look up and nothing to ask: the schema names the module, so the
17135
+ * one correct value is already known. `createFixPatch` writes it — this handler
17136
+ * exists to send it there, and to say what `--fix` would do when it is off.
17137
+ */
17138
+ async function handleViewCheckModule(ctx) {
17139
+ if (!ctx.fix) {
17140
+ return {
17141
+ success: true,
17142
+ fixableErrorMessage: `${ctx.validationError.message}. ` + "Run 'val validate --fix' to point it at the module its schema names."
17143
+ };
17144
+ }
17145
+ return {
17146
+ success: true,
17147
+ shouldApplyPatch: true
17148
+ };
17149
+ }
17081
17150
  async function handleExternalUpload() {
17082
17151
  return {
17083
17152
  success: true,
@@ -17109,7 +17178,8 @@ const currentFixHandlers = {
17109
17178
  "images:check-all-files": handleCheckAllFiles,
17110
17179
  "files:check-all-files": handleCheckAllFiles,
17111
17180
  "jsonValues:extract-entry": handleJsonValuesExtractEntry,
17112
- "external:upload": handleExternalUpload
17181
+ "external:upload": handleExternalUpload,
17182
+ "view:check-module": handleViewCheckModule
17113
17183
  };
17114
17184
  const deprecatedFixHandlers = {
17115
17185
  "image:replace-metadata": handleFileMetadata
@@ -10879,7 +10879,7 @@ async function initHandlerOptions(route, opts, config) {
10879
10879
  valContentUrl
10880
10880
  });
10881
10881
  if (isProxyMode) {
10882
- var _opts$git, _opts$git2, _opts$versions, _opts$versions2;
10882
+ var _opts$versions, _opts$versions2;
10883
10883
  /*
10884
10884
  * Why this app is in http mode, in the message that says what is missing.
10885
10885
  *
@@ -10911,11 +10911,23 @@ async function initHandlerOptions(route, opts, config) {
10911
10911
  * with no line of work to publish to, and a branch without a commit names
10912
10912
  * a line with no position in it; either alone would be a half-configured
10913
10913
  * repository that fails later, at a publish, rather than here.
10914
+ *
10915
+ * ONE NAME, wherever it comes from. `opts` is the bindings'
10916
+ * `{ versions, ...config }`, so `opts.gitCommit` IS `val.config.ts`'s
10917
+ * `gitCommit` -- there is nothing to map and no second place to look.
10918
+ *
10919
+ * It used to be a nested `git: { commit, branch }` here and two flat keys
10920
+ * in `ValConfig`, and the two never met: nothing mapped one onto the
10921
+ * other, so a project that set the documented config keys -- which is
10922
+ * what every Vercel deployment does, from `VERCEL_GIT_COMMIT_SHA` --
10923
+ * resolved to no repository at all. Nothing failed and nothing was
10924
+ * logged; the commit was simply never sent, and every patch it saved
10925
+ * recorded none.
10914
10926
  */
10915
- const maybeGitCommit = ((_opts$git = opts.git) === null || _opts$git === void 0 ? void 0 : _opts$git.commit) || process.env.VAL_GIT_COMMIT;
10916
- const maybeGitBranch = ((_opts$git2 = opts.git) === null || _opts$git2 === void 0 ? void 0 : _opts$git2.branch) || process.env.VAL_GIT_BRANCH;
10927
+ const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
10928
+ const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
10917
10929
  if (!!maybeGitCommit !== !!maybeGitBranch) {
10918
- throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both (the ` + "`git` option, or VAL_GIT_COMMIT and VAL_GIT_BRANCH) for a project " + "whose content is mirrored into a repository, or neither for one " + "whose content service is the store of record." + because);
10930
+ throw new Error(`Val is configured with a git ${maybeGitCommit ? "commit" : "branch"} ` + `but no ${maybeGitCommit ? "branch" : "commit"}. Set both ` + "(`gitCommit` and `gitBranch` in val.config.ts, or VAL_GIT_COMMIT " + "and VAL_GIT_BRANCH) for a project whose content is mirrored into " + "a repository, or neither for one whose content service is the " + "store of record." + because);
10919
10931
  }
10920
10932
  if (!maybeValProject) {
10921
10933
  throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
@@ -16301,6 +16313,44 @@ async function createFixPatch(config, apply, sourcePath, validationError, remote
16301
16313
  fixes: undefined
16302
16314
  });
16303
16315
  }
16316
+ } else if (fix === "view:check-module") {
16317
+ // The schema is the authority: it names the module, and there is exactly
16318
+ // one valid pointer. So this is written rather than reported — nobody has
16319
+ // a decision to make here.
16320
+ const [, modulePath] = Internal.splitModuleFilePathAndModulePath(sourcePath);
16321
+ if (moduleSource === undefined || moduleSchema === undefined) {
16322
+ remainingErrors.push({
16323
+ ...validationError,
16324
+ message: "Unexpected error while checking a view (no module source or schema)",
16325
+ fixes: undefined
16326
+ });
16327
+ continue;
16328
+ }
16329
+ const {
16330
+ schema: schemaAtPath
16331
+ } = Internal.resolvePath(modulePath, moduleSource, moduleSchema);
16332
+ if (schemaAtPath.type !== "view") {
16333
+ remainingErrors.push({
16334
+ ...validationError,
16335
+ message: `Could not fix view: schema at ${sourcePath} is '${schemaAtPath.type}', not a view`,
16336
+ fixes: undefined
16337
+ });
16338
+ continue;
16339
+ }
16340
+ if (apply) {
16341
+ patch.push({
16342
+ op: "replace",
16343
+ path: Internal.createPatchPath(modulePath),
16344
+ value: {
16345
+ view: schemaAtPath.moduleFilePath
16346
+ }
16347
+ });
16348
+ } else {
16349
+ remainingErrors.push({
16350
+ ...validationError,
16351
+ message: `This view points at the wrong module. Expected '${schemaAtPath.moduleFilePath}'.`
16352
+ });
16353
+ }
16304
16354
  }
16305
16355
  }
16306
16356
  if (!validationError.fixes || validationError.fixes.length === 0) {
@@ -17044,6 +17094,25 @@ async function handleJsonValuesExtractEntry(ctx) {
17044
17094
  * `fixableErrorMessage` rather than a plain error, because the error IS fixable
17045
17095
  * — just not by this command.
17046
17096
  */
17097
+ /**
17098
+ * A view pointer that names a module its schema does not.
17099
+ *
17100
+ * Nothing to look up and nothing to ask: the schema names the module, so the
17101
+ * one correct value is already known. `createFixPatch` writes it — this handler
17102
+ * exists to send it there, and to say what `--fix` would do when it is off.
17103
+ */
17104
+ async function handleViewCheckModule(ctx) {
17105
+ if (!ctx.fix) {
17106
+ return {
17107
+ success: true,
17108
+ fixableErrorMessage: `${ctx.validationError.message}. ` + "Run 'val validate --fix' to point it at the module its schema names."
17109
+ };
17110
+ }
17111
+ return {
17112
+ success: true,
17113
+ shouldApplyPatch: true
17114
+ };
17115
+ }
17047
17116
  async function handleExternalUpload() {
17048
17117
  return {
17049
17118
  success: true,
@@ -17075,7 +17144,8 @@ const currentFixHandlers = {
17075
17144
  "images:check-all-files": handleCheckAllFiles,
17076
17145
  "files:check-all-files": handleCheckAllFiles,
17077
17146
  "jsonValues:extract-entry": handleJsonValuesExtractEntry,
17078
- "external:upload": handleExternalUpload
17147
+ "external:upload": handleExternalUpload,
17148
+ "view:check-module": handleViewCheckModule
17079
17149
  };
17080
17150
  const deprecatedFixHandlers = {
17081
17151
  "image:replace-metadata": handleFileMetadata
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "./package.json": "./package.json"
17
17
  },
18
18
  "types": "dist/valbuild-server.cjs.d.ts",
19
- "version": "0.133.0",
19
+ "version": "0.134.0",
20
20
  "devDependencies": {
21
21
  "@prettier/sync": "^0.6.1",
22
22
  "@types/jest": "^30.0.0"
@@ -29,9 +29,9 @@
29
29
  "typescript": "^6.0.3",
30
30
  "zod": "^4.4.3",
31
31
  "zod-validation-error": "^5.0.0",
32
- "@valbuild/core": "0.130.0",
33
- "@valbuild/shared": "0.133.0",
34
- "@valbuild/ui": "0.133.0"
32
+ "@valbuild/core": "0.134.0",
33
+ "@valbuild/shared": "0.134.0",
34
+ "@valbuild/ui": "0.134.0"
35
35
  },
36
36
  "engines": {
37
37
  "node": "^20.19.0 || >=22"