@valbuild/cli 0.97.7 → 0.98.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/cli/dist/valbuild-cli-cli.cjs.dev.js +73 -172
- package/cli/dist/valbuild-cli-cli.cjs.prod.js +73 -172
- package/cli/dist/valbuild-cli-cli.esm.js +72 -169
- package/package.json +3 -2
- package/src/cli.ts +11 -5
- package/src/connect.ts +2 -4
- package/src/debug/context.ts +2 -4
- package/src/listUnusedFiles.ts +2 -4
- package/src/login.ts +29 -94
- package/src/lsp.ts +19 -0
- package/src/utils/evalValConfigFile.ts +6 -100
- package/src/validate.ts +2 -4
package/src/lsp.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Start the Val language server.
|
|
3
|
+
*
|
|
4
|
+
* Editors normally resolve `@valbuild/language-server` from the project's
|
|
5
|
+
* `node_modules` and launch its `val-language-server` binary directly. This
|
|
6
|
+
* subcommand exists so the server is discoverable from the CLI and easy to
|
|
7
|
+
* start by hand when debugging an editor integration:
|
|
8
|
+
*
|
|
9
|
+
* npx val lsp --stdio
|
|
10
|
+
*
|
|
11
|
+
* The import is dynamic so that `vscode-languageserver` is not loaded on every
|
|
12
|
+
* `val` invocation.
|
|
13
|
+
*/
|
|
14
|
+
export async function lsp(): Promise<void> {
|
|
15
|
+
const { main } = await import("@valbuild/language-server");
|
|
16
|
+
// Transport (`--stdio`, `--node-ipc`, `--socket=`) is read from argv by the
|
|
17
|
+
// server itself, so the flags pass straight through.
|
|
18
|
+
main();
|
|
19
|
+
}
|
|
@@ -1,100 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { createRequire } from "node:module";
|
|
8
|
-
|
|
9
|
-
const ValConfigSchema = z.object({
|
|
10
|
-
project: z.string().optional(),
|
|
11
|
-
root: z.string().optional(),
|
|
12
|
-
files: z
|
|
13
|
-
.object({
|
|
14
|
-
directory: z.string().refine(
|
|
15
|
-
(val): val is `/public` | `/public/${string}` =>
|
|
16
|
-
(val === "/public" ||
|
|
17
|
-
(val.startsWith("/public/") && !val.endsWith("/"))) &&
|
|
18
|
-
// Reject path traversal so the directory cannot escape /public
|
|
19
|
-
!val
|
|
20
|
-
.split("/")
|
|
21
|
-
.some((segment) => segment === "." || segment === ".."),
|
|
22
|
-
{
|
|
23
|
-
message:
|
|
24
|
-
"files.directory must start with '/public', must not end with '/' and must not contain '.' or '..' segments",
|
|
25
|
-
},
|
|
26
|
-
),
|
|
27
|
-
})
|
|
28
|
-
.optional(),
|
|
29
|
-
gitCommit: z.string().optional(),
|
|
30
|
-
gitBranch: z.string().optional(),
|
|
31
|
-
defaultTheme: z.union([z.literal("light"), z.literal("dark")]).optional(),
|
|
32
|
-
ai: z
|
|
33
|
-
.object({
|
|
34
|
-
commitMessages: z
|
|
35
|
-
.object({
|
|
36
|
-
disabled: z.boolean().optional(),
|
|
37
|
-
})
|
|
38
|
-
.optional(),
|
|
39
|
-
})
|
|
40
|
-
.optional(),
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export async function evalValConfigFile(
|
|
44
|
-
projectRoot: string,
|
|
45
|
-
configFileName: string,
|
|
46
|
-
): Promise<ValConfig | null> {
|
|
47
|
-
const valConfigPath = path.join(projectRoot, configFileName);
|
|
48
|
-
|
|
49
|
-
let code: string | null = null;
|
|
50
|
-
try {
|
|
51
|
-
code = await fs.readFile(valConfigPath, "utf-8");
|
|
52
|
-
} catch {
|
|
53
|
-
//
|
|
54
|
-
}
|
|
55
|
-
if (!code) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const transpiled = ts.transpileModule(code, {
|
|
60
|
-
compilerOptions: {
|
|
61
|
-
target: ts.ScriptTarget.ES2020,
|
|
62
|
-
module: ts.ModuleKind.CommonJS,
|
|
63
|
-
esModuleInterop: true,
|
|
64
|
-
},
|
|
65
|
-
fileName: valConfigPath,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const projectRootRequire = createRequire(valConfigPath);
|
|
69
|
-
const exportsObj = {};
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
-
const sandbox: Record<string, any> = {
|
|
72
|
-
exports: exportsObj,
|
|
73
|
-
module: { exports: exportsObj },
|
|
74
|
-
require: projectRootRequire, // NOTE: this is a security risk, but this code is running in the users own environment at the CLI level
|
|
75
|
-
__filename: valConfigPath,
|
|
76
|
-
__dirname: projectRoot,
|
|
77
|
-
console,
|
|
78
|
-
process,
|
|
79
|
-
};
|
|
80
|
-
sandbox.global = sandbox;
|
|
81
|
-
|
|
82
|
-
const context = vm.createContext(sandbox);
|
|
83
|
-
const script = new vm.Script(transpiled.outputText, {
|
|
84
|
-
filename: valConfigPath,
|
|
85
|
-
});
|
|
86
|
-
script.runInContext(context);
|
|
87
|
-
const valConfig = sandbox.module.exports.config;
|
|
88
|
-
if (!valConfig) {
|
|
89
|
-
throw Error(
|
|
90
|
-
`Val config file at path: '${valConfigPath}' must export a config object. Got: ${valConfig}`,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
const result = ValConfigSchema.safeParse(valConfig);
|
|
94
|
-
if (!result.success) {
|
|
95
|
-
throw Error(
|
|
96
|
-
`Val config file at path: '${valConfigPath}' has invalid schema: ${result.error.message}`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
return result.data;
|
|
100
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Moved to `@valbuild/server` so that the CLI and
|
|
3
|
+
* `@valbuild/language-server` resolve project config through the same code.
|
|
4
|
+
* Re-exported here to keep existing CLI imports working.
|
|
5
|
+
*/
|
|
6
|
+
export { evalValConfigFile, findAndEvalValConfigFile } from "@valbuild/server";
|
package/src/validate.ts
CHANGED
|
@@ -4,7 +4,7 @@ import fs from "fs/promises";
|
|
|
4
4
|
import { glob } from "fast-glob";
|
|
5
5
|
import { DEFAULT_CONTENT_HOST, DEFAULT_VAL_REMOTE_HOST } from "@valbuild/core";
|
|
6
6
|
import { getSettings, uploadRemoteFile } from "@valbuild/server";
|
|
7
|
-
import {
|
|
7
|
+
import { findAndEvalValConfigFile } from "./utils/evalValConfigFile";
|
|
8
8
|
import { createDefaultValFSHost, runValidation } from "./runValidation";
|
|
9
9
|
import {
|
|
10
10
|
sourcePathToCodeFrame,
|
|
@@ -49,9 +49,7 @@ export async function validate({
|
|
|
49
49
|
// errors found. Re-reads config and val files each call so it always reflects
|
|
50
50
|
// the latest state on disk (used both for one-shot and watch mode).
|
|
51
51
|
async function runOnce(): Promise<number> {
|
|
52
|
-
const valConfigFile =
|
|
53
|
-
(await evalValConfigFile(projectRoot, "val.config.ts")) ||
|
|
54
|
-
(await evalValConfigFile(projectRoot, "val.config.js"));
|
|
52
|
+
const valConfigFile = await findAndEvalValConfigFile(projectRoot);
|
|
55
53
|
|
|
56
54
|
const resolvedValConfigFile = valConfigFile
|
|
57
55
|
? {
|