@valbuild/server 0.102.0 → 0.103.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.
@@ -1,4 +1,4 @@
1
- import { FileMetadata, FileSource, ImageMetadata, ModuleFilePath, PatchId, RemoteSource, Schema, SelectorSource, SerializedSchema, Source, SourcePath, ValConfig, ValModules, ValidationError } from "@valbuild/core";
1
+ import { MediaSource, FileMetadata, FileSource, ImageMetadata, ModuleFilePath, PatchId, Schema, SelectorSource, SerializedSchema, Source, SourcePath, ValConfig, ValModules, ValidationError } from "@valbuild/core";
2
2
  import { result } from "@valbuild/core/fp";
3
3
  import { JSONValue, ParentRef, Patch, PatchError } from "@valbuild/core/patch";
4
4
  import { ValSyntaxError, ValSyntaxErrorTree } from "./patch/ts/syntax.js";
@@ -225,9 +225,9 @@ export declare abstract class ValOps {
225
225
  validations: Record<SourcePath, ValidationError[]>;
226
226
  }>;
227
227
  files: Record<SourcePath, FileSource>;
228
- remoteFiles: Record<SourcePath, RemoteSource>;
228
+ remoteFiles: Record<SourcePath, MediaSource>;
229
229
  }>;
230
- validateRemoteFiles(schemas: Schemas, sources: Sources, remoteFiles: Record<SourcePath, RemoteSource>): Promise<Record<SourcePath, ValidationError[]>>;
230
+ validateRemoteFiles(schemas: Schemas, sources: Sources, remoteFiles: Record<SourcePath, MediaSource>): Promise<Record<SourcePath, ValidationError[]>>;
231
231
  validateFiles(schemas: Schemas, sources: Sources, files: Record<SourcePath, FileSource>, fileLastUpdatedByPatchId?: PatchAnalysis["fileLastUpdatedByPatchId"]): Promise<Record<SourcePath, ValidationError[]>>;
