vize 0.64.0 → 0.65.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 CHANGED
@@ -4,10 +4,11 @@ The `vize` npm package provides:
4
4
 
5
5
  - shared config utilities (`defineConfig`, `loadConfig`)
6
6
  - the native `vize lint` command
7
+ - the native `vize check` command for package scripts
7
8
 
8
9
  For Vite integration, pair it with `@vizejs/vite-plugin`.
9
- For the full Rust-native CLI (`build`, `fmt`, `check`, `lsp`, `ide`), install the Rust `vize`
10
- binary with `cargo install vize`.
10
+ For the full Rust-native CLI (`build`, `fmt`, project-backed `check`, `lsp`, `ide`), install the
11
+ Rust `vize` binary with `cargo install vize`.
11
12
 
12
13
  Need `vp` first? Install Vite+ once from the [Vite+ install guide](https://viteplus.dev/guide/install).
13
14
 
@@ -19,11 +20,13 @@ vp install -D vize
19
20
 
20
21
  ## CLI
21
22
 
22
- The npm CLI currently exposes `lint`:
23
+ The npm CLI exposes `lint` and `check`:
23
24
 
24
25
  ```bash
25
26
  vp exec vize lint src
26
27
  vp exec vize lint --preset opinionated --help-level short src
28
+ vp exec vize check
29
+ vp exec vize check src
27
30
  ```
28
31
 
29
32
  Shared config discovery is supported for the npm CLI:
@@ -41,11 +44,18 @@ export default defineConfig({
41
44
  linter: {
42
45
  preset: "opinionated",
43
46
  },
47
+ typeChecker: {
48
+ strict: true,
49
+ },
44
50
  });
45
51
  ```
46
52
 
47
53
  Override config discovery with `--config`, or disable it with `--no-config`.
48
54
 
55
+ `vize check` in the npm package uses the packaged NAPI checker so it can run from `package.json`
56
+ scripts after installing `vize`. Use the Rust CLI when you need Corsa project diagnostics across
57
+ Vue, TS, TSX, and `.d.ts` inputs.
58
+
49
59
  ## Programmatic Config Helpers
50
60
 
51
61
  ```ts
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { loadConfig } from "./config.mjs";
2
2
  import { createRequire } from "node:module";
3
- import { readFileSync } from "node:fs";
3
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
4
4
  import * as path from "node:path";
5
5
  import { spawnSync } from "node:child_process";
6
6
  import { pathToFileURL } from "node:url";
@@ -37,12 +37,12 @@ function getBindingPackageName() {
37
37
  default: throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);
38
38
  }
39
39
  }
