vize 0.291.0 → 0.303.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,12 +1,12 @@
1
1
  import { createRequire } from "node:module";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
2
+ import * as fs$1 from "node:fs";
3
+ import * as path$1 from "node:path";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { transform } from "oxc-transform";
7
7
  import { execFileSync } from "node:child_process";
8
8
  //#region src/config/pkl.js
9
- const PACKAGE_ROOT$1 = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "../..");
9
+ const PACKAGE_ROOT$1 = path$1.resolve(fileURLToPath(new URL(".", import.meta.url)), "../..");
10
10
  const DOCUMENTED_PKL_SCHEMA_IMPORT_RE = /^(\s*(?:amends|import)\s+)(["'])node_modules\/vize\/pkl\/(VizeConfig\.pkl|vize\.pkl)\2/gm;
11
11
  /**
12
12
  * Evaluate a `vize.config.pkl` file and return its JSON representation.
@@ -33,7 +33,7 @@ function loadPklConfigJson(filePath) {
33
33
  "json",
34
34
  evalFilePath
35
35
  ], {
36
- cwd: path.dirname(filePath),
36
+ cwd: path$1.dirname(filePath),
37
37
  encoding: "utf-8",
38
38
  stdio: [
39
39
  "ignore",
@@ -45,21 +45,21 @@ function loadPklConfigJson(filePath) {
45
45
  } catch (error) {
46
46
  throw new Error(`Failed to evaluate vize PKL config at ${filePath}: ${getErrorMessage$1(error)}`);
47
47
  } finally {
48
- if (patchedFilePath) fs.rmSync(patchedFilePath, { force: true });
48
+ if (patchedFilePath) fs$1.rmSync(patchedFilePath, { force: true });
49
49
  }
50
50
  }
51
51
  function findPklBinary() {
52
52
  try {
53
53
  const pklPkgPath = import.meta.resolve?.("@pkl-community/pkl");
54
54
  if (pklPkgPath) {
55
- const pklLibDir = path.dirname(fileURLToPath(pklPkgPath));
56
- const pklPackageDir = path.dirname(pklLibDir);
55
+ const pklLibDir = path$1.dirname(fileURLToPath(pklPkgPath));
56
+ const pklPackageDir = path$1.dirname(pklLibDir);
57
57
  const candidates = [
58
- path.join(pklLibDir, "main.js"),
59
- path.join(pklPackageDir, "pkl"),
60
- path.join(pklPackageDir, "pkl.exe")
58
+ path$1.join(pklLibDir, "main.js"),
59
+ path$1.join(pklPackageDir, "pkl"),
60
+ path$1.join(pklPackageDir, "pkl.exe")
61
61
  ];
62
- for (const candidate of candidates) if (fs.existsSync(candidate)) try {
62
+ for (const candidate of candidates) if (fs$1.existsSync(candidate)) try {
63
63
  execFileSync(candidate, ["--version"], { stdio: "ignore" });
64
64
  return candidate;
65
65
  } catch {}
@@ -73,20 +73,20 @@ function findPklBinary() {
73
73
  }
74
74
  }
75
75
  function createPklConfigWithBundledSchemaImports(filePath) {
76
- const configDir = path.dirname(filePath);
77
- const source = fs.readFileSync(filePath, "utf-8");
76
+ const configDir = path$1.dirname(filePath);
77
+ const source = fs$1.readFileSync(filePath, "utf-8");
78
78
  let patched = false;
79
79
  const content = source.replace(DOCUMENTED_PKL_SCHEMA_IMPORT_RE, (match, prefix, quote, schemaFile) => {
80
- const projectSchemaPath = path.join(configDir, "node_modules", "vize", "pkl", schemaFile);
81
- if (fs.existsSync(projectSchemaPath)) return match;
82
- const bundledSchemaPath = path.join(PACKAGE_ROOT$1, "pkl", schemaFile);
83
- if (!fs.existsSync(bundledSchemaPath)) return match;
80
+ const projectSchemaPath = path$1.join(configDir, "node_modules", "vize", "pkl", schemaFile);
81
+ if (fs$1.existsSync(projectSchemaPath)) return match;
82
+ const bundledSchemaPath = path$1.join(PACKAGE_ROOT$1, "pkl", schemaFile);
83
+ if (!fs$1.existsSync(bundledSchemaPath)) return match;
84
84
  patched = true;
85
85
  return `${prefix}${quote}${pathToFileURL(bundledSchemaPath).href}${quote}`;
86
86
  });
87
87
  if (!patched) return null;
88
- const tempFile = path.join(configDir, `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.pkl`);
89
- fs.writeFileSync(tempFile, content, {
88
+ const tempFile = path$1.join(configDir, `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.pkl`);
89
+ fs$1.writeFileSync(tempFile, content, {
90
90
  flag: "wx",
91
91
  mode: 384
92
92
  });
@@ -110,9 +110,9 @@ const DEFAULT_CONFIG_ENV = {
110
110
  mode: "development",
111
111
  command: "serve"
112
112
  };
113
- const PACKAGE_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
114
- const VIZE_CONFIG_JSON_SCHEMA_PATH = path.join(PACKAGE_ROOT, "schemas", "vize.config.schema.json");
115
- const VIZE_CONFIG_PKL_SCHEMA_PATH = path.join(PACKAGE_ROOT, "pkl", "vize.pkl");
113
+ const PACKAGE_ROOT = path$1.resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
114
+ const VIZE_CONFIG_JSON_SCHEMA_PATH = path$1.join(PACKAGE_ROOT, "schemas", "vize.config.schema.json");
115
+ const VIZE_CONFIG_PKL_SCHEMA_PATH = path$1.join(PACKAGE_ROOT, "pkl", "vize.pkl");
116
116
  /**
117
117
  * Define a Vize configuration with type checking.
118
118
  * Accepts a plain object or a function that receives ConfigEnv.
@@ -127,8 +127,8 @@ async function loadConfig(root, options = {}) {
127
127
  const { mode = "root", configFile, env } = options;
128
128
  if (mode === "none") return null;
129
129
  if (configFile) {
130
- const absolutePath = path.isAbsolute(configFile) ? configFile : path.resolve(root, configFile);
131
- if (fs.existsSync(absolutePath)) return loadConfigFile(absolutePath, env);
130
+ const absolutePath = path$1.isAbsolute(configFile) ? configFile : path$1.resolve(root, configFile);
131
+ if (fs$1.existsSync(absolutePath)) return loadConfigFile(absolutePath, env);
132
132
  return null;
133
133
  }
134
134
  if (mode === "auto") return loadConfigFromDirAuto(root, env);
@@ -136,29 +136,29 @@ async function loadConfig(root, options = {}) {
136
136
  }
137
137
  async function loadConfigFromDir(dir, env) {
138
138
  for (const name of CONFIG_FILE_NAMES) {
139
- const filePath = path.join(dir, name);
140
- if (!fs.existsSync(filePath)) continue;
139
+ const filePath = path$1.join(dir, name);
140
+ if (!fs$1.existsSync(filePath)) continue;
141
141
  const config = await loadConfigFile(filePath, env);
142
142
  if (config !== null) return config;
143
143
  }
144
144
  return null;
145
145
  }
146
146
  async function loadConfigFromDirAuto(startDir, env) {
147
- let currentDir = path.resolve(startDir);
147
+ let currentDir = path$1.resolve(startDir);
148
148
  while (true) {
149
149
  const config = await loadConfigFromDir(currentDir, env);
150
150
  if (config !== null) return config;
151
- const parentDir = path.dirname(currentDir);
151
+ const parentDir = path$1.dirname(currentDir);
152
152
  if (parentDir === currentDir) return null;
153
153
  currentDir = parentDir;
154
154
  }
155
155
  }
156
156
  async function loadConfigFile(filePath, env) {
157
- const absolutePath = path.resolve(filePath);
158
- if (!fs.existsSync(absolutePath)) return null;
159
- const ext = path.extname(absolutePath);
157
+ const absolutePath = path$1.resolve(filePath);
158
+ if (!fs$1.existsSync(absolutePath)) return null;
159
+ const ext = path$1.extname(absolutePath);
160
160
  if (ext === ".pkl") return loadPklConfig(absolutePath);
161
- if (ext === ".json") return parseJsonConfig(fs.readFileSync(absolutePath, "utf-8"), absolutePath);
161
+ if (ext === ".json") return parseJsonConfig(fs$1.readFileSync(absolutePath, "utf-8"), absolutePath);
162
162
  if (ext === ".ts") return loadTypeScriptConfig(absolutePath, env);
163
163
  return loadESMConfig(absolutePath, env);
164
164
  }
@@ -171,9 +171,9 @@ async function resolveConfigExport(exported, env) {
171
171
  return normalizeLoadedConfig(exported);
172
172
  }
173
173
  async function loadTypeScriptConfig(filePath, env) {
174
- const result = await transform(filePath, fs.readFileSync(filePath, "utf-8"), { typescript: { onlyRemoveTypeImports: true } });
175
- const tempFile = path.join(path.dirname(filePath), `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.mjs`);
176
- fs.writeFileSync(tempFile, result.code, {
174
+ const result = await transform(filePath, fs$1.readFileSync(filePath, "utf-8"), { typescript: { onlyRemoveTypeImports: true } });
175
+ const tempFile = path$1.join(path$1.dirname(filePath), `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.mjs`);
176
+ fs$1.writeFileSync(tempFile, result.code, {
177
177
  flag: "wx",
178
178
  mode: 384
179
179
  });
@@ -181,7 +181,7 @@ async function loadTypeScriptConfig(filePath, env) {
181
181
  const module = await importFresh(tempFile);
182
182
  return resolveConfigExport(module.default || module, env);
183
183
  } finally {
184
- fs.rmSync(tempFile, { force: true });
184
+ fs$1.rmSync(tempFile, { force: true });
185
185
  }
186
186
  }
187
187
  async function loadESMConfig(filePath, env) {
@@ -190,7 +190,7 @@ async function loadESMConfig(filePath, env) {
190
190
  }
191
191
  async function importFresh(filePath) {
192
192
  const fileUrl = pathToFileURL(filePath);
193
- fileUrl.searchParams.set("t", String(fs.statSync(filePath).mtimeMs));
193
+ fileUrl.searchParams.set("t", String(fs$1.statSync(filePath).mtimeMs));
194
194
  return import(fileUrl.href);
195
195
  }
196
196
  function parseJsonConfig(content, filePath) {
@@ -220,4 +220,4 @@ function normalizeGlobalTypes(config) {
220
220
  //#endregion
221
221
  export { loadConfig as a, defineConfig as i, VIZE_CONFIG_JSON_SCHEMA_PATH as n, normalizeGlobalTypes as o, VIZE_CONFIG_PKL_SCHEMA_PATH as r, resolveConfigExport as s, CONFIG_FILE_NAMES as t };
222
222
 
223
- //# sourceMappingURL=config-D1BwAgHh.mjs.map
223
+ //# sourceMappingURL=config-CqEev07u.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-CqEev07u.mjs","names":["PACKAGE_ROOT","path","getErrorMessage","fs","path","fs"],"sources":["../src/config/pkl.js","../src/config.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { execFileSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\nconst PACKAGE_ROOT = path.resolve(fileURLToPath(new URL(\".\", import.meta.url)), \"../..\");\n\nconst DOCUMENTED_PKL_SCHEMA_IMPORT_RE =\n /^(\\s*(?:amends|import)\\s+)([\"'])node_modules\\/vize\\/pkl\\/(VizeConfig\\.pkl|vize\\.pkl)\\2/gm;\n\n/**\n * Evaluate a `vize.config.pkl` file and return its JSON representation.\n *\n * The npm-facing loader keeps PKL execution in Node because it needs package\n * resolution for `@pkl-community/pkl`, but all structural config normalization\n * happens in Rust after this function returns. A missing PKL runtime returns\n * `null` so config discovery can fall through to lower-priority formats; an\n * evaluation failure throws because a present PKL config should not silently be\n * ignored.\n */\nexport function loadPklConfigJson(filePath) {\n const pklBin = findPklBinary();\n if (!pklBin) {\n console.warn(\n \"[vize] pkl CLI not found. Install @pkl-community/pkl or add pkl to PATH. \" +\n \"Falling back to the next config format.\",\n );\n return null;\n }\n\n const patchedFilePath = createPklConfigWithBundledSchemaImports(filePath);\n const evalFilePath = patchedFilePath ?? filePath;\n try {\n return execFileSync(pklBin, [\"eval\", \"-f\", \"json\", evalFilePath], {\n cwd: path.dirname(filePath),\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 30_000,\n });\n } catch (error) {\n throw new Error(`Failed to evaluate vize PKL config at ${filePath}: ${getErrorMessage(error)}`);\n } finally {\n if (patchedFilePath) {\n fs.rmSync(patchedFilePath, { force: true });\n }\n }\n}\n\nfunction findPklBinary() {\n try {\n const pklPkgPath = import.meta.resolve?.(\"@pkl-community/pkl\");\n if (pklPkgPath) {\n const pklLibDir = path.dirname(fileURLToPath(pklPkgPath));\n const pklPackageDir = path.dirname(pklLibDir);\n const candidates = [\n path.join(pklLibDir, \"main.js\"),\n path.join(pklPackageDir, \"pkl\"),\n path.join(pklPackageDir, \"pkl.exe\"),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n try {\n execFileSync(candidate, [\"--version\"], { stdio: \"ignore\" });\n return candidate;\n } catch {\n // Keep looking: the shim can exist when its runtime is unavailable.\n }\n }\n }\n }\n } catch {\n // Fall back to PATH below.\n }\n\n try {\n execFileSync(\"pkl\", [\"--version\"], { stdio: \"ignore\" });\n return \"pkl\";\n } catch {\n return null;\n }\n}\n\nfunction createPklConfigWithBundledSchemaImports(filePath) {\n const configDir = path.dirname(filePath);\n const source = fs.readFileSync(filePath, \"utf-8\");\n let patched = false;\n\n const content = source.replace(\n DOCUMENTED_PKL_SCHEMA_IMPORT_RE,\n (match, prefix, quote, schemaFile) => {\n const projectSchemaPath = path.join(configDir, \"node_modules\", \"vize\", \"pkl\", schemaFile);\n if (fs.existsSync(projectSchemaPath)) {\n return match;\n }\n\n const bundledSchemaPath = path.join(PACKAGE_ROOT, \"pkl\", schemaFile);\n if (!fs.existsSync(bundledSchemaPath)) {\n return match;\n }\n\n patched = true;\n return `${prefix}${quote}${pathToFileURL(bundledSchemaPath).href}${quote}`;\n },\n );\n\n if (!patched) {\n return null;\n }\n\n const tempFile = path.join(\n configDir,\n `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.pkl`,\n );\n fs.writeFileSync(tempFile, content, { flag: \"wx\", mode: 0o600 });\n return tempFile;\n}\n\nfunction getErrorMessage(error) {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { transform } from \"oxc-transform\";\nimport type {\n ResolvedVizeConfig,\n LoadConfigOptions,\n UserConfigExport,\n ConfigEnv,\n GlobalTypesConfig,\n GlobalTypeDeclaration,\n} from \"./types/index.js\";\nimport { loadPklConfigJson } from \"./config/pkl.js\";\n\ntype NativeConfigHelpers = {\n normalizeVizeConfig(value: unknown): unknown;\n};\n\nconst require = createRequire(import.meta.url);\nconst native = require(\"@vizejs/native\") as NativeConfigHelpers;\n\nexport const CONFIG_FILE_NAMES = [\n \"vize.config.pkl\",\n \"vize.config.ts\",\n \"vize.config.js\",\n \"vize.config.mjs\",\n \"vize.config.json\",\n] as const;\n\nconst DEFAULT_CONFIG_ENV: ConfigEnv = {\n mode: \"development\",\n command: \"serve\",\n};\n\nconst PACKAGE_ROOT = path.resolve(fileURLToPath(new URL(\".\", import.meta.url)), \"..\");\n\nexport const VIZE_CONFIG_JSON_SCHEMA_PATH = path.join(\n PACKAGE_ROOT,\n \"schemas\",\n \"vize.config.schema.json\",\n);\n\nexport const VIZE_CONFIG_PKL_SCHEMA_PATH = path.join(PACKAGE_ROOT, \"pkl\", \"vize.pkl\");\n\n/**\n * Define a Vize configuration with type checking.\n * Accepts a plain object or a function that receives ConfigEnv.\n */\nexport function defineConfig(config: UserConfigExport): UserConfigExport {\n return config;\n}\n\n/**\n * Load `vize.config.*` from the specified directory.\n */\nexport async function loadConfig(\n root: string,\n options: LoadConfigOptions = {},\n): Promise<ResolvedVizeConfig | null> {\n const { mode = \"root\", configFile, env } = options;\n\n if (mode === \"none\") {\n return null;\n }\n\n if (configFile) {\n const absolutePath = path.isAbsolute(configFile) ? configFile : path.resolve(root, configFile);\n if (fs.existsSync(absolutePath)) {\n return loadConfigFile(absolutePath, env);\n }\n return null;\n }\n\n if (mode === \"auto\") {\n return loadConfigFromDirAuto(root, env);\n }\n\n return loadConfigFromDir(root, env);\n}\n\nasync function loadConfigFromDir(dir: string, env?: ConfigEnv): Promise<ResolvedVizeConfig | null> {\n for (const name of CONFIG_FILE_NAMES) {\n const filePath = path.join(dir, name);\n if (!fs.existsSync(filePath)) {\n continue;\n }\n\n const config = await loadConfigFile(filePath, env);\n if (config !== null) {\n return config;\n }\n }\n return null;\n}\n\nasync function loadConfigFromDirAuto(\n startDir: string,\n env?: ConfigEnv,\n): Promise<ResolvedVizeConfig | null> {\n let currentDir = path.resolve(startDir);\n\n while (true) {\n const config = await loadConfigFromDir(currentDir, env);\n if (config !== null) {\n return config;\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nasync function loadConfigFile(\n filePath: string,\n env?: ConfigEnv,\n): Promise<ResolvedVizeConfig | null> {\n const absolutePath = path.resolve(filePath);\n if (!fs.existsSync(absolutePath)) {\n return null;\n }\n\n const ext = path.extname(absolutePath);\n\n if (ext === \".pkl\") {\n return loadPklConfig(absolutePath);\n }\n\n if (ext === \".json\") {\n const content = fs.readFileSync(absolutePath, \"utf-8\");\n return parseJsonConfig(content, absolutePath);\n }\n\n if (ext === \".ts\") {\n return loadTypeScriptConfig(absolutePath, env);\n }\n\n return loadESMConfig(absolutePath, env);\n}\n\nfunction loadPklConfig(filePath: string): ResolvedVizeConfig | null {\n const output = loadPklConfigJson(filePath);\n return output === null ? null : parseJsonConfig(output, filePath);\n}\n\nexport async function resolveConfigExport(\n exported: UserConfigExport,\n env?: ConfigEnv,\n): Promise<ResolvedVizeConfig> {\n if (typeof exported === \"function\") {\n return normalizeLoadedConfig(await exported(env ?? DEFAULT_CONFIG_ENV));\n }\n\n return normalizeLoadedConfig(exported);\n}\n\nasync function loadTypeScriptConfig(\n filePath: string,\n env?: ConfigEnv,\n): Promise<ResolvedVizeConfig> {\n const source = fs.readFileSync(filePath, \"utf-8\");\n const result = await transform(filePath, source, {\n typescript: {\n onlyRemoveTypeImports: true,\n },\n });\n\n const tempFile = path.join(\n path.dirname(filePath),\n `.vize-config-${process.pid}-${Date.now()}-${randomUUID()}.mjs`,\n );\n fs.writeFileSync(tempFile, result.code, { flag: \"wx\", mode: 0o600 });\n\n try {\n const module = await importFresh(tempFile);\n const exported: UserConfigExport = module.default || module;\n return resolveConfigExport(exported, env);\n } finally {\n fs.rmSync(tempFile, { force: true });\n }\n}\n\nasync function loadESMConfig(filePath: string, env?: ConfigEnv): Promise<ResolvedVizeConfig> {\n const module = await importFresh(filePath);\n const exported: UserConfigExport = module.default || module;\n return resolveConfigExport(exported, env);\n}\n\nasync function importFresh(filePath: string): Promise<Record<string, unknown>> {\n const fileUrl = pathToFileURL(filePath);\n fileUrl.searchParams.set(\"t\", String(fs.statSync(filePath).mtimeMs));\n return import(fileUrl.href);\n}\n\nfunction parseJsonConfig(content: string, filePath: string): ResolvedVizeConfig {\n try {\n return normalizeLoadedConfig(JSON.parse(content));\n } catch (error) {\n throw new Error(`Failed to parse vize config JSON at ${filePath}: ${getErrorMessage(error)}`);\n }\n}\n\nfunction normalizeLoadedConfig(config: unknown): ResolvedVizeConfig {\n return native.normalizeVizeConfig(config ?? null) as ResolvedVizeConfig;\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n\n/**\n * Normalize GlobalTypesConfig shorthand strings to GlobalTypeDeclaration objects\n */\nexport function normalizeGlobalTypes(\n config: GlobalTypesConfig,\n): Record<string, GlobalTypeDeclaration> {\n const resolvedConfig =\n \"types\" in config &&\n typeof config.types === \"object\" &&\n config.types !== null &&\n !Array.isArray(config.types)\n ? config.types\n : config;\n\n const result: Record<string, GlobalTypeDeclaration> = {};\n for (const [key, value] of Object.entries(resolvedConfig)) {\n if (typeof value === \"string\") {\n result[key] = { type: value };\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n"],"mappings":"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"}
package/dist/config.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as loadConfig, i as defineConfig, n as VIZE_CONFIG_JSON_SCHEMA_PATH, o as normalizeGlobalTypes, r as VIZE_CONFIG_PKL_SCHEMA_PATH, s as resolveConfigExport, t as CONFIG_FILE_NAMES } from "./config-D1BwAgHh.mjs";
1
+ import { a as loadConfig, i as defineConfig, n as VIZE_CONFIG_JSON_SCHEMA_PATH, o as normalizeGlobalTypes, r as VIZE_CONFIG_PKL_SCHEMA_PATH, s as resolveConfigExport, t as CONFIG_FILE_NAMES } from "./config-CqEev07u.mjs";
2
2
  export { CONFIG_FILE_NAMES, VIZE_CONFIG_JSON_SCHEMA_PATH, VIZE_CONFIG_PKL_SCHEMA_PATH, defineConfig, loadConfig, normalizeGlobalTypes, resolveConfigExport };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as loadConfig, i as defineConfig, n as VIZE_CONFIG_JSON_SCHEMA_PATH, o as normalizeGlobalTypes, r as VIZE_CONFIG_PKL_SCHEMA_PATH, s as resolveConfigExport, t as CONFIG_FILE_NAMES } from "./config-D1BwAgHh.mjs";
1
+ import { a as loadConfig, i as defineConfig, n as VIZE_CONFIG_JSON_SCHEMA_PATH, o as normalizeGlobalTypes, r as VIZE_CONFIG_PKL_SCHEMA_PATH, s as resolveConfigExport, t as CONFIG_FILE_NAMES } from "./config-CqEev07u.mjs";
2
2
  export { CONFIG_FILE_NAMES, VIZE_CONFIG_JSON_SCHEMA_PATH, VIZE_CONFIG_PKL_SCHEMA_PATH, defineConfig, loadConfig, normalizeGlobalTypes, resolveConfigExport };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vize",
3
- "version": "0.291.0",
3
+ "version": "0.303.0",
4
4
  "description": "Vize - High-performance Vue.js toolchain in Rust",
5
5
  "keywords": [
6
6
  "cli",
@@ -22,7 +22,8 @@
22
22
  "directory": "npm/cli"
23
23
  },
24
24
  "bin": {
25
- "vize": "bin/vize"
25
+ "vize": "bin/vize",
26
+ "vz": "bin/vize"
26
27
  },
27
28
  "files": [
28
29
  "bin",
@@ -52,7 +53,7 @@
52
53
  "access": "public"
53
54
  },
54
55
  "dependencies": {
55
- "@vizejs/native": "0.291.0",
56
+ "@vizejs/native": "0.303.0",
56
57
  "oxc-transform": "0.130.0"
57
58
  },
58
59
  "devDependencies": {
@@ -83,11 +84,19 @@
83
84
  "engines": {
84
85
  "node": ">=22"
85
86
  },
87
+ "tsContentMapper": {
88
+ "exec": [
89
+ "node",
90
+ "./bin/vize",
91
+ "content-mapper"
92
+ ]
93
+ },
86
94
  "scripts": {
87
95
  "build": "vp run --workspace-root generate:rule-types && vp pack",
88
- "check": "vp check src vite.config.ts",
89
- "check:fix": "vp check --fix src vite.config.ts",
90
- "fmt": "vp fmt --write src vite.config.ts",
91
- "generate:rule-types": "vp run --workspace-root generate:rule-types"
96
+ "check": "vp check src tests vite.config.ts",
97
+ "check:fix": "vp check --fix src tests vite.config.ts",
98
+ "fmt": "vp fmt --write src tests vite.config.ts",
99
+ "generate:rule-types": "vp run --workspace-root generate:rule-types",
100
+ "test": "vp pack && vp test run tests/setup.test.ts"
92
101
  }
93
102
  }
package/src/cli.ts CHANGED
@@ -1,6 +1,19 @@
1
1
  import { createRequire } from "node:module";
2
2
 
3
+ import { runSetupCli } from "./setup.js";
4
+
3
5
  const require = createRequire(import.meta.url);
4
- const native = require("@vizejs/native") as typeof import("@vizejs/native");
5
6
 
6
- native.runCli(process.argv.slice(2));
7
+ try {
8
+ const args = process.argv.slice(2);
9
+ if (args[0] === "setup") {
10
+ runSetupCli(args.slice(1));
11
+ } else {
12
+ const native = require("@vizejs/native") as typeof import("@vizejs/native");
13
+ native.runCli(args);
14
+ }
15
+ } catch (error) {
16
+ const message = error instanceof Error ? error.message : String(error);
17
+ process.stderr.write(`[vize] ${message}\n`);
18
+ process.exitCode = 1;
19
+ }
@@ -0,0 +1,187 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ export const VIZE_CONFIG_FILES = [
5
+ "vize.config.pkl",
6
+ "vize.config.ts",
7
+ "vize.config.js",
8
+ "vize.config.mjs",
9
+ "vize.config.json",
10
+ ] as const;
11
+
12
+ export const OXLINT_CONFIG_FILES = [
13
+ ".oxlintrc.json",
14
+ ".oxlintrc.jsonc",
15
+ "oxlint.config.ts",
16
+ "oxlint.config.mts",
17
+ "oxlint.config.js",
18
+ "oxlint.config.mjs",
19
+ "oxlint.config.cjs",
20
+ "oxlint.config.cts",
21
+ ] as const;
22
+
23
+ export const REQUIRED_DEV_DEPENDENCIES = [
24
+ "vize",
25
+ "@vizejs/vite-plugin",
26
+ "@vizejs/vite-plugin-musea",
27
+ "oxlint",
28
+ "oxlint-plugin-vize",
29
+ ] as const;
30
+
31
+ export const DEFAULT_SCRIPTS = {
32
+ "vize:build": "vize build src",
33
+ "vize:fmt": "vize fmt --check src",
34
+ "vize:fmt:fix": "vize fmt --write src",
35
+ "vize:lint": "vize lint --preset happy-path --max-warnings 0 src",
36
+ "vize:check": "vize check src",
37
+ "vize:musea": "vize musea",
38
+ "vize:ready": "vize ready src",
39
+ } as const;
40
+
41
+ export const DEFAULT_VIZE_CONFIG = `import { defineConfig } from "vize";
42
+
43
+ export default defineConfig({
44
+ compiler: {
45
+ templateSyntax: "standard",
46
+ },
47
+ linter: {
48
+ preset: "happy-path",
49
+ },
50
+ typeChecker: {
51
+ enabled: true,
52
+ strict: true,
53
+ },
54
+ vite: {
55
+ scanPatterns: ["src/**/*.vue"],
56
+ },
57
+ });
58
+ `;
59
+
60
+ export const DEFAULT_OXLINT_CONFIG = `import { defineConfig } from "oxlint";
61
+ import { configs } from "oxlint-plugin-vize";
62
+
63
+ export default defineConfig({
64
+ plugins: ["vue"],
65
+ jsPlugins: ["oxlint-plugin-vize"],
66
+ settings: {
67
+ vize: {
68
+ preset: "general-recommended",
69
+ helpLevel: "short",
70
+ },
71
+ },
72
+ rules: configs.recommended,
73
+ });
74
+ `;
75
+
76
+ type JsonObject = Record<string, unknown>;
77
+
78
+ export interface PlannedFile {
79
+ readonly filename: string;
80
+ readonly source: string;
81
+ }
82
+
83
+ export function readRequiredFile(filename: string, message: string): string {
84
+ try {
85
+ return fs.readFileSync(filename, "utf8");
86
+ } catch (error) {
87
+ if (isNodeError(error) && error.code === "ENOENT") {
88
+ throw new Error(`${message}: ${filename}`, { cause: error });
89
+ }
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ export function parsePackageJson(filename: string, source: string): JsonObject {
95
+ try {
96
+ const parsed = JSON.parse(source) as unknown;
97
+ if (!isJsonObject(parsed)) {
98
+ throw new Error("package.json must contain an object");
99
+ }
100
+ return parsed;
101
+ } catch (error) {
102
+ throw new Error(`Invalid package.json: ${filename}`, { cause: error });
103
+ }
104
+ }
105
+
106
+ export function detectJsonIndent(source: string): string | number {
107
+ const match = source.match(/^[\t ]+(?=")/mu);
108
+ return match?.[0] ?? 2;
109
+ }
110
+
111
+ export function dependencyNames(packageJson: JsonObject): Set<string> {
112
+ const names = new Set<string>();
113
+ for (const field of ["dependencies", "devDependencies", "optionalDependencies"] as const) {
114
+ const dependencies = packageJson[field];
115
+ if (!isJsonObject(dependencies)) {
116
+ continue;
117
+ }
118
+ for (const name of Object.keys(dependencies)) {
119
+ names.add(name);
120
+ }
121
+ }
122
+ return names;
123
+ }
124
+
125
+ export function addDefaultScripts(packageJson: JsonObject): {
126
+ readonly addedScripts: string[];
127
+ readonly preservedScripts: string[];
128
+ } {
129
+ if (packageJson.scripts !== undefined && !isJsonObject(packageJson.scripts)) {
130
+ throw new Error("package.json scripts must contain an object");
131
+ }
132
+
133
+ const scripts = (packageJson.scripts ?? {}) as JsonObject;
134
+ const addedScripts: string[] = [];
135
+ const preservedScripts: string[] = [];
136
+ for (const [name, command] of Object.entries(DEFAULT_SCRIPTS)) {
137
+ if (name in scripts) {
138
+ preservedScripts.push(name);
139
+ continue;
140
+ }
141
+ scripts[name] = command;
142
+ addedScripts.push(name);
143
+ }
144
+ if (addedScripts.length > 0) {
145
+ packageJson.scripts = scripts;
146
+ }
147
+ return { addedScripts, preservedScripts };
148
+ }
149
+
150
+ export function planGeneratedConfig(
151
+ root: string,
152
+ candidates: readonly string[],
153
+ generatedName: string,
154
+ source: string,
155
+ plannedFiles: PlannedFile[],
156
+ createdFiles: string[],
157
+ preservedFiles: string[],
158
+ ): void {
159
+ const existing = candidates.find((candidate) => fs.existsSync(path.join(root, candidate)));
160
+ if (existing) {
161
+ preservedFiles.push(existing);
162
+ return;
163
+ }
164
+ plannedFiles.push({ filename: path.join(root, generatedName), source });
165
+ createdFiles.push(generatedName);
166
+ }
167
+
168
+ export function atomicWriteFile(filename: string, source: string): void {
169
+ const temporary = path.join(
170
+ path.dirname(filename),
171
+ `.${path.basename(filename)}.${process.pid}.${Date.now()}.tmp`,
172
+ );
173
+ try {
174
+ fs.writeFileSync(temporary, source, { encoding: "utf8", flag: "wx" });
175
+ fs.renameSync(temporary, filename);
176
+ } finally {
177
+ fs.rmSync(temporary, { force: true });
178
+ }
179
+ }
180
+
181
+ function isJsonObject(value: unknown): value is JsonObject {
182
+ return typeof value === "object" && value !== null && !Array.isArray(value);
183
+ }
184
+
185
+ function isNodeError(value: unknown): value is NodeJS.ErrnoException {
186
+ return value instanceof Error;
187
+ }
@@ -0,0 +1,159 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ import type { PlannedFile } from "./config.js";
5
+
6
+ const VITE_CONFIG_FILES = [
7
+ "vite.config.ts",
8
+ "vite.config.mts",
9
+ "vite.config.js",
10
+ "vite.config.mjs",
11
+ ] as const;
12
+
13
+ const VITE_PLUS_LINT_IMPORT =
14
+ 'import { configs as vizePlusLintConfigs } from "oxlint-plugin-vize";\n';
15
+
16
+ const VITE_PLUS_LINT_BLOCK = ` lint: {
17
+ plugins: ["vue"],
18
+ jsPlugins: ["oxlint-plugin-vize"],
19
+ settings: {
20
+ vize: {
21
+ preset: "general-recommended",
22
+ helpLevel: "short",
23
+ },
24
+ },
25
+ rules: vizePlusLintConfigs.recommended,
26
+ },
27
+ `;
28
+
29
+ export interface ViteMigrationPlan {
30
+ readonly file: PlannedFile | null;
31
+ readonly preserved: string | null;
32
+ readonly removesOfficialPlugin: boolean;
33
+ readonly enablesVitePlusLint: boolean;
34
+ readonly hasVitePlusLint: boolean;
35
+ readonly usesVitePlus: boolean;
36
+ }
37
+
38
+ export function planViteMigration(
39
+ root: string,
40
+ mayConfigureVitePlusLint: boolean,
41
+ ): ViteMigrationPlan {
42
+ const existing = VITE_CONFIG_FILES.filter((candidate) =>
43
+ fs.existsSync(path.join(root, candidate)),
44
+ );
45
+ if (existing.length === 0) {
46
+ return {
47
+ file: null,
48
+ preserved: null,
49
+ removesOfficialPlugin: false,
50
+ enablesVitePlusLint: false,
51
+ hasVitePlusLint: false,
52
+ usesVitePlus: false,
53
+ };
54
+ }
55
+ if (existing.length > 1) {
56
+ return {
57
+ file: null,
58
+ preserved: `Vite configs (${existing.join(", ")})`,
59
+ removesOfficialPlugin: false,
60
+ enablesVitePlusLint: false,
61
+ hasVitePlusLint: false,
62
+ usesVitePlus: false,
63
+ };
64
+ }
65
+
66
+ const relativeFilename = existing[0]!;
67
+ const filename = path.join(root, relativeFilename);
68
+ const source = fs.readFileSync(filename, "utf8");
69
+ const usesVitePlus = /from\s+["']vite-plus["']/u.test(source);
70
+ let migratedSource = source;
71
+ let removesOfficialPlugin = false;
72
+ let preserved: string | null = null;
73
+
74
+ if (!source.includes("@vizejs/vite-plugin")) {
75
+ const importPattern =
76
+ /^([^\S\r\n]*import[^\S\r\n]+)([$A-Z_a-z][$\w]*)([^\S\r\n]+from[^\S\r\n]+)(["'])@vitejs\/plugin-vue\4([^\S\r\n]*;?[^\S\r\n]*)$/gmu;
77
+ const imports = [...source.matchAll(importPattern)];
78
+ if (imports.length === 1) {
79
+ const localName = imports[0]![2]!;
80
+ const zeroArgumentCallPattern = new RegExp(
81
+ `\\b${escapeRegExp(localName)}\\s*\\(\\s*\\)`,
82
+ "gu",
83
+ );
84
+ const calls = [...source.matchAll(zeroArgumentCallPattern)];
85
+ const importIndex = imports[0]!.index!;
86
+ const importSource = imports[0]![0];
87
+ const sourceWithoutExpectedUse =
88
+ source.slice(0, importIndex) +
89
+ source.slice(importIndex + importSource.length).replace(zeroArgumentCallPattern, "");
90
+ const hasOtherUses = new RegExp(`\\b${escapeRegExp(localName)}\\b`, "u").test(
91
+ sourceWithoutExpectedUse,
92
+ );
93
+ if (calls.length === 1 && !hasOtherUses) {
94
+ migratedSource = source.replace(importPattern, `$1$2$3$4@vizejs/vite-plugin$4$5`);
95
+ removesOfficialPlugin = true;
96
+ } else {
97
+ preserved = relativeFilename;
98
+ }
99
+ } else if (source.includes("@vitejs/plugin-vue")) {
100
+ preserved = relativeFilename;
101
+ }
102
+ }
103
+
104
+ const hadVitePlusLint = usesVitePlus && source.includes("oxlint-plugin-vize");
105
+ let enablesVitePlusLint = false;
106
+ if (mayConfigureVitePlusLint && !hadVitePlusLint && canInjectVitePlusLint(migratedSource)) {
107
+ const injectedSource = injectVitePlusLint(migratedSource);
108
+ if (injectedSource !== null) {
109
+ migratedSource = injectedSource;
110
+ enablesVitePlusLint = true;
111
+ }
112
+ }
113
+
114
+ return {
115
+ file: migratedSource === source ? null : { filename, source: migratedSource },
116
+ preserved:
117
+ preserved ??
118
+ (migratedSource === source && source.includes("@vizejs/vite-plugin")
119
+ ? relativeFilename
120
+ : null),
121
+ removesOfficialPlugin,
122
+ enablesVitePlusLint,
123
+ hasVitePlusLint: hadVitePlusLint || enablesVitePlusLint,
124
+ usesVitePlus,
125
+ };
126
+ }
127
+
128
+ function canInjectVitePlusLint(source: string): boolean {
129
+ if (
130
+ !/from\s+["']vite-plus["']/u.test(source) ||
131
+ /^\s*lint\s*:/mu.test(source) ||
132
+ /\bvizePlusLintConfigs\b/u.test(source)
133
+ ) {
134
+ return false;
135
+ }
136
+ return [...source.matchAll(/\bdefineConfig\s*\(\s*\{/gu)].length === 1;
137
+ }
138
+
139
+ function injectVitePlusLint(source: string): string | null {
140
+ const importLines = [
141
+ ...source.matchAll(
142
+ /^import[^\r\n]*(?:from\s+["'][^"']+["']|["'][^"']+["'])\s*;?[^\S\r\n]*(?:\r?\n|$)/gmu,
143
+ ),
144
+ ];
145
+ const lastImport = importLines.at(-1);
146
+ if (!lastImport || lastImport.index === undefined) {
147
+ return null;
148
+ }
149
+ const importEnd = lastImport.index + lastImport[0].length;
150
+ const withImport = source.slice(0, importEnd) + VITE_PLUS_LINT_IMPORT + source.slice(importEnd);
151
+ return withImport.replace(
152
+ /\bdefineConfig\s*\(\s*\{/u,
153
+ (opening) => `${opening}\n${VITE_PLUS_LINT_BLOCK}`,
154
+ );
155
+ }
156
+
157
+ function escapeRegExp(value: string): string {
158
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
159
+ }