vize 0.41.0 → 0.42.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/README.md +53 -1
- package/bin/vize +1 -1
- package/dist/cli.mjs +36 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/{config-DA4uu8ja.d.mts → config-tYKh_ZMu.d.mts} +10 -3
- package/dist/{config-DA4uu8ja.d.mts.map → config-tYKh_ZMu.d.mts.map} +1 -1
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +71 -34
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +21 -17
- package/pkl/vize.pkl +122 -0
- package/schemas/vize.config.schema.json +352 -0
- package/src/cli.ts +55 -4
- package/src/config.ts +100 -41
- package/src/index.ts +8 -1
- package/src/types/core.ts +5 -0
package/src/config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
5
|
import { transform } from "oxc-transform";
|
|
5
6
|
import type {
|
|
6
7
|
VizeConfig,
|
|
@@ -11,18 +12,29 @@ import type {
|
|
|
11
12
|
GlobalTypeDeclaration,
|
|
12
13
|
} from "./types/index.js";
|
|
13
14
|
|
|
14
|
-
const CONFIG_FILE_NAMES = [
|
|
15
|
+
export const CONFIG_FILE_NAMES = [
|
|
15
16
|
"vize.config.ts",
|
|
16
17
|
"vize.config.js",
|
|
17
18
|
"vize.config.mjs",
|
|
19
|
+
"vize.config.pkl",
|
|
18
20
|
"vize.config.json",
|
|
19
|
-
];
|
|
21
|
+
] as const;
|
|
20
22
|
|
|
21
23
|
const DEFAULT_CONFIG_ENV: ConfigEnv = {
|
|
22
24
|
mode: "development",
|
|
23
25
|
command: "serve",
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
const PACKAGE_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
|
|
29
|
+
|
|
30
|
+
export const VIZE_CONFIG_JSON_SCHEMA_PATH = path.join(
|
|
31
|
+
PACKAGE_ROOT,
|
|
32
|
+
"schemas",
|
|
33
|
+
"vize.config.schema.json",
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const VIZE_CONFIG_PKL_SCHEMA_PATH = path.join(PACKAGE_ROOT, "pkl", "vize.pkl");
|
|
37
|
+
|
|
26
38
|
/**
|
|
27
39
|
* Define a Vize configuration with type checking.
|
|
28
40
|
* Accepts a plain object or a function that receives ConfigEnv.
|
|
@@ -32,7 +44,7 @@ export function defineConfig(config: UserConfigExport): UserConfigExport {
|
|
|
32
44
|
}
|
|
33
45
|
|
|
34
46
|
/**
|
|
35
|
-
* Load vize.config
|
|
47
|
+
* Load `vize.config.*` from the specified directory.
|
|
36
48
|
*/
|
|
37
49
|
export async function loadConfig(
|
|
38
50
|
root: string,
|
|
@@ -44,7 +56,6 @@ export async function loadConfig(
|
|
|
44
56
|
return null;
|
|
45
57
|
}
|
|
46
58
|
|
|
47
|
-
// Custom config file path
|
|
48
59
|
if (configFile) {
|
|
49
60
|
const absolutePath = path.isAbsolute(configFile) ? configFile : path.resolve(root, configFile);
|
|
50
61
|
if (fs.existsSync(absolutePath)) {
|
|
@@ -53,7 +64,6 @@ export async function loadConfig(
|
|
|
53
64
|
return null;
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
// Search for config file
|
|
57
67
|
if (mode === "auto") {
|
|
58
68
|
const configPath = findConfigFileAuto(root);
|
|
59
69
|
if (!configPath) {
|
|
@@ -62,17 +72,14 @@ export async function loadConfig(
|
|
|
62
72
|
return loadConfigFile(configPath, env);
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
// mode === "root"
|
|
66
75
|
const configPath = findConfigFileInDir(root);
|
|
67
76
|
if (!configPath) {
|
|
68
77
|
return null;
|
|
69
78
|
}
|
|
79
|
+
|
|
70
80
|
return loadConfigFile(configPath, env);
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
/**
|
|
74
|
-
* Find config file in a specific directory
|
|
75
|
-
*/
|
|
76
83
|
function findConfigFileInDir(dir: string): string | null {
|
|
77
84
|
for (const name of CONFIG_FILE_NAMES) {
|
|
78
85
|
const filePath = path.join(dir, name);
|
|
@@ -83,27 +90,24 @@ function findConfigFileInDir(dir: string): string | null {
|
|
|
83
90
|
return null;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
/**
|
|
87
|
-
* Find config file by searching from cwd upward
|
|
88
|
-
*/
|
|
89
93
|
function findConfigFileAuto(startDir: string): string | null {
|
|
90
94
|
let currentDir = path.resolve(startDir);
|
|
91
|
-
const root = path.parse(currentDir).root;
|
|
92
95
|
|
|
93
|
-
while (
|
|
96
|
+
while (true) {
|
|
94
97
|
const configPath = findConfigFileInDir(currentDir);
|
|
95
98
|
if (configPath) {
|
|
96
99
|
return configPath;
|
|
97
100
|
}
|
|
98
|
-
currentDir = path.dirname(currentDir);
|
|
99
|
-
}
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
const parentDir = path.dirname(currentDir);
|
|
103
|
+
if (parentDir === currentDir) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
currentDir = parentDir;
|
|
108
|
+
}
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
/**
|
|
105
|
-
* Load and evaluate a config file
|
|
106
|
-
*/
|
|
107
111
|
async function loadConfigFile(filePath: string, env?: ConfigEnv): Promise<VizeConfig | null> {
|
|
108
112
|
if (!fs.existsSync(filePath)) {
|
|
109
113
|
return null;
|
|
@@ -113,20 +117,20 @@ async function loadConfigFile(filePath: string, env?: ConfigEnv): Promise<VizeCo
|
|
|
113
117
|
|
|
114
118
|
if (ext === ".json") {
|
|
115
119
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
116
|
-
return
|
|
120
|
+
return parseJsonConfig(content, filePath);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (ext === ".pkl") {
|
|
124
|
+
return loadPklConfig(filePath);
|
|
117
125
|
}
|
|
118
126
|
|
|
119
127
|
if (ext === ".ts") {
|
|
120
128
|
return loadTypeScriptConfig(filePath, env);
|
|
121
129
|
}
|
|
122
130
|
|
|
123
|
-
// .js, .mjs - ESM
|
|
124
131
|
return loadESMConfig(filePath, env);
|
|
125
132
|
}
|
|
126
133
|
|
|
127
|
-
/**
|
|
128
|
-
* Resolve a UserConfigExport to a VizeConfig
|
|
129
|
-
*/
|
|
130
134
|
async function resolveConfigExport(
|
|
131
135
|
exported: UserConfigExport,
|
|
132
136
|
env?: ConfigEnv,
|
|
@@ -134,12 +138,10 @@ async function resolveConfigExport(
|
|
|
134
138
|
if (typeof exported === "function") {
|
|
135
139
|
return exported(env ?? DEFAULT_CONFIG_ENV);
|
|
136
140
|
}
|
|
141
|
+
|
|
137
142
|
return exported;
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
/**
|
|
141
|
-
* Load TypeScript config file using oxc-transform
|
|
142
|
-
*/
|
|
143
145
|
async function loadTypeScriptConfig(filePath: string, env?: ConfigEnv): Promise<VizeConfig> {
|
|
144
146
|
const source = fs.readFileSync(filePath, "utf-8");
|
|
145
147
|
const result = transform(filePath, source, {
|
|
@@ -148,32 +150,89 @@ async function loadTypeScriptConfig(filePath: string, env?: ConfigEnv): Promise<
|
|
|
148
150
|
},
|
|
149
151
|
});
|
|
150
152
|
|
|
151
|
-
const code = result.code;
|
|
152
|
-
|
|
153
|
-
// Write to temp file and import (use Date.now() to avoid race conditions)
|
|
154
153
|
const tempFile = filePath.replace(/\.ts$/, `.temp.${Date.now()}.mjs`);
|
|
155
|
-
fs.writeFileSync(tempFile, code);
|
|
154
|
+
fs.writeFileSync(tempFile, result.code);
|
|
156
155
|
|
|
157
156
|
try {
|
|
158
|
-
const
|
|
159
|
-
const module = await import(fileUrl);
|
|
157
|
+
const module = await importFresh(tempFile);
|
|
160
158
|
const exported: UserConfigExport = module.default || module;
|
|
161
159
|
return resolveConfigExport(exported, env);
|
|
162
160
|
} finally {
|
|
163
|
-
fs.
|
|
161
|
+
fs.rmSync(tempFile, { force: true });
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
164
|
|
|
167
|
-
/**
|
|
168
|
-
* Load ESM config file
|
|
169
|
-
*/
|
|
170
165
|
async function loadESMConfig(filePath: string, env?: ConfigEnv): Promise<VizeConfig> {
|
|
171
|
-
const
|
|
172
|
-
const module = await import(fileUrl);
|
|
166
|
+
const module = await importFresh(filePath);
|
|
173
167
|
const exported: UserConfigExport = module.default || module;
|
|
174
168
|
return resolveConfigExport(exported, env);
|
|
175
169
|
}
|
|
176
170
|
|
|
171
|
+
function loadPklConfig(filePath: string): VizeConfig {
|
|
172
|
+
try {
|
|
173
|
+
const output = execFileSync("pkl", ["eval", "--format", "json", filePath], {
|
|
174
|
+
cwd: path.dirname(filePath),
|
|
175
|
+
encoding: "utf-8",
|
|
176
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
177
|
+
});
|
|
178
|
+
return parseJsonConfig(output, filePath);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`Failed to evaluate PKL config at ${filePath}. Make sure the 'pkl' CLI is installed and on PATH. ${getErrorMessage(error)}`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function importFresh(filePath: string): Promise<Record<string, unknown>> {
|
|
187
|
+
const fileUrl = pathToFileURL(filePath);
|
|
188
|
+
fileUrl.searchParams.set("t", String(fs.statSync(filePath).mtimeMs));
|
|
189
|
+
return import(fileUrl.href);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function parseJsonConfig(content: string, filePath: string): VizeConfig {
|
|
193
|
+
try {
|
|
194
|
+
return normalizeLoadedConfig(JSON.parse(content));
|
|
195
|
+
} catch (error) {
|
|
196
|
+
throw new Error(`Failed to parse vize config JSON at ${filePath}: ${getErrorMessage(error)}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function normalizeLoadedConfig(config: unknown): VizeConfig {
|
|
201
|
+
const normalized = stripNullish(config);
|
|
202
|
+
return (normalized ?? {}) as VizeConfig;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function stripNullish(value: unknown): unknown {
|
|
206
|
+
if (value === null) {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (Array.isArray(value)) {
|
|
211
|
+
return value.map((entry) => stripNullish(entry)).filter((entry) => entry !== undefined);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (typeof value === "object" && value !== null) {
|
|
215
|
+
const result: Record<string, unknown> = {};
|
|
216
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
217
|
+
const normalizedEntry = stripNullish(entry);
|
|
218
|
+
if (normalizedEntry !== undefined) {
|
|
219
|
+
result[key] = normalizedEntry;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function getErrorMessage(error: unknown): string {
|
|
229
|
+
if (error instanceof Error) {
|
|
230
|
+
return error.message;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return String(error);
|
|
234
|
+
}
|
|
235
|
+
|
|
177
236
|
/**
|
|
178
237
|
* Normalize GlobalTypesConfig shorthand strings to GlobalTypeDeclaration objects
|
|
179
238
|
*/
|
package/src/index.ts
CHANGED
|
@@ -31,4 +31,11 @@ export type {
|
|
|
31
31
|
} from "./types/index.js";
|
|
32
32
|
|
|
33
33
|
// Config utilities
|
|
34
|
-
export {
|
|
34
|
+
export {
|
|
35
|
+
CONFIG_FILE_NAMES,
|
|
36
|
+
VIZE_CONFIG_JSON_SCHEMA_PATH,
|
|
37
|
+
VIZE_CONFIG_PKL_SCHEMA_PATH,
|
|
38
|
+
defineConfig,
|
|
39
|
+
loadConfig,
|
|
40
|
+
normalizeGlobalTypes,
|
|
41
|
+
} from "./config.js";
|
package/src/types/core.ts
CHANGED
|
@@ -36,6 +36,11 @@ export type LintPreset = "happy-path" | "opinionated" | "essential" | "nuxt";
|
|
|
36
36
|
* Vize configuration options
|
|
37
37
|
*/
|
|
38
38
|
export interface VizeConfig {
|
|
39
|
+
/**
|
|
40
|
+
* JSON Schema reference for editor autocompletion.
|
|
41
|
+
*/
|
|
42
|
+
$schema?: string;
|
|
43
|
+
|
|
39
44
|
/**
|
|
40
45
|
* Vue compiler options
|
|
41
46
|
*/
|