232
232
  /**
233
233
  * Applies the pending patches to the source files so they can be committed.
@@ -1,8 +1,19 @@
1
1
  import { FileMetadata, ImageMetadata, SerializedSchema, Source, SourcePath, ValidationError } from "@valbuild/core";
2
- import { Patch } from "@valbuild/core/patch";
2
+ import { JSONValue, Patch } from "@valbuild/core/patch";
3
3
  export type FixPatchRemainingError = ValidationError & {
4
4
  sourcePath?: SourcePath;
5
5
  };
6
+ /**
7
+ * A whole media value, for the fixes that replace one outright.
8
+ *
9
+ * The three remote fixes each wrote this shape out by hand, and one of them was
10
+ * left behind when the shape changed. One name, so the next change cannot miss a
11
+ * site.
12
+ *
13
+ * `path` last is deliberate: it is the field the fix is about, and a stray
14
+ * `path` inside the metadata must not win over it.
15
+ */
16
+ export declare function mediaValue(path: string, metadata: unknown): Record<string, JSONValue>;
6
17
  export declare function createFixPatch(config: {
7
18
  projectRoot: string;
8
19
  remoteHost: string;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The fix handlers behind `val validate --fix`, and the editor quick fixes that
3
+ * must agree with it.
4
+ *
5
+ * ## Why this lives in `@valbuild/server`
6
+ *
7
+ * A fix is two layers. `createFixPatch` is the second: given a validation
8
+ * error it produces a patch. The first is everything that has to happen before a
9
+ * patch can be produced — read the file, check it is actually on disk, extract
10
+ * metadata, pick a remote bucket, upload the bytes, download them back. That
11
+ * layer used to live in `packages/cli/src/runValidation.ts`, which made it
12
+ * reachable only from the CLI: `@valbuild/cli` exports nothing but `./cli`, and
13
+ * `@valbuild/language-server` cannot depend on it anyway without creating a
14
+ * cycle (the CLI depends on the language server).
15
+ *
16
+ * The consequence was that an editor could offer the fixes needing no
17
+ * precondition and had to reimplement or skip the rest. Both happened: the
18
+ * VS Code extension grew its own remote-upload client, and the language server
19
+ * declined to offer remote fixes at all.
20
+ *
21
+ * So the layer sits here, next to `createFixPatch`, and the CLI and the language
22
+ * server are both callers. {@link FixHandlerContext} is deliberately made of
23
+ * things any caller already has — a `Service`, an `IValFSHost`, a project root —
24
+ * rather than of CLI concepts.
25
+ *
26
+ * What stays in the CLI is the driver: the `runValidation` async generator that
27
+ * walks every module, decides what to report, and renders it to a terminal.
28
+ */
29
+ import { ModuleFilePath, SourcePath, ValidationFix } from "@valbuild/core";
30
+ import type { Service } from "./Service.js";
31
+ import type { IValFSHost } from "./ValFSHost.js";
32
+ export type { IValFSHost };
33
+ export type IValRemote = {
34
+ remoteHost: string;
35
+ getSettings(projectName: string, options: {
36
+ pat: string;
37
+ }): Promise<{
38
+ success: true;
39
+ data: {
40
+ publicProjectId: string;
41
+ remoteFileBuckets: {
42
+ bucket: string;
43
+ }[];
44
+ };
45
+ } | {
46
+ success: false;
47
+ message: string;
48
+ }>;
49
+ uploadFile(project: string, bucket: string, fileHash: string, fileExt: string | undefined, fileBuffer: Buffer, options: {
50
+ pat: string;
51
+ }): Promise<{
52
+ success: true;
53
+ } | {
54
+ success: false;
55
+ error: string;
56
+ }>;
57
+ };
58
+ export type ValModule = Awaited<ReturnType<Service["get"]>>;
59
+ export type ValidationError = {
60
+ message: string;
61
+ value?: unknown;
62
+ fixes?: ValidationFix[];
63
+ keyError?: boolean;
64
+ };
65
+ export type FixHandlerContext = {
66
+ sourcePath: SourcePath;
67
+ validationError: ValidationError;
68
+ valModule: ValModule;
69
+ projectRoot: string;
70
+ fix: boolean;
71
+ service: Service;
72
+ valFiles: string[];
73
+ moduleFilePath: ModuleFilePath;
74
+ file: string;
75
+ fs: IValFSHost;
76
+ remoteFiles: Record<SourcePath, {
77
+ ref: string;
78
+ metadata?: Record<string, unknown>;
79
+ }>;
80
+ publicProjectId?: string;
81
+ remoteFileBuckets?: string[];
82
+ remoteFilesCounter: number;
83
+ remote: IValRemote;
84
+ project: string | undefined;
85
+ };
86
+ export type FixHandlerResult = {
87
+ success: boolean;
88
+ errorMessage?: string;
89
+ shouldApplyPatch?: boolean;
90
+ appliedFix?: boolean;
91
+ fixableErrorMessage?: string;
92
+ publicProjectId?: string;
93
+ remoteFileBuckets?: string[];
94
+ remoteFilesCounter?: number;
95
+ events?: ValidationEvent[];
96
+ };
97
+ export type FixHandler = (ctx: FixHandlerContext) => Promise<FixHandlerResult>;
98
+ export type ValidationEvent = {
99
+ type: "file-valid";
100
+ file: string;
101
+ durationMs: number;
102
+ } | {
103
+ type: "file-error-count";
104
+ file: string;
105
+ errorCount: number;
106
+ durationMs: number;
107
+ } | {
108
+ type: "validation-error";
109
+ sourcePath: string;
110
+ message: string;
111
+ keyError?: boolean;
112
+ } | {
113
+ type: "validation-fixable-error";
114
+ sourcePath: string;
115
+ message: string;
116
+ fixable: boolean;
117
+ keyError?: boolean;
118
+ } | {
119
+ type: "unknown-fix";
120
+ sourcePath: string;
121
+ fixes: string[];
122
+ keyError?: boolean;
123
+ } | {
124
+ type: "unregistered-module";
125
+ file: string;
126
+ } | {
127
+ type: "fix-applied";
128
+ file: string;
129
+ sourcePath: string;
130
+ } | {
131
+ type: "fatal-error";
132
+ file: string;
133
+ message: string;
134
+ } | {
135
+ type: "remote-uploading";
136
+ ref: string;
137
+ } | {
138
+ type: "remote-uploaded";
139
+ ref: string;
140
+ } | {
141
+ type: "remote-already-uploaded";
142
+ filePath: string;
143
+ } | {
144
+ type: "remote-downloading";
145
+ sourcePath: string;
146
+ } | {
147
+ type: "summary-errors";
148
+ count: number;
149
+ } | {
150
+ type: "summary-success";
151
+ };
152
+ export declare function handleFileMetadata(ctx: FixHandlerContext): Promise<FixHandlerResult>;
153
+ export declare function handleRemoteFileUpload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
154
+ export declare function handleRemoteGalleryFileUpload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
155
+ export declare function handleRemoteFileDownload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
156
+ export declare function handleRemoteFileCheck(): Promise<FixHandlerResult>;
157
+ export declare function handleUniqueFolderCheck(ctx: FixHandlerContext): Promise<FixHandlerResult>;
158
+ export declare function handleCheckAllFiles(ctx: FixHandlerContext): Promise<FixHandlerResult>;
159
+ export declare function handleJsonValuesExtractEntry(ctx: FixHandlerContext): Promise<FixHandlerResult>;
160
+ export declare const currentFixHandlers: Record<Exclude<ValidationFix, "keyof:check-keys" | "router:check-route">, FixHandler>;
161
+ export declare const fixHandlers: Record<string, FixHandler>;
162
+ export declare function createDefaultValFSHost(): IValFSHost;
@@ -1,2 +1,8 @@
1
1
  import { ValidationError } from "@valbuild/core";
2
+ /**
3
+ * The media path a validation error is about, if it is about media at all.
4
+ *
5
+ * There is no schema in hand here — a `ValidationError` carries only the value
6
+ * it flagged — so the shape is all there is to go on.
7
+ */
2
8
  export declare function getValidationErrorFileRef(validationError: ValidationError): string | null;
@@ -11,6 +11,8 @@ export { formatSyntaxErrorTree } from "./patch/ts/syntax.js";
11
11
  export { analyzeValModule } from "./patch/ts/valModule.js";
12
12
  export type { ValModuleAnalysis } from "./patch/ts/valModule.js";
13
13
  export { createFixPatch } from "./createFixPatch.js";
14
+ export { fixHandlers, currentFixHandlers, createDefaultValFSHost, handleFileMetadata, handleRemoteFileUpload, handleRemoteGalleryFileUpload, handleRemoteFileDownload, handleRemoteFileCheck, handleUniqueFolderCheck, handleCheckAllFiles, handleJsonValuesExtractEntry, } from "./fixHandlers.js";
15
+ export type { FixHandler, FixHandlerContext, FixHandlerResult, IValRemote, ValidationEvent, ValidationError, ValModule, } from "./fixHandlers.js";
14
16
  export * from "./jwt.js";
15
17
  export type { ValServer } from "./ValServer.js";
16
18
  export { getSettings } from "./getSettings.js";
@@ -37,19 +37,5 @@ export declare function deepValidateExpression(value: ts.Expression): result.Res
37
37
  */
38
38
  export declare function evaluateExpression(value: ts.Expression): result.Result<JSONValue, ValSyntaxErrorTree>;
39
39
  export declare function findObjectPropertyAssignment(value: ts.ObjectLiteralExpression, key: string): result.Result<LiteralPropertyAssignment | undefined, ValSyntaxErrorTree>;
40
- export declare function isValFileMethodCall(node: ts.Expression): node is ts.CallExpression;
41
- export declare function isValImageMethodCall(node: ts.Expression): node is ts.CallExpression;
42
- export declare function isValRemoteMethodCall(node: ts.Expression): node is ts.CallExpression;
43
- export declare function findValFileNodeArg(node: ts.CallExpression): result.Result<ts.StringLiteral, ValSyntaxErrorTree>;
44
- export declare function findValRemoteNodeArg(node: ts.CallExpression): result.Result<ts.StringLiteral, ValSyntaxErrorTree>;
45
- export declare function findValImageNodeArg(node: ts.CallExpression): result.Result<ts.StringLiteral, ValSyntaxErrorTree>;
46
- export declare function findValFileMetadataArg(node: ts.CallExpression): result.Result<ts.ObjectLiteralExpression | undefined, ValSyntaxErrorTree>;
47
- export declare function findValImageMetadataArg(node: ts.CallExpression): result.Result<ts.ObjectLiteralExpression | undefined, ValSyntaxErrorTree>;
48
- export declare function findValRemoteMetadataArg(node: ts.CallExpression): result.Result<ts.ObjectLiteralExpression | undefined, ValSyntaxErrorTree>;
49
- /**
50
- * Given a list of expressions, validates that all the expressions are not
51
- * spread elements. In other words, it ensures that the expressions are the
52
- * initializers of the values at their respective indices in the evaluated list.
53
- */
54
40
  export declare function validateInitializers(nodes: ReadonlyArray<ts.Expression>): ValSyntaxErrorTree | undefined;
55
41
  export {};