40
- function loadNative() {
40
+ function loadNative(command) {
41
41
  const attemptedPackages = getAttemptedPackages();
42
42
  let lastError = null;
43
43
  for (const packageName of attemptedPackages) try {
44
44
  const binding = require(packageName);
45
- if (typeof binding.lint !== "function") throw new Error(`${packageName} does not expose the lint binding.`);
45
+ if (typeof binding[command === "check" ? "typeCheck" : "lint"] !== "function") throw new Error(`${packageName} does not expose the ${command} binding.`);
46
46
  return binding;
47
47
  } catch (error) {
48
48
  lastError = error;
@@ -71,7 +71,20 @@ function shouldPreferWorkspaceBinding(resolvedPath) {
71
71
  }
72
72
  function printUsage() {
73
73
  console.error("Usage: vize <command> [options]");
74
- console.error("Commands: lint, musea");
74
+ console.error("Commands: check, lint, musea");
75
+ }
76
+ function printCheckUsage() {
77
+ console.error("Usage: vize check [options] [files-or-directories]");
78
+ console.error("Options:");
79
+ console.error(" -f, --format <text|json> Output format");
80
+ console.error(" -q, --quiet Show summary only");
81
+ console.error(" --strict Enable strict checks");
82
+ console.error(" --show-virtual-ts Print generated Virtual TS");
83
+ console.error(" --max-warnings <number> Fail when warnings exceed the limit");
84
+ console.error(" -c, --config <path> Use a specific vize config file");
85
+ console.error(" --no-config Disable config discovery");
86
+ console.error("");
87
+ console.error("Note: npm `vize check` uses the packaged NAPI checker. Install the Rust CLI for project-backed Corsa diagnostics.");
75
88
  }
76
89
  function resolvePackageBinaryFromCwd(packageName, binName = packageName) {
77
90
  const packageJsonPath = createRequire(pathToFileURL(path.join(process.cwd(), "package.json")).href).resolve(`${packageName}/package.json`);
@@ -127,6 +140,251 @@ function parseLintCommand(args) {
127
140
  sharedConfig
128
141
  };
129
142
  }
143
+ function parseCheckCommand(args) {
144
+ const patterns = [];
145
+ const options = {};
146
+ const sharedConfig = { configMode: "root" };
147
+ for (let i = 0; i < args.length; i++) {
148
+ const arg = args[i];
149
+ if (arg === "--format" || arg === "-f") options.format = args[++i];
150
+ else if (arg === "--quiet" || arg === "-q") options.quiet = true;
151
+ else if (arg === "--strict") options.strict = true;
152
+ else if (arg === "--no-strict") options.strict = false;
153
+ else if (arg === "--show-virtual-ts" || arg === "--include-virtual-ts") options.includeVirtualTs = true;
154
+ else if (arg === "--max-warnings") options.maxWarnings = Number.parseInt(args[++i], 10);
155
+ else if (arg === "--no-check-props") options.checkProps = false;
156
+ else if (arg === "--no-check-emits") options.checkEmits = false;
157
+ else if (arg === "--no-check-template-bindings") options.checkTemplateBindings = false;
158
+ else if (arg === "--no-check-reactivity") options.checkReactivity = false;
159
+ else if (arg === "--no-check-setup-context") options.checkSetupContext = false;
160
+ else if (arg === "--no-check-invalid-exports") options.checkInvalidExports = false;
161
+ else if (arg === "--no-check-fallthrough-attrs") options.checkFallthroughAttrs = false;
162
+ else if (arg === "--config" || arg === "-c") {
163
+ const configFile = args[++i];
164
+ if (!configFile) throw new Error("Missing path after --config");
165
+ sharedConfig.configFile = configFile;
166
+ } else if (arg === "--no-config") sharedConfig.configMode = "none";
167
+ else if (arg === "--help" || arg === "-h") options.help = true;
168
+ else if (arg === "--tsconfig" || arg === "--corsa-path" || arg === "--servers") i++;
169
+ else if (arg === "--socket" || arg === "-s" || arg === "--declaration-dir") i++;
170
+ else if (arg === "--profile" || arg === "--declaration") {} else if (!arg.startsWith("-")) patterns.push(arg);
171
+ }
172
+ return {
173
+ patterns,
174
+ options,
175
+ sharedConfig
176
+ };
177
+ }
178
+ function hasGlobSyntax(pattern) {
179
+ return pattern.includes("*") || pattern.includes("?") || pattern.includes("[");
180
+ }
181
+ function normalizePath(filePath) {
182
+ return filePath.split(path.sep).join("/");
183
+ }
184
+ function displayPath(filePath) {
185
+ const relative = path.relative(process.cwd(), filePath);
186
+ if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) return normalizePath(relative);
187
+ return normalizePath(filePath);
188
+ }
189
+ function isVueFile(filePath) {
190
+ return path.extname(filePath) === ".vue";
191
+ }
192
+ function collectVueFilesFromDirectory(directory, recursive) {
193
+ const files = [];
194
+ const entries = readdirSync(directory, { withFileTypes: true });
195
+ for (const entry of entries) {
196
+ const entryPath = path.join(directory, entry.name);
197
+ if (entry.isDirectory()) {
198
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
199
+ if (recursive) files.push(...collectVueFilesFromDirectory(entryPath, true));
200
+ } else if (entry.isFile() && isVueFile(entryPath)) files.push(entryPath);
201
+ }
202
+ return files;
203
+ }
204
+ function globBase(pattern) {
205
+ const normalized = normalizePath(pattern);
206
+ const globIndex = normalized.search(/[*?[]/);
207
+ if (globIndex === -1) return normalized;
208
+ const beforeGlob = normalized.slice(0, globIndex);
209
+ const slashIndex = beforeGlob.lastIndexOf("/");
210
+ if (slashIndex === -1) return ".";
211
+ return beforeGlob.slice(0, slashIndex) || "/";
212
+ }
213
+ function globToRegExp(pattern) {
214
+ const normalized = normalizePath(pattern);
215
+ let source = "";
216
+ for (let i = 0; i < normalized.length; i++) {
217
+ const char = normalized[i];
218
+ const next = normalized[i + 1];
219
+ const afterNext = normalized[i + 2];
220
+ if (char === "*" && next === "*" && afterNext === "/") {
221
+ source += "(?:.*/)?";
222
+ i += 2;
223
+ } else if (char === "*" && next === "*") {
224
+ source += ".*";
225
+ i++;
226
+ } else if (char === "*") source += "[^/]*";
227
+ else if (char === "?") source += "[^/]";
228
+ else if ("\\^$+?.()|{}[]".includes(char)) source += `\\${char}`;
229
+ else source += char;
230
+ }
231
+ return new RegExp(`^${source}$`);
232
+ }
233
+ function shouldRecurseGlob(pattern, base) {
234
+ const normalizedPattern = normalizePath(pattern);
235
+ const normalizedBase = normalizePath(base);
236
+ return (normalizedBase === "." ? normalizedPattern : normalizedPattern.slice(normalizedBase.length).replace(/^\/+/, "")).includes("/");
237
+ }
238
+ function collectVueFilesFromGlob(pattern) {
239
+ const basePattern = globBase(pattern);
240
+ const base = path.resolve(process.cwd(), basePattern);
241
+ if (!existsSync(base)) return [];
242
+ const isAbsolutePattern = path.isAbsolute(pattern);
243
+ const regex = globToRegExp(normalizePath(isAbsolutePattern ? path.resolve(pattern) : pattern));
244
+ return collectVueFilesFromDirectory(base, shouldRecurseGlob(pattern, basePattern)).filter((file) => {
245
+ const comparable = isAbsolutePattern ? normalizePath(file) : normalizePath(path.relative(process.cwd(), file));
246
+ return regex.test(comparable);
247
+ });
248
+ }
249
+ function collectCheckFiles(patterns) {
250
+ const files = /* @__PURE__ */ new Set();
251
+ const inputs = patterns.length === 0 ? ["."] : patterns;
252
+ for (const input of inputs) {
253
+ if (hasGlobSyntax(input)) {
254
+ for (const file of collectVueFilesFromGlob(input)) files.add(path.resolve(file));
255
+ continue;
256
+ }
257
+ const resolved = path.resolve(process.cwd(), input);
258
+ if (!existsSync(resolved)) continue;
259
+ const stats = statSync(resolved);
260
+ if (stats.isDirectory()) for (const file of collectVueFilesFromDirectory(resolved, true)) files.add(path.resolve(file));
261
+ else if (stats.isFile() && isVueFile(resolved)) files.add(resolved);
262
+ }
263
+ return Array.from(files).sort();
264
+ }
265
+ function lineStarts(source) {
266
+ const starts = [0];
267
+ for (let i = 0; i < source.length; i++) if (source.charCodeAt(i) === 10) starts.push(i + 1);
268
+ return starts;
269
+ }
270
+ function offsetToLineColumn(starts, offset) {
271
+ let low = 0;
272
+ let high = starts.length - 1;
273
+ while (low <= high) {
274
+ const mid = Math.floor((low + high) / 2);
275
+ if (starts[mid] <= offset) low = mid + 1;
276
+ else high = mid - 1;
277
+ }
278
+ const lineIndex = Math.max(0, high);
279
+ return {
280
+ line: lineIndex + 1,
281
+ column: offset - starts[lineIndex] + 1
282
+ };
283
+ }
284
+ function toNativeTypeCheckOptions(file, options) {
285
+ return {
286
+ filename: file,
287
+ strict: options.strict,
288
+ includeVirtualTs: options.includeVirtualTs,
289
+ include_virtual_ts: options.includeVirtualTs,
290
+ checkProps: options.checkProps,
291
+ check_props: options.checkProps,
292
+ checkEmits: options.checkEmits,
293
+ check_emits: options.checkEmits,
294
+ checkTemplateBindings: options.checkTemplateBindings,
295
+ check_template_bindings: options.checkTemplateBindings,
296
+ checkReactivity: options.checkReactivity,
297
+ check_reactivity: options.checkReactivity,
298
+ checkSetupContext: options.checkSetupContext,
299
+ check_setup_context: options.checkSetupContext,
300
+ checkInvalidExports: options.checkInvalidExports,
301
+ check_invalid_exports: options.checkInvalidExports,
302
+ checkFallthroughAttrs: options.checkFallthroughAttrs,
303
+ check_fallthrough_attrs: options.checkFallthroughAttrs
304
+ };
305
+ }
306
+ function renderCheckText(results, options, timeMs) {
307
+ let totalErrors = 0;
308
+ let totalWarnings = 0;
309
+ for (const { file, source, result } of results) {
310
+ totalErrors += result.errorCount;
311
+ totalWarnings += result.warningCount;
312
+ if (options.includeVirtualTs && result.virtualTs) process.stderr.write(`\n=== ${displayPath(file)} ===\n${result.virtualTs}\n`);
313
+ if (options.quiet || result.diagnostics.length === 0) continue;
314
+ const starts = lineStarts(source);
315
+ process.stdout.write(`\n\x1b[4m${displayPath(file)}\x1b[0m\n`);
316
+ for (const diagnostic of result.diagnostics) {
317
+ const color = diagnostic.severity === "error" ? "\x1B[31m" : "\x1B[33m";
318
+ const location = offsetToLineColumn(starts, diagnostic.start);
319
+ const code = diagnostic.code ? ` [${diagnostic.code}]` : "";
320
+ process.stdout.write(` ${color}${diagnostic.severity}:${location.line}:${location.column}\x1b[0m${code} ${diagnostic.message}\n`);
321
+ if (diagnostic.help) process.stdout.write(` help: ${diagnostic.help}\n`);
322
+ }
323
+ }
324
+ const status = totalErrors > 0 ? "\x1B[31mERR\x1B[0m" : "\x1B[32mOK\x1B[0m";
325
+ process.stdout.write(`\n${status} Type checked ${results.length} Vue files in ${timeMs.toFixed(2)}ms\n`);
326
+ if (totalErrors > 0) process.stdout.write(` \x1b[31m${totalErrors} error(s)\x1b[0m\n`);
327
+ else process.stdout.write(" \x1B[32mNo type errors found!\x1B[0m\n");
328
+ if (totalWarnings > 0) process.stdout.write(` \x1b[33m${totalWarnings} warning(s)\x1b[0m\n`);
329
+ }
330
+ async function runCheck(args) {
331
+ const { patterns, options, sharedConfig } = parseCheckCommand(args);
332
+ if (options.help) {
333
+ printCheckUsage();
334
+ return;
335
+ }
336
+ const config = await loadConfig(process.cwd(), {
337
+ mode: sharedConfig.configMode,
338
+ configFile: sharedConfig.configFile,
339
+ env: {
340
+ mode: process.env.NODE_ENV ?? "development",
341
+ command: "check"
342
+ }
343
+ });
344
+ if (sharedConfig.configFile && !config) throw new Error(`Could not find config file: ${sharedConfig.configFile}`);
345
+ if (config?.typeChecker?.enabled === false) {
346
+ process.stderr.write("[vize] Skipping check because typeChecker.enabled is false in vize.config.\n");
347
+ return;
348
+ }
349
+ options.strict ??= config?.typeChecker?.strict;
350
+ options.checkProps ??= config?.typeChecker?.checkProps;
351
+ options.checkEmits ??= config?.typeChecker?.checkEmits;
352
+ options.checkTemplateBindings ??= config?.typeChecker?.checkTemplateBindings;
353
+ const files = collectCheckFiles(patterns);
354
+ if (files.length === 0) {
355
+ process.stderr.write(`No Vue files found matching inputs: ${JSON.stringify(patterns)}\n`);
356
+ return;
357
+ }
358
+ const native = loadNative("check");
359
+ const start = performance.now();
360
+ const results = files.map((file) => {
361
+ const source = readFileSync(file, "utf8");
362
+ return {
363
+ file,
364
+ source,
365
+ result: native.typeCheck(source, toNativeTypeCheckOptions(file, options))
366
+ };
367
+ });
368
+ const timeMs = performance.now() - start;
369
+ const totalErrors = results.reduce((sum, { result }) => sum + result.errorCount, 0);
370
+ const totalWarnings = results.reduce((sum, { result }) => sum + result.warningCount, 0);
371
+ if (options.format === "json") process.stdout.write(`${JSON.stringify({
372
+ files: results.map(({ file, result }) => ({
373
+ file: displayPath(file),
374
+ diagnostics: result.diagnostics,
375
+ virtualTs: result.virtualTs
376
+ })),
377
+ errorCount: totalErrors,
378
+ warningCount: totalWarnings,
379
+ fileCount: results.length
380
+ }, null, 2)}\n`);
381
+ else renderCheckText(results, options, timeMs);
382
+ if (totalErrors > 0) process.exit(1);
383
+ if (options.maxWarnings !== void 0 && totalWarnings > options.maxWarnings) {
384
+ process.stderr.write(`\nToo many warnings (${totalWarnings} > max ${options.maxWarnings})\n`);
385
+ process.exit(1);
386
+ }
387
+ }
130
388
  async function runLint(args) {
131
389
  const { patterns, options, sharedConfig } = parseLintCommand(args);
132
390
  const config = await loadConfig(process.cwd(), {
@@ -144,7 +402,7 @@ async function runLint(args) {
144
402
  }
145
403
  options.preset ??= config?.linter?.preset;
146
404
  if (patterns.length === 0) patterns.push(".");
147
- const result = loadNative().lint(patterns, {
405
+ const result = loadNative("lint").lint(patterns, {
148
406
  format: options.format,
149
407
  max_warnings: options.maxWarnings,
150
408
  quiet: options.quiet,
@@ -163,7 +421,7 @@ async function runLint(args) {
163
421
  process.exit(1);
164
422
  }
165
423
  }
166
- const NAPI_COMMANDS = new Set(["lint"]);
424
+ const NAPI_COMMANDS = new Set(["check", "lint"]);
167
425
  const JS_COMMANDS = new Set(["musea"]);
168
426
  async function main() {
169
427
  const args = process.argv.slice(2);
@@ -175,6 +433,9 @@ async function main() {
175
433
  if (NAPI_COMMANDS.has(command)) {
176
434
  const commandArgs = args.slice(1);
177
435
  switch (command) {
436
+ case "check":
437
+ await runCheck(commandArgs);
438
+ break;
178
439
  case "lint":
179
440
  await runLint(commandArgs);
180
441
  break;
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { spawnSync } from \"node:child_process\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport { loadConfig } from \"./config.js\";\n\nconst require = createRequire(import.meta.url);\nconst WORKSPACE_BINDING_PATH = \"../../vize-native\";\n\n// ============================================================================\n// Native binding loader (oxlint pattern)\n// ============================================================================\n\nfunction isMusl(): boolean {\n const report = process.report?.getReport();\n if (typeof report === \"object\" && report !== null && \"header\" in report) {\n const header = (report as { header: { glibcVersionRuntime?: string } }).header;\n return !header.glibcVersionRuntime;\n }\n try {\n const lddPath = require(\"child_process\").execSync(\"which ldd\").toString().trim();\n return readFileSync(lddPath, \"utf8\").includes(\"musl\");\n } catch {\n return true;\n }\n}\n\nfunction getBindingPackageName(): string {\n const { platform, arch } = process;\n\n switch (platform) {\n case \"darwin\":\n switch (arch) {\n case \"x64\":\n return \"@vizejs/native-darwin-x64\";\n case \"arm64\":\n return \"@vizejs/native-darwin-arm64\";\n default:\n throw new Error(`Unsupported architecture on macOS: ${arch}`);\n }\n case \"win32\":\n switch (arch) {\n case \"x64\":\n return \"@vizejs/native-win32-x64-msvc\";\n case \"arm64\":\n return \"@vizejs/native-win32-arm64-msvc\";\n default:\n throw new Error(`Unsupported architecture on Windows: ${arch}`);\n }\n case \"linux\":\n switch (arch) {\n case \"x64\":\n return isMusl() ? \"@vizejs/native-linux-x64-musl\" : \"@vizejs/native-linux-x64-gnu\";\n case \"arm64\":\n return isMusl() ? \"@vizejs/native-linux-arm64-musl\" : \"@vizejs/native-linux-arm64-gnu\";\n default:\n throw new Error(`Unsupported architecture on Linux: ${arch}`);\n }\n default:\n throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);\n }\n}\n\ninterface NativeBinding {\n lint: (\n patterns: string[],\n options?: {\n format?: string;\n max_warnings?: number;\n quiet?: boolean;\n fix?: boolean;\n help_level?: string;\n preset?: string;\n },\n ) => LintResult;\n}\n\nfunction loadNative(): NativeBinding {\n const attemptedPackages = getAttemptedPackages();\n let lastError: unknown = null;\n\n for (const packageName of attemptedPackages) {\n try {\n const binding = require(packageName) as Partial<NativeBinding>;\n if (typeof binding.lint !== \"function\") {\n throw new Error(`${packageName} does not expose the lint binding.`);\n }\n return binding as NativeBinding;\n } catch (error) {\n lastError = error;\n }\n }\n\n console.error(`Failed to load native binding. Tried: ${attemptedPackages.join(\", \")}`);\n console.error(\"Try reinstalling: npm install vize\");\n throw lastError instanceof Error ? lastError : new Error(\"Failed to load native binding\");\n}\n\nfunction getAttemptedPackages(): readonly string[] {\n const platformBindingPackage = getBindingPackageName();\n return shouldPreferWorkspaceBinding(resolveWorkspaceBindingPath())\n ? [WORKSPACE_BINDING_PATH, platformBindingPackage]\n : [platformBindingPackage, WORKSPACE_BINDING_PATH];\n}\n\nfunction resolveWorkspaceBindingPath(): string | null {\n try {\n return require.resolve(WORKSPACE_BINDING_PATH);\n } catch {\n return null;\n }\n}\n\nfunction shouldPreferWorkspaceBinding(resolvedPath: string | null): boolean {\n const override = process.env.VIZE_PREFER_WORKSPACE_BINDING;\n if (override === \"1\" || override === \"true\") {\n return true;\n }\n if (override === \"0\" || override === \"false\") {\n return false;\n }\n if (resolvedPath == null) {\n return false;\n }\n\n return resolvedPath.includes(`${path.sep}npm${path.sep}vize-native${path.sep}`);\n}\n\n// ============================================================================\n// Lint command\n// ============================================================================\n\ninterface LintOptions {\n format?: string;\n maxWarnings?: number;\n quiet?: boolean;\n fix?: boolean;\n helpLevel?: string;\n preset?: string;\n}\n\ninterface LintResult {\n output: string;\n errorCount: number;\n warningCount: number;\n fileCount: number;\n timeMs: number;\n}\n\ninterface SharedConfigOptions {\n configFile?: string;\n configMode: \"root\" | \"none\";\n}\n\ninterface ParsedLintCommand {\n patterns: string[];\n options: LintOptions;\n sharedConfig: SharedConfigOptions;\n}\n\nfunction printUsage(): void {\n console.error(\"Usage: vize <command> [options]\");\n console.error(\"Commands: lint, musea\");\n}\n\nfunction resolvePackageBinaryFromCwd(packageName: string, binName: string = packageName): string {\n const cwdRequire = createRequire(pathToFileURL(path.join(process.cwd(), \"package.json\")).href);\n const packageJsonPath = cwdRequire.resolve(`${packageName}/package.json`);\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const bin = typeof packageJson.bin === \"string\" ? packageJson.bin : packageJson.bin?.[binName];\n\n if (!bin) {\n throw new Error(`Could not resolve binary '${binName}' from package '${packageName}'`);\n }\n\n return path.resolve(path.dirname(packageJsonPath), bin);\n}\n\nfunction runMusea(args: string[]): void {\n const isHelp = args.includes(\"--help\") || args.includes(\"-h\");\n if (isHelp) {\n console.error(\"Usage: vize musea [--build] [...vite options]\");\n console.error(\" --build Run `vite build` instead of `vite dev`\");\n return;\n }\n\n const isBuild = args.includes(\"--build\");\n const viteArgs = args.filter((arg) => arg !== \"--build\");\n const viteCommand = isBuild ? \"build\" : \"dev\";\n const viteBin = resolvePackageBinaryFromCwd(\"vite\");\n const result = spawnSync(process.execPath, [viteBin, viteCommand, ...viteArgs], {\n stdio: \"inherit\",\n cwd: process.cwd(),\n env: process.env,\n });\n\n if (result.error) {\n throw result.error;\n }\n\n process.exit(result.status ?? 1);\n}\n\nfunction parseLintCommand(args: string[]): ParsedLintCommand {\n const patterns: string[] = [];\n const options: LintOptions = {};\n const sharedConfig: SharedConfigOptions = {\n configMode: \"root\",\n };\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--format\" || arg === \"-f\") {\n options.format = args[++i];\n } else if (arg === \"--max-warnings\") {\n options.maxWarnings = Number.parseInt(args[++i], 10);\n } else if (arg === \"--quiet\" || arg === \"-q\") {\n options.quiet = true;\n } else if (arg === \"--fix\") {\n options.fix = true;\n } else if (arg === \"--help-level\") {\n options.helpLevel = args[++i];\n } else if (arg === \"--preset\") {\n options.preset = args[++i];\n } else if (arg === \"--config\" || arg === \"-c\") {\n const configFile = args[++i];\n if (!configFile) {\n throw new Error(\"Missing path after --config\");\n }\n sharedConfig.configFile = configFile;\n } else if (arg === \"--no-config\") {\n sharedConfig.configMode = \"none\";\n } else if (!arg.startsWith(\"-\")) {\n patterns.push(arg);\n }\n }\n\n return { patterns, options, sharedConfig };\n}\n\nasync function runLint(args: string[]): Promise<void> {\n const { patterns, options, sharedConfig } = parseLintCommand(args);\n const config = await loadConfig(process.cwd(), {\n mode: sharedConfig.configMode,\n configFile: sharedConfig.configFile,\n env: {\n mode: process.env.NODE_ENV ?? \"development\",\n command: \"lint\",\n },\n });\n\n if (sharedConfig.configFile && !config) {\n throw new Error(`Could not find config file: ${sharedConfig.configFile}`);\n }\n\n if (config?.linter?.enabled === false) {\n process.stderr.write(\"[vize] Skipping lint because linter.enabled is false in vize.config.\\n\");\n return;\n }\n\n options.preset ??= config?.linter?.preset;\n\n if (patterns.length === 0) {\n patterns.push(\".\");\n }\n\n const native = loadNative();\n const result = native.lint(patterns, {\n format: options.format,\n max_warnings: options.maxWarnings,\n quiet: options.quiet,\n fix: options.fix,\n help_level: options.helpLevel,\n preset: options.preset,\n });\n\n if (result.output) {\n process.stdout.write(result.output);\n if (!result.output.endsWith(\"\\n\")) {\n process.stdout.write(\"\\n\");\n }\n }\n\n if (options.fix) {\n process.stderr.write(\"\\nNote: --fix is not yet implemented\\n\");\n }\n\n if (result.errorCount > 0) {\n process.exit(1);\n }\n\n if (options.maxWarnings !== undefined && result.warningCount > options.maxWarnings) {\n process.stderr.write(\n `\\nToo many warnings (${result.warningCount} > max ${options.maxWarnings})\\n`,\n );\n process.exit(1);\n }\n}\n\n// ============================================================================\n// Command router\n// ============================================================================\n\nconst NAPI_COMMANDS = new Set([\"lint\"]);\nconst JS_COMMANDS = new Set([\"musea\"]);\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (!command || command === \"--help\" || command === \"-h\") {\n printUsage();\n process.exit(1);\n }\n\n if (NAPI_COMMANDS.has(command)) {\n const commandArgs = args.slice(1);\n switch (command) {\n case \"lint\":\n await runLint(commandArgs);\n break;\n }\n } else if (JS_COMMANDS.has(command)) {\n const commandArgs = args.slice(1);\n switch (command) {\n case \"musea\":\n runMusea(commandArgs);\n break;\n }\n } else {\n printUsage();\n console.error(`Unknown command: ${command}`);\n console.error(\n \"For commands not yet available via NAPI, install from source: cargo install vize\",\n );\n process.exit(1);\n }\n}\n\nif (!import.meta.vitest) {\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n\nif (import.meta.vitest) {\n const { describe, expect, it } = import.meta.vitest;\n\n describe(\"shouldPreferWorkspaceBinding\", () => {\n it(\"detects the local workspace native package\", () => {\n expect(\n shouldPreferWorkspaceBinding(\n `${path.sep}Users${path.sep}example${path.sep}repo${path.sep}npm${path.sep}vize-native${path.sep}index.js`,\n ),\n ).toBe(true);\n });\n\n it(\"ignores published platform packages\", () => {\n expect(\n shouldPreferWorkspaceBinding(\n `${path.sep}repo${path.sep}node_modules${path.sep}.pnpm${path.sep}@vizejs+native-darwin-arm64${path.sep}node_modules${path.sep}@vizejs${path.sep}native-darwin-arm64${path.sep}index.js`,\n ),\n ).toBe(false);\n });\n\n it(\"returns false when the fallback package cannot be resolved\", () => {\n expect(shouldPreferWorkspaceBinding(null)).toBe(false);\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { spawnSync } from \"node:child_process\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport { loadConfig } from \"./config.js\";\n\nconst require = createRequire(import.meta.url);\nconst WORKSPACE_BINDING_PATH = \"../../vize-native\";\n\n// ============================================================================\n// Native binding loader (oxlint pattern)\n// ============================================================================\n\nfunction isMusl(): boolean {\n const report = process.report?.getReport();\n if (typeof report === \"object\" && report !== null && \"header\" in report) {\n const header = (report as { header: { glibcVersionRuntime?: string } }).header;\n return !header.glibcVersionRuntime;\n }\n try {\n const lddPath = require(\"child_process\").execSync(\"which ldd\").toString().trim();\n return readFileSync(lddPath, \"utf8\").includes(\"musl\");\n } catch {\n return true;\n }\n}\n\nfunction getBindingPackageName(): string {\n const { platform, arch } = process;\n\n switch (platform) {\n case \"darwin\":\n switch (arch) {\n case \"x64\":\n return \"@vizejs/native-darwin-x64\";\n case \"arm64\":\n return \"@vizejs/native-darwin-arm64\";\n default:\n throw new Error(`Unsupported architecture on macOS: ${arch}`);\n }\n case \"win32\":\n switch (arch) {\n case \"x64\":\n return \"@vizejs/native-win32-x64-msvc\";\n case \"arm64\":\n return \"@vizejs/native-win32-arm64-msvc\";\n default:\n throw new Error(`Unsupported architecture on Windows: ${arch}`);\n }\n case \"linux\":\n switch (arch) {\n case \"x64\":\n return isMusl() ? \"@vizejs/native-linux-x64-musl\" : \"@vizejs/native-linux-x64-gnu\";\n case \"arm64\":\n return isMusl() ? \"@vizejs/native-linux-arm64-musl\" : \"@vizejs/native-linux-arm64-gnu\";\n default:\n throw new Error(`Unsupported architecture on Linux: ${arch}`);\n }\n default:\n throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);\n }\n}\n\ninterface NativeBinding {\n typeCheck: (source: string, options?: NativeTypeCheckOptions) => TypeCheckResult;\n lint: (\n patterns: string[],\n options?: {\n format?: string;\n max_warnings?: number;\n quiet?: boolean;\n fix?: boolean;\n help_level?: string;\n preset?: string;\n },\n ) => LintResult;\n}\n\nfunction loadNative(command: \"check\" | \"lint\"): NativeBinding {\n const attemptedPackages = getAttemptedPackages();\n let lastError: unknown = null;\n\n for (const packageName of attemptedPackages) {\n try {\n const binding = require(packageName) as Partial<NativeBinding>;\n if (typeof binding[command === \"check\" ? \"typeCheck\" : \"lint\"] !== \"function\") {\n throw new Error(`${packageName} does not expose the ${command} binding.`);\n }\n return binding as NativeBinding;\n } catch (error) {\n lastError = error;\n }\n }\n\n console.error(`Failed to load native binding. Tried: ${attemptedPackages.join(\", \")}`);\n console.error(\"Try reinstalling: npm install vize\");\n throw lastError instanceof Error ? lastError : new Error(\"Failed to load native binding\");\n}\n\nfunction getAttemptedPackages(): readonly string[] {\n const platformBindingPackage = getBindingPackageName();\n return shouldPreferWorkspaceBinding(resolveWorkspaceBindingPath())\n ? [WORKSPACE_BINDING_PATH, platformBindingPackage]\n : [platformBindingPackage, WORKSPACE_BINDING_PATH];\n}\n\nfunction resolveWorkspaceBindingPath(): string | null {\n try {\n return require.resolve(WORKSPACE_BINDING_PATH);\n } catch {\n return null;\n }\n}\n\nfunction shouldPreferWorkspaceBinding(resolvedPath: string | null): boolean {\n const override = process.env.VIZE_PREFER_WORKSPACE_BINDING;\n if (override === \"1\" || override === \"true\") {\n return true;\n }\n if (override === \"0\" || override === \"false\") {\n return false;\n }\n if (resolvedPath == null) {\n return false;\n }\n\n return resolvedPath.includes(`${path.sep}npm${path.sep}vize-native${path.sep}`);\n}\n\n// ============================================================================\n// Lint command\n// ============================================================================\n\ninterface LintOptions {\n format?: string;\n maxWarnings?: number;\n quiet?: boolean;\n fix?: boolean;\n helpLevel?: string;\n preset?: string;\n}\n\ninterface LintResult {\n output: string;\n errorCount: number;\n warningCount: number;\n fileCount: number;\n timeMs: number;\n}\n\ninterface SharedConfigOptions {\n configFile?: string;\n configMode: \"root\" | \"none\";\n}\n\ninterface ParsedLintCommand {\n patterns: string[];\n options: LintOptions;\n sharedConfig: SharedConfigOptions;\n}\n\nfunction printUsage(): void {\n console.error(\"Usage: vize <command> [options]\");\n console.error(\"Commands: check, lint, musea\");\n}\n\nfunction printCheckUsage(): void {\n console.error(\"Usage: vize check [options] [files-or-directories]\");\n console.error(\"Options:\");\n console.error(\" -f, --format <text|json> Output format\");\n console.error(\" -q, --quiet Show summary only\");\n console.error(\" --strict Enable strict checks\");\n console.error(\" --show-virtual-ts Print generated Virtual TS\");\n console.error(\" --max-warnings <number> Fail when warnings exceed the limit\");\n console.error(\" -c, --config <path> Use a specific vize config file\");\n console.error(\" --no-config Disable config discovery\");\n console.error(\"\");\n console.error(\n \"Note: npm `vize check` uses the packaged NAPI checker. Install the Rust CLI for project-backed Corsa diagnostics.\",\n );\n}\n\nfunction resolvePackageBinaryFromCwd(packageName: string, binName: string = packageName): string {\n const cwdRequire = createRequire(pathToFileURL(path.join(process.cwd(), \"package.json\")).href);\n const packageJsonPath = cwdRequire.resolve(`${packageName}/package.json`);\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const bin = typeof packageJson.bin === \"string\" ? packageJson.bin : packageJson.bin?.[binName];\n\n if (!bin) {\n throw new Error(`Could not resolve binary '${binName}' from package '${packageName}'`);\n }\n\n return path.resolve(path.dirname(packageJsonPath), bin);\n}\n\nfunction runMusea(args: string[]): void {\n const isHelp = args.includes(\"--help\") || args.includes(\"-h\");\n if (isHelp) {\n console.error(\"Usage: vize musea [--build] [...vite options]\");\n console.error(\" --build Run `vite build` instead of `vite dev`\");\n return;\n }\n\n const isBuild = args.includes(\"--build\");\n const viteArgs = args.filter((arg) => arg !== \"--build\");\n const viteCommand = isBuild ? \"build\" : \"dev\";\n const viteBin = resolvePackageBinaryFromCwd(\"vite\");\n const result = spawnSync(process.execPath, [viteBin, viteCommand, ...viteArgs], {\n stdio: \"inherit\",\n cwd: process.cwd(),\n env: process.env,\n });\n\n if (result.error) {\n throw result.error;\n }\n\n process.exit(result.status ?? 1);\n}\n\nfunction parseLintCommand(args: string[]): ParsedLintCommand {\n const patterns: string[] = [];\n const options: LintOptions = {};\n const sharedConfig: SharedConfigOptions = {\n configMode: \"root\",\n };\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--format\" || arg === \"-f\") {\n options.format = args[++i];\n } else if (arg === \"--max-warnings\") {\n options.maxWarnings = Number.parseInt(args[++i], 10);\n } else if (arg === \"--quiet\" || arg === \"-q\") {\n options.quiet = true;\n } else if (arg === \"--fix\") {\n options.fix = true;\n } else if (arg === \"--help-level\") {\n options.helpLevel = args[++i];\n } else if (arg === \"--preset\") {\n options.preset = args[++i];\n } else if (arg === \"--config\" || arg === \"-c\") {\n const configFile = args[++i];\n if (!configFile) {\n throw new Error(\"Missing path after --config\");\n }\n sharedConfig.configFile = configFile;\n } else if (arg === \"--no-config\") {\n sharedConfig.configMode = \"none\";\n } else if (!arg.startsWith(\"-\")) {\n patterns.push(arg);\n }\n }\n\n return { patterns, options, sharedConfig };\n}\n\n// ============================================================================\n// Check command\n// ============================================================================\n\ninterface NativeTypeCheckOptions {\n filename?: string;\n strict?: boolean;\n includeVirtualTs?: boolean;\n include_virtual_ts?: boolean;\n checkProps?: boolean;\n check_props?: boolean;\n checkEmits?: boolean;\n check_emits?: boolean;\n checkTemplateBindings?: boolean;\n check_template_bindings?: boolean;\n checkReactivity?: boolean;\n check_reactivity?: boolean;\n checkSetupContext?: boolean;\n check_setup_context?: boolean;\n checkInvalidExports?: boolean;\n check_invalid_exports?: boolean;\n checkFallthroughAttrs?: boolean;\n check_fallthrough_attrs?: boolean;\n}\n\ninterface TypeDiagnostic {\n severity: string;\n message: string;\n start: number;\n end: number;\n code?: string;\n help?: string;\n related?: Array<{\n message: string;\n start: number;\n end: number;\n filename?: string;\n }>;\n}\n\ninterface TypeCheckResult {\n diagnostics: TypeDiagnostic[];\n virtualTs?: string;\n errorCount: number;\n warningCount: number;\n analysisTimeMs?: number;\n}\n\ninterface CheckOptions {\n format?: string;\n quiet?: boolean;\n strict?: boolean;\n includeVirtualTs?: boolean;\n maxWarnings?: number;\n checkProps?: boolean;\n checkEmits?: boolean;\n checkTemplateBindings?: boolean;\n checkReactivity?: boolean;\n checkSetupContext?: boolean;\n checkInvalidExports?: boolean;\n checkFallthroughAttrs?: boolean;\n help?: boolean;\n}\n\ninterface ParsedCheckCommand {\n patterns: string[];\n options: CheckOptions;\n sharedConfig: SharedConfigOptions;\n}\n\ninterface CheckedFileResult {\n file: string;\n source: string;\n result: TypeCheckResult;\n}\n\nfunction parseCheckCommand(args: string[]): ParsedCheckCommand {\n const patterns: string[] = [];\n const options: CheckOptions = {};\n const sharedConfig: SharedConfigOptions = {\n configMode: \"root\",\n };\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--format\" || arg === \"-f\") {\n options.format = args[++i];\n } else if (arg === \"--quiet\" || arg === \"-q\") {\n options.quiet = true;\n } else if (arg === \"--strict\") {\n options.strict = true;\n } else if (arg === \"--no-strict\") {\n options.strict = false;\n } else if (arg === \"--show-virtual-ts\" || arg === \"--include-virtual-ts\") {\n options.includeVirtualTs = true;\n } else if (arg === \"--max-warnings\") {\n options.maxWarnings = Number.parseInt(args[++i], 10);\n } else if (arg === \"--no-check-props\") {\n options.checkProps = false;\n } else if (arg === \"--no-check-emits\") {\n options.checkEmits = false;\n } else if (arg === \"--no-check-template-bindings\") {\n options.checkTemplateBindings = false;\n } else if (arg === \"--no-check-reactivity\") {\n options.checkReactivity = false;\n } else if (arg === \"--no-check-setup-context\") {\n options.checkSetupContext = false;\n } else if (arg === \"--no-check-invalid-exports\") {\n options.checkInvalidExports = false;\n } else if (arg === \"--no-check-fallthrough-attrs\") {\n options.checkFallthroughAttrs = false;\n } else if (arg === \"--config\" || arg === \"-c\") {\n const configFile = args[++i];\n if (!configFile) {\n throw new Error(\"Missing path after --config\");\n }\n sharedConfig.configFile = configFile;\n } else if (arg === \"--no-config\") {\n sharedConfig.configMode = \"none\";\n } else if (arg === \"--help\" || arg === \"-h\") {\n options.help = true;\n } else if (arg === \"--tsconfig\" || arg === \"--corsa-path\" || arg === \"--servers\") {\n i++;\n } else if (arg === \"--socket\" || arg === \"-s\" || arg === \"--declaration-dir\") {\n i++;\n } else if (arg === \"--profile\" || arg === \"--declaration\") {\n // Accepted for package-script compatibility with the Rust CLI. The npm\n // checker does not currently emit project profiles or declarations.\n } else if (!arg.startsWith(\"-\")) {\n patterns.push(arg);\n }\n }\n\n return { patterns, options, sharedConfig };\n}\n\nfunction hasGlobSyntax(pattern: string): boolean {\n return pattern.includes(\"*\") || pattern.includes(\"?\") || pattern.includes(\"[\");\n}\n\nfunction normalizePath(filePath: string): string {\n return filePath.split(path.sep).join(\"/\");\n}\n\nfunction displayPath(filePath: string): string {\n const relative = path.relative(process.cwd(), filePath);\n if (relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative)) {\n return normalizePath(relative);\n }\n return normalizePath(filePath);\n}\n\nfunction isVueFile(filePath: string): boolean {\n return path.extname(filePath) === \".vue\";\n}\n\nfunction collectVueFilesFromDirectory(directory: string, recursive: boolean): string[] {\n const files: string[] = [];\n const entries = readdirSync(directory, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name === \".git\") {\n continue;\n }\n if (recursive) {\n files.push(...collectVueFilesFromDirectory(entryPath, true));\n }\n } else if (entry.isFile() && isVueFile(entryPath)) {\n files.push(entryPath);\n }\n }\n\n return files;\n}\n\nfunction globBase(pattern: string): string {\n const normalized = normalizePath(pattern);\n const globIndex = normalized.search(/[*?[]/);\n if (globIndex === -1) {\n return normalized;\n }\n\n const beforeGlob = normalized.slice(0, globIndex);\n const slashIndex = beforeGlob.lastIndexOf(\"/\");\n if (slashIndex === -1) {\n return \".\";\n }\n return beforeGlob.slice(0, slashIndex) || \"/\";\n}\n\nfunction globToRegExp(pattern: string): RegExp {\n const normalized = normalizePath(pattern);\n let source = \"\";\n\n for (let i = 0; i < normalized.length; i++) {\n const char = normalized[i];\n const next = normalized[i + 1];\n const afterNext = normalized[i + 2];\n\n if (char === \"*\" && next === \"*\" && afterNext === \"/\") {\n source += \"(?:.*/)?\";\n i += 2;\n } else if (char === \"*\" && next === \"*\") {\n source += \".*\";\n i++;\n } else if (char === \"*\") {\n source += \"[^/]*\";\n } else if (char === \"?\") {\n source += \"[^/]\";\n } else if (\"\\\\^$+?.()|{}[]\".includes(char)) {\n source += `\\\\${char}`;\n } else {\n source += char;\n }\n }\n\n return new RegExp(`^${source}$`);\n}\n\nfunction shouldRecurseGlob(pattern: string, base: string): boolean {\n const normalizedPattern = normalizePath(pattern);\n const normalizedBase = normalizePath(base);\n const rest =\n normalizedBase === \".\"\n ? normalizedPattern\n : normalizedPattern.slice(normalizedBase.length).replace(/^\\/+/, \"\");\n return rest.includes(\"/\");\n}\n\nfunction collectVueFilesFromGlob(pattern: string): string[] {\n const basePattern = globBase(pattern);\n const base = path.resolve(process.cwd(), basePattern);\n if (!existsSync(base)) {\n return [];\n }\n\n const isAbsolutePattern = path.isAbsolute(pattern);\n const normalizedPattern = normalizePath(isAbsolutePattern ? path.resolve(pattern) : pattern);\n const regex = globToRegExp(normalizedPattern);\n const candidates = collectVueFilesFromDirectory(base, shouldRecurseGlob(pattern, basePattern));\n\n return candidates.filter((file) => {\n const comparable = isAbsolutePattern\n ? normalizePath(file)\n : normalizePath(path.relative(process.cwd(), file));\n return regex.test(comparable);\n });\n}\n\nfunction collectCheckFiles(patterns: string[]): string[] {\n const files = new Set<string>();\n const inputs = patterns.length === 0 ? [\".\"] : patterns;\n\n for (const input of inputs) {\n if (hasGlobSyntax(input)) {\n for (const file of collectVueFilesFromGlob(input)) {\n files.add(path.resolve(file));\n }\n continue;\n }\n\n const resolved = path.resolve(process.cwd(), input);\n if (!existsSync(resolved)) {\n continue;\n }\n\n const stats = statSync(resolved);\n if (stats.isDirectory()) {\n for (const file of collectVueFilesFromDirectory(resolved, true)) {\n files.add(path.resolve(file));\n }\n } else if (stats.isFile() && isVueFile(resolved)) {\n files.add(resolved);\n }\n }\n\n return Array.from(files).sort();\n}\n\nfunction lineStarts(source: string): number[] {\n const starts = [0];\n for (let i = 0; i < source.length; i++) {\n if (source.charCodeAt(i) === 10) {\n starts.push(i + 1);\n }\n }\n return starts;\n}\n\nfunction offsetToLineColumn(starts: number[], offset: number): { line: number; column: number } {\n let low = 0;\n let high = starts.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n if (starts[mid] <= offset) {\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n const lineIndex = Math.max(0, high);\n return {\n line: lineIndex + 1,\n column: offset - starts[lineIndex] + 1,\n };\n}\n\nfunction toNativeTypeCheckOptions(file: string, options: CheckOptions): NativeTypeCheckOptions {\n return {\n filename: file,\n strict: options.strict,\n includeVirtualTs: options.includeVirtualTs,\n include_virtual_ts: options.includeVirtualTs,\n checkProps: options.checkProps,\n check_props: options.checkProps,\n checkEmits: options.checkEmits,\n check_emits: options.checkEmits,\n checkTemplateBindings: options.checkTemplateBindings,\n check_template_bindings: options.checkTemplateBindings,\n checkReactivity: options.checkReactivity,\n check_reactivity: options.checkReactivity,\n checkSetupContext: options.checkSetupContext,\n check_setup_context: options.checkSetupContext,\n checkInvalidExports: options.checkInvalidExports,\n check_invalid_exports: options.checkInvalidExports,\n checkFallthroughAttrs: options.checkFallthroughAttrs,\n check_fallthrough_attrs: options.checkFallthroughAttrs,\n };\n}\n\nfunction renderCheckText(\n results: CheckedFileResult[],\n options: CheckOptions,\n timeMs: number,\n): void {\n let totalErrors = 0;\n let totalWarnings = 0;\n\n for (const { file, source, result } of results) {\n totalErrors += result.errorCount;\n totalWarnings += result.warningCount;\n\n if (options.includeVirtualTs && result.virtualTs) {\n process.stderr.write(`\\n=== ${displayPath(file)} ===\\n${result.virtualTs}\\n`);\n }\n\n if (options.quiet || result.diagnostics.length === 0) {\n continue;\n }\n\n const starts = lineStarts(source);\n process.stdout.write(`\\n\\x1b[4m${displayPath(file)}\\x1b[0m\\n`);\n for (const diagnostic of result.diagnostics) {\n const color = diagnostic.severity === \"error\" ? \"\\x1b[31m\" : \"\\x1b[33m\";\n const location = offsetToLineColumn(starts, diagnostic.start);\n const code = diagnostic.code ? ` [${diagnostic.code}]` : \"\";\n process.stdout.write(\n ` ${color}${diagnostic.severity}:${location.line}:${location.column}\\x1b[0m${code} ${diagnostic.message}\\n`,\n );\n if (diagnostic.help) {\n process.stdout.write(` help: ${diagnostic.help}\\n`);\n }\n }\n }\n\n const status = totalErrors > 0 ? \"\\x1b[31mERR\\x1b[0m\" : \"\\x1b[32mOK\\x1b[0m\";\n process.stdout.write(\n `\\n${status} Type checked ${results.length} Vue files in ${timeMs.toFixed(2)}ms\\n`,\n );\n if (totalErrors > 0) {\n process.stdout.write(` \\x1b[31m${totalErrors} error(s)\\x1b[0m\\n`);\n } else {\n process.stdout.write(\" \\x1b[32mNo type errors found!\\x1b[0m\\n\");\n }\n if (totalWarnings > 0) {\n process.stdout.write(` \\x1b[33m${totalWarnings} warning(s)\\x1b[0m\\n`);\n }\n}\n\nasync function runCheck(args: string[]): Promise<void> {\n const { patterns, options, sharedConfig } = parseCheckCommand(args);\n if (options.help) {\n printCheckUsage();\n return;\n }\n\n const config = await loadConfig(process.cwd(), {\n mode: sharedConfig.configMode,\n configFile: sharedConfig.configFile,\n env: {\n mode: process.env.NODE_ENV ?? \"development\",\n command: \"check\",\n },\n });\n\n if (sharedConfig.configFile && !config) {\n throw new Error(`Could not find config file: ${sharedConfig.configFile}`);\n }\n\n if (config?.typeChecker?.enabled === false) {\n process.stderr.write(\n \"[vize] Skipping check because typeChecker.enabled is false in vize.config.\\n\",\n );\n return;\n }\n\n options.strict ??= config?.typeChecker?.strict;\n options.checkProps ??= config?.typeChecker?.checkProps;\n options.checkEmits ??= config?.typeChecker?.checkEmits;\n options.checkTemplateBindings ??= config?.typeChecker?.checkTemplateBindings;\n\n const files = collectCheckFiles(patterns);\n if (files.length === 0) {\n process.stderr.write(`No Vue files found matching inputs: ${JSON.stringify(patterns)}\\n`);\n return;\n }\n\n const native = loadNative(\"check\");\n const start = performance.now();\n const results = files.map((file) => {\n const source = readFileSync(file, \"utf8\");\n return {\n file,\n source,\n result: native.typeCheck(source, toNativeTypeCheckOptions(file, options)),\n };\n });\n const timeMs = performance.now() - start;\n const totalErrors = results.reduce((sum, { result }) => sum + result.errorCount, 0);\n const totalWarnings = results.reduce((sum, { result }) => sum + result.warningCount, 0);\n\n if (options.format === \"json\") {\n process.stdout.write(\n `${JSON.stringify(\n {\n files: results.map(({ file, result }) => ({\n file: displayPath(file),\n diagnostics: result.diagnostics,\n virtualTs: result.virtualTs,\n })),\n errorCount: totalErrors,\n warningCount: totalWarnings,\n fileCount: results.length,\n },\n null,\n 2,\n )}\\n`,\n );\n } else {\n renderCheckText(results, options, timeMs);\n }\n\n if (totalErrors > 0) {\n process.exit(1);\n }\n\n if (options.maxWarnings !== undefined && totalWarnings > options.maxWarnings) {\n process.stderr.write(`\\nToo many warnings (${totalWarnings} > max ${options.maxWarnings})\\n`);\n process.exit(1);\n }\n}\n\nasync function runLint(args: string[]): Promise<void> {\n const { patterns, options, sharedConfig } = parseLintCommand(args);\n const config = await loadConfig(process.cwd(), {\n mode: sharedConfig.configMode,\n configFile: sharedConfig.configFile,\n env: {\n mode: process.env.NODE_ENV ?? \"development\",\n command: \"lint\",\n },\n });\n\n if (sharedConfig.configFile && !config) {\n throw new Error(`Could not find config file: ${sharedConfig.configFile}`);\n }\n\n if (config?.linter?.enabled === false) {\n process.stderr.write(\"[vize] Skipping lint because linter.enabled is false in vize.config.\\n\");\n return;\n }\n\n options.preset ??= config?.linter?.preset;\n\n if (patterns.length === 0) {\n patterns.push(\".\");\n }\n\n const native = loadNative(\"lint\");\n const result = native.lint(patterns, {\n format: options.format,\n max_warnings: options.maxWarnings,\n quiet: options.quiet,\n fix: options.fix,\n help_level: options.helpLevel,\n preset: options.preset,\n });\n\n if (result.output) {\n process.stdout.write(result.output);\n if (!result.output.endsWith(\"\\n\")) {\n process.stdout.write(\"\\n\");\n }\n }\n\n if (options.fix) {\n process.stderr.write(\"\\nNote: --fix is not yet implemented\\n\");\n }\n\n if (result.errorCount > 0) {\n process.exit(1);\n }\n\n if (options.maxWarnings !== undefined && result.warningCount > options.maxWarnings) {\n process.stderr.write(\n `\\nToo many warnings (${result.warningCount} > max ${options.maxWarnings})\\n`,\n );\n process.exit(1);\n }\n}\n\n// ============================================================================\n// Command router\n// ============================================================================\n\nconst NAPI_COMMANDS = new Set([\"check\", \"lint\"]);\nconst JS_COMMANDS = new Set([\"musea\"]);\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (!command || command === \"--help\" || command === \"-h\") {\n printUsage();\n process.exit(1);\n }\n\n if (NAPI_COMMANDS.has(command)) {\n const commandArgs = args.slice(1);\n switch (command) {\n case \"check\":\n await runCheck(commandArgs);\n break;\n case \"lint\":\n await runLint(commandArgs);\n break;\n }\n } else if (JS_COMMANDS.has(command)) {\n const commandArgs = args.slice(1);\n switch (command) {\n case \"musea\":\n runMusea(commandArgs);\n break;\n }\n } else {\n printUsage();\n console.error(`Unknown command: ${command}`);\n console.error(\n \"For commands not yet available via NAPI, install from source: cargo install vize\",\n );\n process.exit(1);\n }\n}\n\nif (!import.meta.vitest) {\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n\nif (import.meta.vitest) {\n const { describe, expect, it } = import.meta.vitest;\n\n describe(\"shouldPreferWorkspaceBinding\", () => {\n it(\"detects the local workspace native package\", () => {\n expect(\n shouldPreferWorkspaceBinding(\n `${path.sep}Users${path.sep}example${path.sep}repo${path.sep}npm${path.sep}vize-native${path.sep}index.js`,\n ),\n ).toBe(true);\n });\n\n it(\"ignores published platform packages\", () => {\n expect(\n shouldPreferWorkspaceBinding(\n `${path.sep}repo${path.sep}node_modules${path.sep}.pnpm${path.sep}@vizejs+native-darwin-arm64${path.sep}node_modules${path.sep}@vizejs${path.sep}native-darwin-arm64${path.sep}index.js`,\n ),\n ).toBe(false);\n });\n\n it(\"returns false when the fallback package cannot be resolved\", () => {\n expect(shouldPreferWorkspaceBinding(null)).toBe(false);\n });\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vize",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "description": "Vize - High-performance Vue.js toolchain in Rust",
5
5
  "keywords": [
6
6
  "cli",
@@ -56,14 +56,14 @@
56
56
  "vite-plus": "0.1.19"
57
57
  },
58
58
  "optionalDependencies": {
59
- "@vizejs/native-darwin-arm64": "0.64.0",
60
- "@vizejs/native-darwin-x64": "0.64.0",
61
- "@vizejs/native-linux-arm64-gnu": "0.64.0",
62
- "@vizejs/native-linux-arm64-musl": "0.64.0",
63
- "@vizejs/native-linux-x64-gnu": "0.64.0",
64
- "@vizejs/native-linux-x64-musl": "0.64.0",
65
- "@vizejs/native-win32-arm64-msvc": "0.64.0",
66
- "@vizejs/native-win32-x64-msvc": "0.64.0"
59
+ "@vizejs/native-darwin-arm64": "0.65.0",
60
+ "@vizejs/native-darwin-x64": "0.65.0",
61
+ "@vizejs/native-linux-arm64-gnu": "0.65.0",
62
+ "@vizejs/native-linux-arm64-musl": "0.65.0",
63
+ "@vizejs/native-linux-x64-gnu": "0.65.0",
64
+ "@vizejs/native-linux-x64-musl": "0.65.0",
65
+ "@vizejs/native-win32-arm64-msvc": "0.65.0",
66
+ "@vizejs/native-win32-x64-msvc": "0.65.0"
67
67
  },
68
68
  "engines": {
69
69
  "node": ">=18"
package/src/cli.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { readFileSync } from "node:fs";
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
2
  import { spawnSync } from "node:child_process";
3
3
  import * as path from "node:path";
4
4
  import { createRequire } from "node:module";
@@ -63,6 +63,7 @@ function getBindingPackageName(): string {
63
63
  }
64
64
 
65
65
  interface NativeBinding {
66
+ typeCheck: (source: string, options?: NativeTypeCheckOptions) => TypeCheckResult;
66
67
  lint: (
67
68
  patterns: string[],
68
69
  options?: {
@@ -76,15 +77,15 @@ interface NativeBinding {
76
77
  ) => LintResult;
77
78
  }
78
79
 
79
- function loadNative(): NativeBinding {
80
+ function loadNative(command: "check" | "lint"): NativeBinding {
80
81
  const attemptedPackages = getAttemptedPackages();
81
82
  let lastError: unknown = null;
82
83
 
83
84
  for (const packageName of attemptedPackages) {
84
85
  try {
85
86
  const binding = require(packageName) as Partial<NativeBinding>;
86
- if (typeof binding.lint !== "function") {
87
- throw new Error(`${packageName} does not expose the lint binding.`);
87
+ if (typeof binding[command === "check" ? "typeCheck" : "lint"] !== "function") {
88
+ throw new Error(`${packageName} does not expose the ${command} binding.`);
88
89
  }
89
90
  return binding as NativeBinding;
90
91
  } catch (error) {
@@ -161,7 +162,23 @@ interface ParsedLintCommand {
161
162
 
162
163
  function printUsage(): void {
163
164
  console.error("Usage: vize <command> [options]");
164
- console.error("Commands: lint, musea");
165
+ console.error("Commands: check, lint, musea");
166
+ }
167
+
168
+ function printCheckUsage(): void {
169
+ console.error("Usage: vize check [options] [files-or-directories]");
170
+ console.error("Options:");
171
+ console.error(" -f, --format <text|json> Output format");
172
+ console.error(" -q, --quiet Show summary only");
173
+ console.error(" --strict Enable strict checks");
174
+ console.error(" --show-virtual-ts Print generated Virtual TS");
175
+ console.error(" --max-warnings <number> Fail when warnings exceed the limit");
176
+ console.error(" -c, --config <path> Use a specific vize config file");
177
+ console.error(" --no-config Disable config discovery");
178
+ console.error("");
179
+ console.error(
180
+ "Note: npm `vize check` uses the packaged NAPI checker. Install the Rust CLI for project-backed Corsa diagnostics.",
181
+ );
165
182
  }
166
183
 
167
184
  function resolvePackageBinaryFromCwd(packageName: string, binName: string = packageName): string {
@@ -242,6 +259,471 @@ function parseLintCommand(args: string[]): ParsedLintCommand {
242
259
  return { patterns, options, sharedConfig };
243
260
  }
244
261
 
262
+ // ============================================================================
263
+ // Check command
264
+ // ============================================================================
265
+
266
+ interface NativeTypeCheckOptions {
267
+ filename?: string;
268
+ strict?: boolean;
269
+ includeVirtualTs?: boolean;
270
+ include_virtual_ts?: boolean;
271
+ checkProps?: boolean;
272
+ check_props?: boolean;
273
+ checkEmits?: boolean;
274
+ check_emits?: boolean;
275
+ checkTemplateBindings?: boolean;
276
+ check_template_bindings?: boolean;
277
+ checkReactivity?: boolean;
278
+ check_reactivity?: boolean;
279
+ checkSetupContext?: boolean;
280
+ check_setup_context?: boolean;
281
+ checkInvalidExports?: boolean;
282
+ check_invalid_exports?: boolean;
283
+ checkFallthroughAttrs?: boolean;
284
+ check_fallthrough_attrs?: boolean;
285
+ }
286
+
287
+ interface TypeDiagnostic {
288
+ severity: string;
289
+ message: string;
290
+ start: number;
291
+ end: number;
292
+ code?: string;
293
+ help?: string;
294
+ related?: Array<{
295
+ message: string;
296
+ start: number;
297
+ end: number;
298
+ filename?: string;
299
+ }>;
300
+ }
301
+
302
+ interface TypeCheckResult {
303
+ diagnostics: TypeDiagnostic[];
304
+ virtualTs?: string;
305
+ errorCount: number;
306
+ warningCount: number;
307
+ analysisTimeMs?: number;
308
+ }
309
+
310
+ interface CheckOptions {
311
+ format?: string;
312
+ quiet?: boolean;
313
+ strict?: boolean;
314
+ includeVirtualTs?: boolean;
315
+ maxWarnings?: number;
316
+ checkProps?: boolean;
317
+ checkEmits?: boolean;
318
+ checkTemplateBindings?: boolean;
319
+ checkReactivity?: boolean;
320
+ checkSetupContext?: boolean;
321
+ checkInvalidExports?: boolean;
322
+ checkFallthroughAttrs?: boolean;
323
+ help?: boolean;
324
+ }
325
+
326
+ interface ParsedCheckCommand {
327
+ patterns: string[];
328
+ options: CheckOptions;
329
+ sharedConfig: SharedConfigOptions;
330
+ }
331
+
332
+ interface CheckedFileResult {
333
+ file: string;
334
+ source: string;
335
+ result: TypeCheckResult;
336
+ }
337
+
338
+ function parseCheckCommand(args: string[]): ParsedCheckCommand {
339
+ const patterns: string[] = [];
340
+ const options: CheckOptions = {};
341
+ const sharedConfig: SharedConfigOptions = {
342
+ configMode: "root",
343
+ };
344
+
345
+ for (let i = 0; i < args.length; i++) {
346
+ const arg = args[i];
347
+ if (arg === "--format" || arg === "-f") {
348
+ options.format = args[++i];
349
+ } else if (arg === "--quiet" || arg === "-q") {
350
+ options.quiet = true;
351
+ } else if (arg === "--strict") {
352
+ options.strict = true;
353
+ } else if (arg === "--no-strict") {
354
+ options.strict = false;
355
+ } else if (arg === "--show-virtual-ts" || arg === "--include-virtual-ts") {
356
+ options.includeVirtualTs = true;
357
+ } else if (arg === "--max-warnings") {
358
+ options.maxWarnings = Number.parseInt(args[++i], 10);
359
+ } else if (arg === "--no-check-props") {
360
+ options.checkProps = false;
361
+ } else if (arg === "--no-check-emits") {
362
+ options.checkEmits = false;
363
+ } else if (arg === "--no-check-template-bindings") {
364
+ options.checkTemplateBindings = false;
365
+ } else if (arg === "--no-check-reactivity") {
366
+ options.checkReactivity = false;
367
+ } else if (arg === "--no-check-setup-context") {
368
+ options.checkSetupContext = false;
369
+ } else if (arg === "--no-check-invalid-exports") {
370
+ options.checkInvalidExports = false;
371
+ } else if (arg === "--no-check-fallthrough-attrs") {
372
+ options.checkFallthroughAttrs = false;
373
+ } else if (arg === "--config" || arg === "-c") {
374
+ const configFile = args[++i];
375
+ if (!configFile) {
376
+ throw new Error("Missing path after --config");
377
+ }
378
+ sharedConfig.configFile = configFile;
379
+ } else if (arg === "--no-config") {
380
+ sharedConfig.configMode = "none";
381
+ } else if (arg === "--help" || arg === "-h") {
382
+ options.help = true;
383
+ } else if (arg === "--tsconfig" || arg === "--corsa-path" || arg === "--servers") {
384
+ i++;
385
+ } else if (arg === "--socket" || arg === "-s" || arg === "--declaration-dir") {
386
+ i++;
387
+ } else if (arg === "--profile" || arg === "--declaration") {
388
+ // Accepted for package-script compatibility with the Rust CLI. The npm
389
+ // checker does not currently emit project profiles or declarations.
390
+ } else if (!arg.startsWith("-")) {
391
+ patterns.push(arg);
392
+ }
393
+ }
394
+
395
+ return { patterns, options, sharedConfig };
396
+ }
397
+
398
+ function hasGlobSyntax(pattern: string): boolean {
399
+ return pattern.includes("*") || pattern.includes("?") || pattern.includes("[");
400
+ }
401
+
402
+ function normalizePath(filePath: string): string {
403
+ return filePath.split(path.sep).join("/");
404
+ }
405
+
406
+ function displayPath(filePath: string): string {
407
+ const relative = path.relative(process.cwd(), filePath);
408
+ if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) {
409
+ return normalizePath(relative);
410
+ }
411
+ return normalizePath(filePath);
412
+ }
413
+
414
+ function isVueFile(filePath: string): boolean {
415
+ return path.extname(filePath) === ".vue";
416
+ }
417
+
418
+ function collectVueFilesFromDirectory(directory: string, recursive: boolean): string[] {
419
+ const files: string[] = [];
420
+ const entries = readdirSync(directory, { withFileTypes: true });
421
+
422
+ for (const entry of entries) {
423
+ const entryPath = path.join(directory, entry.name);
424
+ if (entry.isDirectory()) {
425
+ if (entry.name === "node_modules" || entry.name === ".git") {
426
+ continue;
427
+ }
428
+ if (recursive) {
429
+ files.push(...collectVueFilesFromDirectory(entryPath, true));
430
+ }
431
+ } else if (entry.isFile() && isVueFile(entryPath)) {
432
+ files.push(entryPath);
433
+ }
434
+ }
435
+
436
+ return files;
437
+ }
438
+
439
+ function globBase(pattern: string): string {
440
+ const normalized = normalizePath(pattern);
441
+ const globIndex = normalized.search(/[*?[]/);
442
+ if (globIndex === -1) {
443
+ return normalized;
444
+ }
445
+
446
+ const beforeGlob = normalized.slice(0, globIndex);
447
+ const slashIndex = beforeGlob.lastIndexOf("/");
448
+ if (slashIndex === -1) {
449
+ return ".";
450
+ }
451
+ return beforeGlob.slice(0, slashIndex) || "/";
452
+ }
453
+
454
+ function globToRegExp(pattern: string): RegExp {
455
+ const normalized = normalizePath(pattern);
456
+ let source = "";
457
+
458
+ for (let i = 0; i < normalized.length; i++) {
459
+ const char = normalized[i];
460
+ const next = normalized[i + 1];
461
+ const afterNext = normalized[i + 2];
462
+
463
+ if (char === "*" && next === "*" && afterNext === "/") {
464
+ source += "(?:.*/)?";
465
+ i += 2;
466
+ } else if (char === "*" && next === "*") {
467
+ source += ".*";
468
+ i++;
469
+ } else if (char === "*") {
470
+ source += "[^/]*";
471
+ } else if (char === "?") {
472
+ source += "[^/]";
473
+ } else if ("\\^$+?.()|{}[]".includes(char)) {
474
+ source += `\\${char}`;
475
+ } else {
476
+ source += char;
477
+ }
478
+ }
479
+
480
+ return new RegExp(`^${source}$`);
481
+ }
482
+
483
+ function shouldRecurseGlob(pattern: string, base: string): boolean {
484
+ const normalizedPattern = normalizePath(pattern);
485
+ const normalizedBase = normalizePath(base);
486
+ const rest =
487
+ normalizedBase === "."
488
+ ? normalizedPattern
489
+ : normalizedPattern.slice(normalizedBase.length).replace(/^\/+/, "");
490
+ return rest.includes("/");
491
+ }
492
+
493
+ function collectVueFilesFromGlob(pattern: string): string[] {
494
+ const basePattern = globBase(pattern);
495
+ const base = path.resolve(process.cwd(), basePattern);
496
+ if (!existsSync(base)) {
497
+ return [];
498
+ }
499
+
500
+ const isAbsolutePattern = path.isAbsolute(pattern);
501
+ const normalizedPattern = normalizePath(isAbsolutePattern ? path.resolve(pattern) : pattern);
502
+ const regex = globToRegExp(normalizedPattern);
503
+ const candidates = collectVueFilesFromDirectory(base, shouldRecurseGlob(pattern, basePattern));
504
+
505
+ return candidates.filter((file) => {
506
+ const comparable = isAbsolutePattern
507
+ ? normalizePath(file)
508
+ : normalizePath(path.relative(process.cwd(), file));
509
+ return regex.test(comparable);
510
+ });
511
+ }
512
+
513
+ function collectCheckFiles(patterns: string[]): string[] {
514
+ const files = new Set<string>();
515
+ const inputs = patterns.length === 0 ? ["."] : patterns;
516
+
517
+ for (const input of inputs) {
518
+ if (hasGlobSyntax(input)) {
519
+ for (const file of collectVueFilesFromGlob(input)) {
520
+ files.add(path.resolve(file));
521
+ }
522
+ continue;
523
+ }
524
+
525
+ const resolved = path.resolve(process.cwd(), input);
526
+ if (!existsSync(resolved)) {
527
+ continue;
528
+ }
529
+
530
+ const stats = statSync(resolved);
531
+ if (stats.isDirectory()) {
532
+ for (const file of collectVueFilesFromDirectory(resolved, true)) {
533
+ files.add(path.resolve(file));
534
+ }
535
+ } else if (stats.isFile() && isVueFile(resolved)) {
536
+ files.add(resolved);
537
+ }
538
+ }
539
+
540
+ return Array.from(files).sort();
541
+ }
542
+
543
+ function lineStarts(source: string): number[] {
544
+ const starts = [0];
545
+ for (let i = 0; i < source.length; i++) {
546
+ if (source.charCodeAt(i) === 10) {
547
+ starts.push(i + 1);
548
+ }
549
+ }
550
+ return starts;
551
+ }
552
+
553
+ function offsetToLineColumn(starts: number[], offset: number): { line: number; column: number } {
554
+ let low = 0;
555
+ let high = starts.length - 1;
556
+ while (low <= high) {
557
+ const mid = Math.floor((low + high) / 2);
558
+ if (starts[mid] <= offset) {
559
+ low = mid + 1;
560
+ } else {
561
+ high = mid - 1;
562
+ }
563
+ }
564
+
565
+ const lineIndex = Math.max(0, high);
566
+ return {
567
+ line: lineIndex + 1,
568
+ column: offset - starts[lineIndex] + 1,
569
+ };
570
+ }
571
+
572
+ function toNativeTypeCheckOptions(file: string, options: CheckOptions): NativeTypeCheckOptions {
573
+ return {
574
+ filename: file,
575
+ strict: options.strict,
576
+ includeVirtualTs: options.includeVirtualTs,
577
+ include_virtual_ts: options.includeVirtualTs,
578
+ checkProps: options.checkProps,
579
+ check_props: options.checkProps,
580
+ checkEmits: options.checkEmits,
581
+ check_emits: options.checkEmits,
582
+ checkTemplateBindings: options.checkTemplateBindings,
583
+ check_template_bindings: options.checkTemplateBindings,
584
+ checkReactivity: options.checkReactivity,
585
+ check_reactivity: options.checkReactivity,
586
+ checkSetupContext: options.checkSetupContext,
587
+ check_setup_context: options.checkSetupContext,
588
+ checkInvalidExports: options.checkInvalidExports,
589
+ check_invalid_exports: options.checkInvalidExports,
590
+ checkFallthroughAttrs: options.checkFallthroughAttrs,
591
+ check_fallthrough_attrs: options.checkFallthroughAttrs,
592
+ };
593
+ }
594
+
595
+ function renderCheckText(
596
+ results: CheckedFileResult[],
597
+ options: CheckOptions,
598
+ timeMs: number,
599
+ ): void {
600
+ let totalErrors = 0;
601
+ let totalWarnings = 0;
602
+
603
+ for (const { file, source, result } of results) {
604
+ totalErrors += result.errorCount;
605
+ totalWarnings += result.warningCount;
606
+
607
+ if (options.includeVirtualTs && result.virtualTs) {
608
+ process.stderr.write(`\n=== ${displayPath(file)} ===\n${result.virtualTs}\n`);
609
+ }
610
+
611
+ if (options.quiet || result.diagnostics.length === 0) {
612
+ continue;
613
+ }
614
+
615
+ const starts = lineStarts(source);
616
+ process.stdout.write(`\n\x1b[4m${displayPath(file)}\x1b[0m\n`);
617
+ for (const diagnostic of result.diagnostics) {
618
+ const color = diagnostic.severity === "error" ? "\x1b[31m" : "\x1b[33m";
619
+ const location = offsetToLineColumn(starts, diagnostic.start);
620
+ const code = diagnostic.code ? ` [${diagnostic.code}]` : "";
621
+ process.stdout.write(
622
+ ` ${color}${diagnostic.severity}:${location.line}:${location.column}\x1b[0m${code} ${diagnostic.message}\n`,
623
+ );
624
+ if (diagnostic.help) {
625
+ process.stdout.write(` help: ${diagnostic.help}\n`);
626
+ }
627
+ }
628
+ }
629
+
630
+ const status = totalErrors > 0 ? "\x1b[31mERR\x1b[0m" : "\x1b[32mOK\x1b[0m";
631
+ process.stdout.write(
632
+ `\n${status} Type checked ${results.length} Vue files in ${timeMs.toFixed(2)}ms\n`,
633
+ );
634
+ if (totalErrors > 0) {
635
+ process.stdout.write(` \x1b[31m${totalErrors} error(s)\x1b[0m\n`);
636
+ } else {
637
+ process.stdout.write(" \x1b[32mNo type errors found!\x1b[0m\n");
638
+ }
639
+ if (totalWarnings > 0) {
640
+ process.stdout.write(` \x1b[33m${totalWarnings} warning(s)\x1b[0m\n`);
641
+ }
642
+ }
643
+
644
+ async function runCheck(args: string[]): Promise<void> {
645
+ const { patterns, options, sharedConfig } = parseCheckCommand(args);
646
+ if (options.help) {
647
+ printCheckUsage();
648
+ return;
649
+ }
650
+
651
+ const config = await loadConfig(process.cwd(), {
652
+ mode: sharedConfig.configMode,
653
+ configFile: sharedConfig.configFile,
654
+ env: {
655
+ mode: process.env.NODE_ENV ?? "development",
656
+ command: "check",
657
+ },
658
+ });
659
+
660
+ if (sharedConfig.configFile && !config) {
661
+ throw new Error(`Could not find config file: ${sharedConfig.configFile}`);
662
+ }
663
+
664
+ if (config?.typeChecker?.enabled === false) {
665
+ process.stderr.write(
666
+ "[vize] Skipping check because typeChecker.enabled is false in vize.config.\n",
667
+ );
668
+ return;
669
+ }
670
+
671
+ options.strict ??= config?.typeChecker?.strict;
672
+ options.checkProps ??= config?.typeChecker?.checkProps;
673
+ options.checkEmits ??= config?.typeChecker?.checkEmits;
674
+ options.checkTemplateBindings ??= config?.typeChecker?.checkTemplateBindings;
675
+
676
+ const files = collectCheckFiles(patterns);
677
+ if (files.length === 0) {
678
+ process.stderr.write(`No Vue files found matching inputs: ${JSON.stringify(patterns)}\n`);
679
+ return;
680
+ }
681
+
682
+ const native = loadNative("check");
683
+ const start = performance.now();
684
+ const results = files.map((file) => {
685
+ const source = readFileSync(file, "utf8");
686
+ return {
687
+ file,
688
+ source,
689
+ result: native.typeCheck(source, toNativeTypeCheckOptions(file, options)),
690
+ };
691
+ });
692
+ const timeMs = performance.now() - start;
693
+ const totalErrors = results.reduce((sum, { result }) => sum + result.errorCount, 0);
694
+ const totalWarnings = results.reduce((sum, { result }) => sum + result.warningCount, 0);
695
+
696
+ if (options.format === "json") {
697
+ process.stdout.write(
698
+ `${JSON.stringify(
699
+ {
700
+ files: results.map(({ file, result }) => ({
701
+ file: displayPath(file),
702
+ diagnostics: result.diagnostics,
703
+ virtualTs: result.virtualTs,
704
+ })),
705
+ errorCount: totalErrors,
706
+ warningCount: totalWarnings,
707
+ fileCount: results.length,
708
+ },
709
+ null,
710
+ 2,
711
+ )}\n`,
712
+ );
713
+ } else {
714
+ renderCheckText(results, options, timeMs);
715
+ }
716
+
717
+ if (totalErrors > 0) {
718
+ process.exit(1);
719
+ }
720
+
721
+ if (options.maxWarnings !== undefined && totalWarnings > options.maxWarnings) {
722
+ process.stderr.write(`\nToo many warnings (${totalWarnings} > max ${options.maxWarnings})\n`);
723
+ process.exit(1);
724
+ }
725
+ }
726
+
245
727
  async function runLint(args: string[]): Promise<void> {
246
728
  const { patterns, options, sharedConfig } = parseLintCommand(args);
247
729
  const config = await loadConfig(process.cwd(), {
@@ -268,7 +750,7 @@ async function runLint(args: string[]): Promise<void> {
268
750
  patterns.push(".");
269
751
  }
270
752
 
271
- const native = loadNative();
753
+ const native = loadNative("lint");
272
754
  const result = native.lint(patterns, {
273
755
  format: options.format,
274
756
  max_warnings: options.maxWarnings,
@@ -305,7 +787,7 @@ async function runLint(args: string[]): Promise<void> {
305
787
  // Command router
306
788
  // ============================================================================
307
789
 
308
- const NAPI_COMMANDS = new Set(["lint"]);
790
+ const NAPI_COMMANDS = new Set(["check", "lint"]);
309
791
  const JS_COMMANDS = new Set(["musea"]);
310
792
 
311
793
  async function main(): Promise<void> {
@@ -320,6 +802,9 @@ async function main(): Promise<void> {
320
802
  if (NAPI_COMMANDS.has(command)) {
321
803
  const commandArgs = args.slice(1);
322
804
  switch (command) {
805
+ case "check":
806
+ await runCheck(commandArgs);
807
+ break;
323
808
  case "lint":
324
809
  await runLint(commandArgs);
325
810
  break;