uilint 0.2.3 → 0.2.4

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/dist/index.js CHANGED
@@ -357,8 +357,8 @@ import { dirname, join as join2 } from "path";
357
357
  import { fileURLToPath } from "url";
358
358
  function getCLIVersion() {
359
359
  try {
360
- const __dirname2 = dirname(fileURLToPath(import.meta.url));
361
- const pkgPath = join2(__dirname2, "..", "..", "package.json");
360
+ const __dirname3 = dirname(fileURLToPath(import.meta.url));
361
+ const pkgPath = join2(__dirname3, "..", "..", "package.json");
362
362
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
363
363
  return pkg.version || "0.0.0";
364
364
  } catch {
@@ -1475,13 +1475,13 @@ async function update(options) {
1475
1475
  }
1476
1476
 
1477
1477
  // src/commands/install.ts
1478
- import { join as join15 } from "path";
1478
+ import { join as join16 } from "path";
1479
1479
  import { ruleRegistry as ruleRegistry2 } from "uilint-eslint";
1480
1480
 
1481
1481
  // src/commands/install/analyze.ts
1482
1482
  import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
1483
1483
  import { join as join8 } from "path";
1484
- import { findWorkspaceRoot as findWorkspaceRoot4 } from "uilint-core/node";
1484
+ import { findWorkspaceRoot as findWorkspaceRoot5 } from "uilint-core/node";
1485
1485
 
1486
1486
  // src/utils/next-detect.ts
1487
1487
  import { existsSync as existsSync4, readdirSync } from "fs";
@@ -1714,6 +1714,24 @@ function isFrontendPackage(pkgJson) {
1714
1714
  };
1715
1715
  return FRONTEND_INDICATORS.some((pkg) => pkg in deps);
1716
1716
  }
1717
+ function isTypeScriptPackage(dir, pkgJson) {
1718
+ if (existsSync6(join5(dir, "tsconfig.json"))) {
1719
+ return true;
1720
+ }
1721
+ const deps = {
1722
+ ...pkgJson.dependencies,
1723
+ ...pkgJson.devDependencies
1724
+ };
1725
+ if ("typescript" in deps) {
1726
+ return true;
1727
+ }
1728
+ for (const configFile of ESLINT_CONFIG_FILES) {
1729
+ if (configFile.endsWith(".ts") && existsSync6(join5(dir, configFile))) {
1730
+ return true;
1731
+ }
1732
+ }
1733
+ return false;
1734
+ }
1717
1735
  function hasEslintConfig(dir) {
1718
1736
  for (const file of ESLINT_CONFIG_FILES) {
1719
1737
  if (existsSync6(join5(dir, file))) {
@@ -1747,7 +1765,8 @@ function findPackages(rootDir, options) {
1747
1765
  name,
1748
1766
  hasEslintConfig: hasEslintConfig(dir),
1749
1767
  isFrontend: isFrontendPackage(pkg),
1750
- isRoot
1768
+ isRoot,
1769
+ isTypeScript: isTypeScriptPackage(dir, pkg)
1751
1770
  };
1752
1771
  } catch {
1753
1772
  return null;
@@ -1853,8 +1872,9 @@ async function installDependencies(pm, projectPath, packages) {
1853
1872
 
1854
1873
  // src/utils/eslint-config-inject.ts
1855
1874
  import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
1856
- import { join as join7 } from "path";
1875
+ import { join as join7, relative as relative2, dirname as dirname6 } from "path";
1857
1876
  import { parseExpression, parseModule, generateCode } from "magicast";
1877
+ import { findWorkspaceRoot as findWorkspaceRoot4 } from "uilint-core/node";
1858
1878
  var CONFIG_EXTENSIONS = [".ts", ".mjs", ".js", ".cjs"];
1859
1879
  function findEslintConfigFile(projectPath) {
1860
1880
  for (const ext of CONFIG_EXTENSIONS) {
@@ -1869,25 +1889,6 @@ function getEslintConfigFilename(configPath) {
1869
1889
  const parts = configPath.split("/");
1870
1890
  return parts[parts.length - 1] || "eslint.config.mjs";
1871
1891
  }
1872
- function hasUilintImport(source) {
1873
- return source.includes('from "uilint-eslint"') || source.includes("from 'uilint-eslint'") || source.includes('require("uilint-eslint")') || source.includes("require('uilint-eslint')");
1874
- }
1875
- function hasUilintConfigsUsage(source) {
1876
- return /\builint\s*\.\s*configs\s*\./.test(source);
1877
- }
1878
- function walkAst(node, visit) {
1879
- if (!node || typeof node !== "object") return;
1880
- visit(node);
1881
- for (const key of Object.keys(node)) {
1882
- const v = node[key];
1883
- if (!v) continue;
1884
- if (Array.isArray(v)) {
1885
- for (const item of v) walkAst(item, visit);
1886
- } else if (typeof v === "object" && v.type) {
1887
- walkAst(v, visit);
1888
- }
1889
- }
1890
- }
1891
1892
  function isIdentifier(node, name) {
1892
1893
  return !!node && node.type === "Identifier" && (name ? node.name === name : typeof node.name === "string");
1893
1894
  }
@@ -1912,35 +1913,6 @@ function hasSpreadProperties(obj) {
1912
1913
  (p2) => p2 && (p2.type === "SpreadElement" || p2.type === "SpreadProperty")
1913
1914
  );
1914
1915
  }
1915
- var IGNORED_AST_KEYS = /* @__PURE__ */ new Set([
1916
- "loc",
1917
- "start",
1918
- "end",
1919
- "extra",
1920
- "leadingComments",
1921
- "trailingComments",
1922
- "innerComments"
1923
- ]);
1924
- function normalizeAstForCompare(node) {
1925
- if (node === null) return null;
1926
- if (node === void 0) return void 0;
1927
- if (typeof node !== "object") return node;
1928
- if (Array.isArray(node)) return node.map(normalizeAstForCompare);
1929
- const out = {};
1930
- const keys = Object.keys(node).filter((k) => !IGNORED_AST_KEYS.has(k)).sort();
1931
- for (const k of keys) {
1932
- if (k.startsWith("$")) continue;
1933
- out[k] = normalizeAstForCompare(node[k]);
1934
- }
1935
- return out;
1936
- }
1937
- function astEquivalent(a, b) {
1938
- try {
1939
- return JSON.stringify(normalizeAstForCompare(a)) === JSON.stringify(normalizeAstForCompare(b));
1940
- } catch {
1941
- return false;
1942
- }
1943
- }
1944
1916
  function collectUilintRuleIdsFromRulesObject(rulesObj) {
1945
1917
  const ids = /* @__PURE__ */ new Set();
1946
1918
  if (!rulesObj || rulesObj.type !== "ObjectExpression") return ids;
@@ -1951,8 +1923,9 @@ function collectUilintRuleIdsFromRulesObject(rulesObj) {
1951
1923
  if (!isStringLiteral(key)) continue;
1952
1924
  const val = key.value;
1953
1925
  if (typeof val !== "string") continue;
1954
- if (!val.startsWith("uilint/")) continue;
1955
- ids.add(val.slice("uilint/".length));
1926
+ if (val.startsWith("uilint/")) {
1927
+ ids.add(val.slice("uilint/".length));
1928
+ }
1956
1929
  }
1957
1930
  return ids;
1958
1931
  }
@@ -2045,24 +2018,6 @@ function findExportedConfigArrayExpression(mod) {
2045
2018
  }
2046
2019
  return null;
2047
2020
  }
2048
- function findUsesUilintConfigs(program2) {
2049
- let found = false;
2050
- walkAst(program2, (n) => {
2051
- if (found) return;
2052
- if (n?.type === "MemberExpression") {
2053
- const obj = n.object;
2054
- const prop = n.property;
2055
- if (isIdentifier(prop, "configs") && isIdentifier(obj, "uilint")) {
2056
- found = true;
2057
- return;
2058
- }
2059
- if (obj?.type === "MemberExpression" && isIdentifier(obj.object, "uilint") && isIdentifier(obj.property, "configs")) {
2060
- found = true;
2061
- }
2062
- }
2063
- });
2064
- return found;
2065
- }
2066
2021
  function collectConfiguredUilintRuleIdsFromConfigArray(arrayExpr) {
2067
2022
  const ids = /* @__PURE__ */ new Set();
2068
2023
  if (!arrayExpr || arrayExpr.type !== "ArrayExpression") return ids;
@@ -2115,69 +2070,68 @@ function chooseUniqueIdentifier(base, used) {
2115
2070
  while (used.has(`${base}${i}`)) i++;
2116
2071
  return `${base}${i}`;
2117
2072
  }
2118
- function getEsmUilintDefaultImportLocal(mod) {
2119
- const items = mod?.imports?.$items ?? [];
2120
- const found = items.find(
2121
- (it) => it?.from === "uilint-eslint" && it?.imported === "default"
2122
- );
2123
- return found?.local ?? null;
2124
- }
2125
- function ensureUilintImportAst(mod) {
2126
- const existing = getEsmUilintDefaultImportLocal(mod);
2127
- if (existing) return { local: existing, changed: false };
2128
- mod.imports.$prepend({
2129
- imported: "default",
2130
- local: "uilint",
2131
- from: "uilint-eslint"
2132
- });
2133
- return { local: "uilint", changed: true };
2134
- }
2135
- function findCjsUilintRequireBinding(program2) {
2136
- if (!program2 || program2.type !== "Program") return null;
2137
- for (const stmt of program2.body ?? []) {
2138
- if (stmt?.type !== "VariableDeclaration") continue;
2139
- for (const decl of stmt.declarations ?? []) {
2140
- const id = decl?.id;
2141
- const init = decl?.init;
2142
- if (!isIdentifier(id)) continue;
2143
- if (init?.type === "CallExpression" && isIdentifier(init.callee, "require") && isStringLiteral(init.arguments?.[0]) && init.arguments[0].value === "uilint-eslint") {
2144
- return id.name;
2145
- }
2146
- }
2073
+ function addLocalRuleImportsAst(mod, selectedRules, configPath, rulesRoot, fileExtension = ".js") {
2074
+ const importNames = /* @__PURE__ */ new Map();
2075
+ let changed = false;
2076
+ const configDir = dirname6(configPath);
2077
+ const rulesDir = join7(rulesRoot, ".uilint", "rules");
2078
+ const relativeRulesPath = relative2(configDir, rulesDir).replace(/\\/g, "/");
2079
+ const normalizedRulesPath = relativeRulesPath.startsWith("./") || relativeRulesPath.startsWith("../") ? relativeRulesPath : `./${relativeRulesPath}`;
2080
+ const used = collectTopLevelBindings(mod.$ast);
2081
+ for (const rule of selectedRules) {
2082
+ const importName = chooseUniqueIdentifier(
2083
+ `${rule.id.replace(/-([a-z])/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase())}Rule`,
2084
+ used
2085
+ );
2086
+ importNames.set(rule.id, importName);
2087
+ used.add(importName);
2088
+ const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;
2089
+ mod.imports.$add({
2090
+ imported: "default",
2091
+ local: importName,
2092
+ from: rulePath
2093
+ });
2094
+ changed = true;
2147
2095
  }
2148
- return null;
2096
+ return { importNames, changed };
2149
2097
  }
2150
- function ensureUilintRequireAst(program2) {
2098
+ function addLocalRuleRequiresAst(program2, selectedRules, configPath, rulesRoot, fileExtension = ".js") {
2099
+ const importNames = /* @__PURE__ */ new Map();
2100
+ let changed = false;
2151
2101
  if (!program2 || program2.type !== "Program") {
2152
- return { local: "uilint", changed: false };
2102
+ return { importNames, changed };
2153
2103
  }
2154
- const existing = findCjsUilintRequireBinding(program2);
2155
- if (existing) return { local: existing, changed: false };
2104
+ const configDir = dirname6(configPath);
2105
+ const rulesDir = join7(rulesRoot, ".uilint", "rules");
2106
+ const relativeRulesPath = relative2(configDir, rulesDir).replace(/\\/g, "/");
2107
+ const normalizedRulesPath = relativeRulesPath.startsWith("./") || relativeRulesPath.startsWith("../") ? relativeRulesPath : `./${relativeRulesPath}`;
2156
2108
  const used = collectTopLevelBindings(program2);
2157
- const local = chooseUniqueIdentifier("uilint", used);
2158
- const stmtMod = parseModule(`const ${local} = require("uilint-eslint");`);
2159
- const stmt = stmtMod.$ast.body?.[0];
2160
- if (!stmt) return { local, changed: false };
2161
- let insertAt = 0;
2162
- const first = program2.body?.[0];
2163
- if (first?.type === "ExpressionStatement" && first.expression?.type === "StringLiteral" && first.expression.value === "use strict") {
2164
- insertAt = 1;
2165
- }
2166
- program2.body.splice(insertAt, 0, stmt);
2167
- return { local, changed: true };
2168
- }
2169
- function buildUilintRuleProperty(rule) {
2170
- const ruleKey = `uilint/${rule.id}`;
2171
- const valueCode = rule.defaultOptions && rule.defaultOptions.length > 0 ? `["${rule.defaultSeverity}", ...${JSON.stringify(
2172
- rule.defaultOptions,
2173
- null,
2174
- 2
2175
- )}]` : `"${rule.defaultSeverity}"`;
2176
- const expr = parseExpression(`({ "${ruleKey}": ${valueCode} })`);
2177
- const obj = expr.$ast;
2178
- return obj.properties?.[0];
2179
- }
2180
- function appendUilintConfigBlockToArray(arrayExpr, selectedRules, uilintRef) {
2109
+ for (const rule of selectedRules) {
2110
+ const importName = chooseUniqueIdentifier(
2111
+ `${rule.id.replace(/-([a-z])/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase())}Rule`,
2112
+ used
2113
+ );
2114
+ importNames.set(rule.id, importName);
2115
+ used.add(importName);
2116
+ const rulePath = `${normalizedRulesPath}/${rule.id}${fileExtension}`;
2117
+ const stmtMod = parseModule(
2118
+ `const ${importName} = require("${rulePath}");`
2119
+ );
2120
+ const stmt = stmtMod.$ast.body?.[0];
2121
+ if (stmt) {
2122
+ let insertAt = 0;
2123
+ const first = program2.body?.[0];
2124
+ if (first?.type === "ExpressionStatement" && first.expression?.type === "StringLiteral" && first.expression.value === "use strict") {
2125
+ insertAt = 1;
2126
+ }
2127
+ program2.body.splice(insertAt, 0, stmt);
2128
+ changed = true;
2129
+ }
2130
+ }
2131
+ return { importNames, changed };
2132
+ }
2133
+ function appendUilintConfigBlockToArray(arrayExpr, selectedRules, ruleImportNames) {
2134
+ const pluginRulesCode = Array.from(ruleImportNames.entries()).map(([ruleId, importName]) => ` "${ruleId}": ${importName},`).join("\n");
2181
2135
  const rulesPropsCode = selectedRules.map((r) => {
2182
2136
  const ruleKey = `uilint/${r.id}`;
2183
2137
  const valueCode = r.defaultOptions && r.defaultOptions.length > 0 ? `["${r.defaultSeverity}", ...${JSON.stringify(
@@ -2193,7 +2147,13 @@ function appendUilintConfigBlockToArray(arrayExpr, selectedRules, uilintRef) {
2193
2147
  "app/**/*.{js,jsx,ts,tsx}",
2194
2148
  "pages/**/*.{js,jsx,ts,tsx}",
2195
2149
  ],
2196
- plugins: { uilint: ${uilintRef} },
2150
+ plugins: {
2151
+ uilint: {
2152
+ rules: {
2153
+ ${pluginRulesCode}
2154
+ },
2155
+ },
2156
+ },
2197
2157
  rules: {
2198
2158
  ${rulesPropsCode}
2199
2159
  },
@@ -2210,14 +2170,13 @@ function getUilintEslintConfigInfoFromSourceAst(source) {
2210
2170
  error: "Could not locate an exported ESLint flat config array (expected `export default [...]`, `export default defineConfig([...])`, `module.exports = [...]`, or `module.exports = defineConfig([...])`)."
2211
2171
  };
2212
2172
  }
2213
- const usesUilintConfigs = findUsesUilintConfigs(found.program);
2214
2173
  const configuredRuleIds = collectConfiguredUilintRuleIdsFromConfigArray(
2215
2174
  found.arrayExpr
2216
2175
  );
2217
2176
  const existingUilint = findExistingUilintRulesObject(found.arrayExpr);
2218
- const configured = usesUilintConfigs || configuredRuleIds.size > 0 || existingUilint.configObj !== null || hasUilintImport(source);
2177
+ const configured = configuredRuleIds.size > 0 || existingUilint.configObj !== null;
2219
2178
  return {
2220
- info: { usesUilintConfigs, configuredRuleIds, configured },
2179
+ info: { configuredRuleIds, configured },
2221
2180
  mod,
2222
2181
  arrayExpr: found.arrayExpr,
2223
2182
  kind: found.kind
@@ -2232,11 +2191,9 @@ function getUilintEslintConfigInfoFromSource(source) {
2232
2191
  const ast = getUilintEslintConfigInfoFromSourceAst(source);
2233
2192
  if ("error" in ast) {
2234
2193
  const configuredRuleIds = extractConfiguredUilintRuleIds(source);
2235
- const usesUilintConfigs = hasUilintConfigsUsage(source);
2236
2194
  return {
2237
- usesUilintConfigs,
2238
2195
  configuredRuleIds,
2239
- configured: usesUilintConfigs || configuredRuleIds.size > 0 || hasUilintImport(source)
2196
+ configured: configuredRuleIds.size > 0
2240
2197
  };
2241
2198
  }
2242
2199
  return ast.info;
@@ -2279,10 +2236,15 @@ async function installEslintPlugin(opts) {
2279
2236
  };
2280
2237
  }
2281
2238
  const { info, mod, arrayExpr, kind } = ast;
2282
- const usesUilintConfigs = info.usesUilintConfigs;
2283
2239
  const configuredIds = info.configuredRuleIds;
2284
- const missingRules = usesUilintConfigs ? [] : getMissingSelectedRules(opts.selectedRules, configuredIds);
2285
- const rulesToUpdate = usesUilintConfigs ? [] : getRulesNeedingUpdate(opts.selectedRules, configuredIds);
2240
+ const missingRules = getMissingSelectedRules(
2241
+ opts.selectedRules,
2242
+ configuredIds
2243
+ );
2244
+ const rulesToUpdate = getRulesNeedingUpdate(
2245
+ opts.selectedRules,
2246
+ configuredIds
2247
+ );
2286
2248
  let rulesToApply = [];
2287
2249
  if (!info.configured) {
2288
2250
  rulesToApply = opts.selectedRules;
@@ -2303,47 +2265,79 @@ async function installEslintPlugin(opts) {
2303
2265
  }
2304
2266
  }
2305
2267
  }
2268
+ if (rulesToApply.length === 0) {
2269
+ return {
2270
+ configFile: configFilename,
2271
+ modified: false,
2272
+ missingRuleIds: missingRules.map((r) => r.id),
2273
+ configured: info.configured
2274
+ };
2275
+ }
2306
2276
  let modifiedAst = false;
2307
- if (!usesUilintConfigs && rulesToApply.length > 0) {
2308
- const existing = findExistingUilintRulesObject(arrayExpr);
2309
- if (existing.safeToMutate && existing.rulesObj) {
2310
- let changedRules = false;
2311
- for (const rule of rulesToApply) {
2312
- const fullKey = `uilint/${rule.id}`;
2313
- const props = existing.rulesObj.properties ?? [];
2314
- const existingProp = props.find((p2) => {
2315
- if (!p2) return false;
2316
- if (p2.type !== "ObjectProperty" && p2.type !== "Property")
2317
- return false;
2318
- return isStringLiteral(p2.key) && p2.key.value === fullKey;
2319
- });
2320
- const newProp = buildUilintRuleProperty(rule);
2321
- if (!newProp) continue;
2322
- if (existingProp) {
2323
- if (!astEquivalent(existingProp.value, newProp.value)) {
2324
- existingProp.value = newProp.value;
2325
- changedRules = true;
2326
- }
2327
- } else {
2328
- props.push(newProp);
2329
- changedRules = true;
2330
- }
2331
- }
2332
- if (changedRules) modifiedAst = true;
2333
- } else {
2334
- const uilintRef = kind === "esm" ? ensureUilintImportAst(mod).local : ensureUilintRequireAst(mod.$ast).local;
2335
- appendUilintConfigBlockToArray(arrayExpr, rulesToApply, uilintRef);
2336
- modifiedAst = true;
2277
+ const localRulesDir = join7(opts.projectPath, ".uilint", "rules");
2278
+ const workspaceRoot = findWorkspaceRoot4(opts.projectPath);
2279
+ const workspaceRulesDir = join7(workspaceRoot, ".uilint", "rules");
2280
+ const rulesRoot = existsSync8(localRulesDir) ? opts.projectPath : workspaceRoot;
2281
+ let fileExtension = ".js";
2282
+ if (rulesToApply.length > 0) {
2283
+ const firstRulePath = join7(
2284
+ rulesRoot,
2285
+ ".uilint",
2286
+ "rules",
2287
+ `${rulesToApply[0].id}.ts`
2288
+ );
2289
+ if (existsSync8(firstRulePath)) {
2290
+ fileExtension = ".ts";
2337
2291
  }
2338
- } else if (!info.configured && !usesUilintConfigs) {
2339
2292
  }
2340
- if (modifiedAst || info.configured) {
2293
+ let ruleImportNames;
2294
+ if (kind === "esm") {
2295
+ const result = addLocalRuleImportsAst(
2296
+ mod,
2297
+ rulesToApply,
2298
+ configPath,
2299
+ rulesRoot,
2300
+ fileExtension
2301
+ );
2302
+ ruleImportNames = result.importNames;
2303
+ if (result.changed) modifiedAst = true;
2304
+ } else {
2305
+ const result = addLocalRuleRequiresAst(
2306
+ mod.$ast,
2307
+ rulesToApply,
2308
+ configPath,
2309
+ rulesRoot,
2310
+ fileExtension
2311
+ );
2312
+ ruleImportNames = result.importNames;
2313
+ if (result.changed) modifiedAst = true;
2314
+ }
2315
+ if (ruleImportNames && ruleImportNames.size > 0) {
2316
+ appendUilintConfigBlockToArray(arrayExpr, rulesToApply, ruleImportNames);
2317
+ modifiedAst = true;
2318
+ }
2319
+ if (!info.configured) {
2341
2320
  if (kind === "esm") {
2342
- const { changed } = ensureUilintImportAst(mod);
2343
- if (changed) modifiedAst = true;
2344
- } else if (kind === "cjs") {
2345
- const { changed } = ensureUilintRequireAst(mod.$ast);
2346
- if (changed) modifiedAst = true;
2321
+ mod.imports.$add({
2322
+ imported: "createRule",
2323
+ local: "createRule",
2324
+ from: "uilint-eslint"
2325
+ });
2326
+ modifiedAst = true;
2327
+ } else {
2328
+ const stmtMod = parseModule(
2329
+ `const { createRule } = require("uilint-eslint");`
2330
+ );
2331
+ const stmt = stmtMod.$ast.body?.[0];
2332
+ if (stmt) {
2333
+ let insertAt = 0;
2334
+ const first = mod.$ast.body?.[0];
2335
+ if (first?.type === "ExpressionStatement" && first.expression?.type === "StringLiteral" && first.expression.value === "use strict") {
2336
+ insertAt = 1;
2337
+ }
2338
+ mod.$ast.body.splice(insertAt, 0, stmt);
2339
+ modifiedAst = true;
2340
+ }
2347
2341
  }
2348
2342
  }
2349
2343
  const updated = modifiedAst ? generateCode(mod).code : original;
@@ -2375,7 +2369,7 @@ function safeParseJson(filePath) {
2375
2369
  }
2376
2370
  }
2377
2371
  async function analyze2(projectPath = process.cwd()) {
2378
- const workspaceRoot = findWorkspaceRoot4(projectPath);
2372
+ const workspaceRoot = findWorkspaceRoot5(projectPath);
2379
2373
  const packageManager = detectPackageManager(projectPath);
2380
2374
  const cursorDir = join8(projectPath, ".cursor");
2381
2375
  const cursorDirExists = existsSync9(cursorDir);
@@ -2435,7 +2429,7 @@ async function analyze2(projectPath = process.cwd()) {
2435
2429
  try {
2436
2430
  const source = readFileSync5(eslintConfigPath, "utf-8");
2437
2431
  const info = getUilintEslintConfigInfoFromSource(source);
2438
- hasRules = info.configuredRuleIds.size > 0 || info.usesUilintConfigs;
2432
+ hasRules = info.configuredRuleIds.size > 0;
2439
2433
  configuredRuleIds = Array.from(info.configuredRuleIds);
2440
2434
  } catch {
2441
2435
  }
@@ -2483,8 +2477,8 @@ async function analyze2(projectPath = process.cwd()) {
2483
2477
  }
2484
2478
 
2485
2479
  // src/commands/install/plan.ts
2486
- import { join as join10 } from "path";
2487
- import { createRequire } from "module";
2480
+ import { join as join11 } from "path";
2481
+ import { createRequire as createRequire2 } from "module";
2488
2482
 
2489
2483
  // src/commands/install/constants.ts
2490
2484
  var HOOKS_CONFIG = {
@@ -2874,10 +2868,10 @@ Generate in \`.uilint/rules/\`:
2874
2868
 
2875
2869
  // src/utils/skill-loader.ts
2876
2870
  import { readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync2, existsSync as existsSync10 } from "fs";
2877
- import { join as join9, dirname as dirname6, relative as relative2 } from "path";
2871
+ import { join as join9, dirname as dirname7, relative as relative3 } from "path";
2878
2872
  import { fileURLToPath as fileURLToPath2 } from "url";
2879
2873
  var __filename = fileURLToPath2(import.meta.url);
2880
- var __dirname = dirname6(__filename);
2874
+ var __dirname = dirname7(__filename);
2881
2875
  function getSkillsDir() {
2882
2876
  const devPath = join9(__dirname, "..", "..", "skills");
2883
2877
  const prodPath = join9(__dirname, "..", "skills");
@@ -2900,7 +2894,7 @@ function collectFiles(dir, baseDir) {
2900
2894
  if (stat.isDirectory()) {
2901
2895
  files.push(...collectFiles(fullPath, baseDir));
2902
2896
  } else if (stat.isFile()) {
2903
- const relativePath = relative2(baseDir, fullPath);
2897
+ const relativePath = relative3(baseDir, fullPath);
2904
2898
  const content = readFileSync6(fullPath, "utf-8");
2905
2899
  files.push({ relativePath, content });
2906
2900
  }
@@ -2921,11 +2915,130 @@ function loadSkill(name) {
2921
2915
  return { name, files };
2922
2916
  }
2923
2917
 
2924
- // src/commands/install/plan.ts
2918
+ // src/utils/rule-loader.ts
2919
+ import { readFileSync as readFileSync7, existsSync as existsSync11 } from "fs";
2920
+ import { join as join10, dirname as dirname8 } from "path";
2921
+ import { fileURLToPath as fileURLToPath3 } from "url";
2922
+ import { createRequire } from "module";
2923
+ var __filename2 = fileURLToPath3(import.meta.url);
2924
+ var __dirname2 = dirname8(__filename2);
2925
2925
  var require2 = createRequire(import.meta.url);
2926
+ function getUilintEslintPackageRoot() {
2927
+ const entry = require2.resolve("uilint-eslint");
2928
+ const entryDir = dirname8(entry);
2929
+ return dirname8(entryDir);
2930
+ }
2931
+ function getUilintEslintSrcDir() {
2932
+ const devPath = join10(
2933
+ __dirname2,
2934
+ "..",
2935
+ "..",
2936
+ "..",
2937
+ "..",
2938
+ "uilint-eslint",
2939
+ "src"
2940
+ );
2941
+ if (existsSync11(devPath)) return devPath;
2942
+ const pkgRoot = getUilintEslintPackageRoot();
2943
+ const srcPath = join10(pkgRoot, "src");
2944
+ if (existsSync11(srcPath)) return srcPath;
2945
+ throw new Error(
2946
+ 'Could not find uilint-eslint "src/" directory. If you are using a published install of uilint-eslint, ensure it includes source files, or run a JS-only rules install.'
2947
+ );
2948
+ }
2949
+ function getUilintEslintDistDir() {
2950
+ const devPath = join10(
2951
+ __dirname2,
2952
+ "..",
2953
+ "..",
2954
+ "..",
2955
+ "..",
2956
+ "uilint-eslint",
2957
+ "dist"
2958
+ );
2959
+ if (existsSync11(devPath)) return devPath;
2960
+ const pkgRoot = getUilintEslintPackageRoot();
2961
+ const distPath = join10(pkgRoot, "dist");
2962
+ if (existsSync11(distPath)) return distPath;
2963
+ throw new Error(
2964
+ 'Could not find uilint-eslint "dist/" directory. This is a bug in uilint installation.'
2965
+ );
2966
+ }
2967
+ function transformRuleContent(content) {
2968
+ let transformed = content;
2969
+ transformed = transformed.replace(
2970
+ /import\s+{\s*createRule\s*}\s+from\s+["']\.\.\/utils\/create-rule\.js["'];?/g,
2971
+ 'import { createRule } from "uilint-eslint";'
2972
+ );
2973
+ transformed = transformed.replace(
2974
+ /import\s+createRule\s+from\s+["']\.\.\/utils\/create-rule\.js["'];?/g,
2975
+ 'import { createRule } from "uilint-eslint";'
2976
+ );
2977
+ transformed = transformed.replace(
2978
+ /import\s+{([^}]+)}\s+from\s+["']\.\.\/utils\/([^"']+)\.js["'];?/g,
2979
+ (match, imports, utilFile) => {
2980
+ const utilsFromPackage = ["cache", "styleguide-loader", "import-graph"];
2981
+ if (utilsFromPackage.includes(utilFile)) {
2982
+ return `import {${imports}} from "uilint-eslint";`;
2983
+ }
2984
+ return match;
2985
+ }
2986
+ );
2987
+ return transformed;
2988
+ }
2989
+ function loadRule(ruleId, options = { typescript: true }) {
2990
+ const { typescript } = options;
2991
+ const extension = typescript ? ".ts" : ".js";
2992
+ if (typescript) {
2993
+ const rulesDir = join10(getUilintEslintSrcDir(), "rules");
2994
+ const implPath = join10(rulesDir, `${ruleId}.ts`);
2995
+ const testPath = join10(rulesDir, `${ruleId}.test.ts`);
2996
+ if (!existsSync11(implPath)) {
2997
+ throw new Error(`Rule "${ruleId}" not found at ${implPath}`);
2998
+ }
2999
+ const rawContent = readFileSync7(implPath, "utf-8");
3000
+ const transformedContent = transformRuleContent(rawContent);
3001
+ const implementation = {
3002
+ relativePath: `${ruleId}.ts`,
3003
+ content: transformedContent
3004
+ };
3005
+ const test = existsSync11(testPath) ? {
3006
+ relativePath: `${ruleId}.test.ts`,
3007
+ content: transformRuleContent(readFileSync7(testPath, "utf-8"))
3008
+ } : void 0;
3009
+ return {
3010
+ ruleId,
3011
+ implementation,
3012
+ test
3013
+ };
3014
+ } else {
3015
+ const rulesDir = join10(getUilintEslintDistDir(), "rules");
3016
+ const implPath = join10(rulesDir, `${ruleId}.js`);
3017
+ if (!existsSync11(implPath)) {
3018
+ throw new Error(
3019
+ `Rule "${ruleId}" not found at ${implPath}. Make sure uilint-eslint has been built.`
3020
+ );
3021
+ }
3022
+ const content = readFileSync7(implPath, "utf-8");
3023
+ const implementation = {
3024
+ relativePath: `${ruleId}.js`,
3025
+ content
3026
+ };
3027
+ return {
3028
+ ruleId,
3029
+ implementation
3030
+ };
3031
+ }
3032
+ }
3033
+ function loadSelectedRules(ruleIds, options = { typescript: true }) {
3034
+ return ruleIds.map((id) => loadRule(id, options));
3035
+ }
3036
+
3037
+ // src/commands/install/plan.ts
3038
+ var require3 = createRequire2(import.meta.url);
2926
3039
  function getSelfDependencyVersionRange(pkgName) {
2927
3040
  try {
2928
- const pkgJson = require2("uilint/package.json");
3041
+ const pkgJson = require3("uilint/package.json");
2929
3042
  const deps = pkgJson?.dependencies;
2930
3043
  const optDeps = pkgJson?.optionalDependencies;
2931
3044
  const peerDeps = pkgJson?.peerDependencies;
@@ -3000,7 +3113,7 @@ function createPlan(state, choices, options = {}) {
3000
3113
  }
3001
3114
  }
3002
3115
  if (items.includes("hooks")) {
3003
- const hooksDir = join10(state.cursorDir.path, "hooks");
3116
+ const hooksDir = join11(state.cursorDir.path, "hooks");
3004
3117
  actions.push({
3005
3118
  type: "create_directory",
3006
3119
  path: hooksDir
@@ -3026,63 +3139,66 @@ function createPlan(state, choices, options = {}) {
3026
3139
  });
3027
3140
  actions.push({
3028
3141
  type: "create_file",
3029
- path: join10(hooksDir, "uilint-session-start.sh"),
3142
+ path: join11(hooksDir, "uilint-session-start.sh"),
3030
3143
  content: SESSION_START_SCRIPT,
3031
3144
  permissions: 493
3032
3145
  });
3033
3146
  actions.push({
3034
3147
  type: "create_file",
3035
- path: join10(hooksDir, "uilint-track.sh"),
3148
+ path: join11(hooksDir, "uilint-track.sh"),
3036
3149
  content: TRACK_SCRIPT,
3037
3150
  permissions: 493
3038
3151
  });
3039
3152
  actions.push({
3040
3153
  type: "create_file",
3041
- path: join10(hooksDir, "uilint-session-end.sh"),
3154
+ path: join11(hooksDir, "uilint-session-end.sh"),
3042
3155
  content: SESSION_END_SCRIPT,
3043
3156
  permissions: 493
3044
3157
  });
3045
3158
  }
3046
3159
  if (items.includes("genstyleguide")) {
3047
- const commandsDir = join10(state.cursorDir.path, "commands");
3160
+ const commandsDir = join11(state.cursorDir.path, "commands");
3048
3161
  actions.push({
3049
3162
  type: "create_directory",
3050
3163
  path: commandsDir
3051
3164
  });
3052
3165
  actions.push({
3053
3166
  type: "create_file",
3054
- path: join10(commandsDir, "genstyleguide.md"),
3167
+ path: join11(commandsDir, "genstyleguide.md"),
3055
3168
  content: GENSTYLEGUIDE_COMMAND_MD
3056
3169
  });
3057
3170
  }
3058
3171
  if (items.includes("genrules")) {
3059
- const commandsDir = join10(state.cursorDir.path, "commands");
3172
+ const commandsDir = join11(state.cursorDir.path, "commands");
3060
3173
  actions.push({
3061
3174
  type: "create_directory",
3062
3175
  path: commandsDir
3063
3176
  });
3064
3177
  actions.push({
3065
3178
  type: "create_file",
3066
- path: join10(commandsDir, "genrules.md"),
3179
+ path: join11(commandsDir, "genrules.md"),
3067
3180
  content: GENRULES_COMMAND_MD
3068
3181
  });
3069
3182
  }
3070
3183
  if (items.includes("skill")) {
3071
- const skillsDir = join10(state.cursorDir.path, "skills");
3184
+ const skillsDir = join11(state.cursorDir.path, "skills");
3072
3185
  actions.push({
3073
3186
  type: "create_directory",
3074
3187
  path: skillsDir
3075
3188
  });
3076
3189
  try {
3077
3190
  const skill = loadSkill("ui-consistency-enforcer");
3078
- const skillDir = join10(skillsDir, skill.name);
3191
+ const skillDir = join11(skillsDir, skill.name);
3079
3192
  actions.push({
3080
3193
  type: "create_directory",
3081
3194
  path: skillDir
3082
3195
  });
3083
3196
  for (const file of skill.files) {
3084
- const filePath = join10(skillDir, file.relativePath);
3085
- const fileDir = join10(skillDir, file.relativePath.split("/").slice(0, -1).join("/"));
3197
+ const filePath = join11(skillDir, file.relativePath);
3198
+ const fileDir = join11(
3199
+ skillDir,
3200
+ file.relativePath.split("/").slice(0, -1).join("/")
3201
+ );
3086
3202
  if (fileDir !== skillDir && file.relativePath.includes("/")) {
3087
3203
  actions.push({
3088
3204
  type: "create_directory",
@@ -3142,6 +3258,35 @@ function createPlan(state, choices, options = {}) {
3142
3258
  const { packagePaths, selectedRules } = choices.eslint;
3143
3259
  for (const pkgPath of packagePaths) {
3144
3260
  const pkgInfo = state.packages.find((p2) => p2.path === pkgPath);
3261
+ const rulesDir = join11(pkgPath, ".uilint", "rules");
3262
+ actions.push({
3263
+ type: "create_directory",
3264
+ path: rulesDir
3265
+ });
3266
+ const isTypeScript = pkgInfo?.isTypeScript ?? true;
3267
+ try {
3268
+ const ruleFiles = loadSelectedRules(
3269
+ selectedRules.map((r) => r.id),
3270
+ {
3271
+ typescript: isTypeScript
3272
+ }
3273
+ );
3274
+ for (const ruleFile of ruleFiles) {
3275
+ actions.push({
3276
+ type: "create_file",
3277
+ path: join11(rulesDir, ruleFile.implementation.relativePath),
3278
+ content: ruleFile.implementation.content
3279
+ });
3280
+ if (ruleFile.test && isTypeScript) {
3281
+ actions.push({
3282
+ type: "create_file",
3283
+ path: join11(rulesDir, ruleFile.test.relativePath),
3284
+ content: ruleFile.test.content
3285
+ });
3286
+ }
3287
+ }
3288
+ } catch {
3289
+ }
3145
3290
  dependencies.push({
3146
3291
  packagePath: pkgPath,
3147
3292
  packageManager: state.packageManager,
@@ -3157,7 +3302,7 @@ function createPlan(state, choices, options = {}) {
3157
3302
  });
3158
3303
  }
3159
3304
  }
3160
- const gitignorePath = join10(state.workspaceRoot, ".gitignore");
3305
+ const gitignorePath = join11(state.workspaceRoot, ".gitignore");
3161
3306
  actions.push({
3162
3307
  type: "append_to_file",
3163
3308
  path: gitignorePath,
@@ -3170,49 +3315,49 @@ function createPlan(state, choices, options = {}) {
3170
3315
 
3171
3316
  // src/commands/install/execute.ts
3172
3317
  import {
3173
- existsSync as existsSync15,
3318
+ existsSync as existsSync16,
3174
3319
  mkdirSync as mkdirSync3,
3175
3320
  writeFileSync as writeFileSync7,
3176
- readFileSync as readFileSync10,
3321
+ readFileSync as readFileSync11,
3177
3322
  unlinkSync,
3178
3323
  chmodSync
3179
3324
  } from "fs";
3180
- import { dirname as dirname7 } from "path";
3325
+ import { dirname as dirname9 } from "path";
3181
3326
 
3182
3327
  // src/utils/react-inject.ts
3183
- import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
3184
- import { join as join11 } from "path";
3328
+ import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
3329
+ import { join as join12 } from "path";
3185
3330
  import { parseModule as parseModule2, generateCode as generateCode2 } from "magicast";
3186
3331
  function getDefaultCandidates(projectPath, appRoot) {
3187
3332
  const viteMainCandidates = [
3188
- join11(appRoot, "main.tsx"),
3189
- join11(appRoot, "main.jsx"),
3190
- join11(appRoot, "main.ts"),
3191
- join11(appRoot, "main.js")
3333
+ join12(appRoot, "main.tsx"),
3334
+ join12(appRoot, "main.jsx"),
3335
+ join12(appRoot, "main.ts"),
3336
+ join12(appRoot, "main.js")
3192
3337
  ];
3193
3338
  const existingViteMain = viteMainCandidates.filter(
3194
- (rel) => existsSync11(join11(projectPath, rel))
3339
+ (rel) => existsSync12(join12(projectPath, rel))
3195
3340
  );
3196
3341
  if (existingViteMain.length > 0) return existingViteMain;
3197
- const viteAppCandidates = [join11(appRoot, "App.tsx"), join11(appRoot, "App.jsx")];
3342
+ const viteAppCandidates = [join12(appRoot, "App.tsx"), join12(appRoot, "App.jsx")];
3198
3343
  const existingViteApp = viteAppCandidates.filter(
3199
- (rel) => existsSync11(join11(projectPath, rel))
3344
+ (rel) => existsSync12(join12(projectPath, rel))
3200
3345
  );
3201
3346
  if (existingViteApp.length > 0) return existingViteApp;
3202
3347
  const layoutCandidates = [
3203
- join11(appRoot, "layout.tsx"),
3204
- join11(appRoot, "layout.jsx"),
3205
- join11(appRoot, "layout.ts"),
3206
- join11(appRoot, "layout.js")
3348
+ join12(appRoot, "layout.tsx"),
3349
+ join12(appRoot, "layout.jsx"),
3350
+ join12(appRoot, "layout.ts"),
3351
+ join12(appRoot, "layout.js")
3207
3352
  ];
3208
3353
  const existingLayouts = layoutCandidates.filter(
3209
- (rel) => existsSync11(join11(projectPath, rel))
3354
+ (rel) => existsSync12(join12(projectPath, rel))
3210
3355
  );
3211
3356
  if (existingLayouts.length > 0) {
3212
3357
  return existingLayouts;
3213
3358
  }
3214
- const pageCandidates = [join11(appRoot, "page.tsx"), join11(appRoot, "page.jsx")];
3215
- return pageCandidates.filter((rel) => existsSync11(join11(projectPath, rel)));
3359
+ const pageCandidates = [join12(appRoot, "page.tsx"), join12(appRoot, "page.jsx")];
3360
+ return pageCandidates.filter((rel) => existsSync12(join12(projectPath, rel)));
3216
3361
  }
3217
3362
  function isUseClientDirective(stmt) {
3218
3363
  return stmt?.type === "ExpressionStatement" && stmt.expression?.type === "StringLiteral" && stmt.expression.value === "use client";
@@ -3225,16 +3370,16 @@ function findImportDeclaration(program2, from) {
3225
3370
  }
3226
3371
  return null;
3227
3372
  }
3228
- function walkAst2(node, visit) {
3373
+ function walkAst(node, visit) {
3229
3374
  if (!node || typeof node !== "object") return;
3230
3375
  if (node.type) visit(node);
3231
3376
  for (const key of Object.keys(node)) {
3232
3377
  const v = node[key];
3233
3378
  if (!v) continue;
3234
3379
  if (Array.isArray(v)) {
3235
- for (const item of v) walkAst2(item, visit);
3380
+ for (const item of v) walkAst(item, visit);
3236
3381
  } else if (typeof v === "object" && v.type) {
3237
- walkAst2(v, visit);
3382
+ walkAst(v, visit);
3238
3383
  }
3239
3384
  }
3240
3385
  }
@@ -3266,7 +3411,7 @@ function ensureNamedImport(program2, from, name) {
3266
3411
  }
3267
3412
  function hasUILintProviderJsx(program2) {
3268
3413
  let found = false;
3269
- walkAst2(program2, (node) => {
3414
+ walkAst(program2, (node) => {
3270
3415
  if (found) return;
3271
3416
  if (node.type !== "JSXElement") return;
3272
3417
  const name = node.openingElement?.name;
@@ -3286,7 +3431,7 @@ function wrapFirstChildrenExpressionWithProvider(program2) {
3286
3431
  if (!providerJsx || providerJsx.type !== "JSXElement")
3287
3432
  return { changed: false };
3288
3433
  let replaced = false;
3289
- walkAst2(program2, (node) => {
3434
+ walkAst(program2, (node) => {
3290
3435
  if (replaced) return;
3291
3436
  if (node.type === "JSXExpressionContainer" && node.expression?.type === "Identifier" && node.expression.name === "children") {
3292
3437
  Object.keys(node).forEach((k) => delete node[k]);
@@ -3310,7 +3455,7 @@ function wrapFirstRenderCallArgumentWithProvider(program2) {
3310
3455
  return { changed: false };
3311
3456
  providerJsx.children = providerJsx.children ?? [];
3312
3457
  let wrapped = false;
3313
- walkAst2(program2, (node) => {
3458
+ walkAst(program2, (node) => {
3314
3459
  if (wrapped) return;
3315
3460
  if (node.type !== "CallExpression") return;
3316
3461
  const callee = node.callee;
@@ -3345,8 +3490,8 @@ async function installReactUILintOverlay(opts) {
3345
3490
  } else {
3346
3491
  chosen = candidates[0];
3347
3492
  }
3348
- const absTarget = join11(opts.projectPath, chosen);
3349
- const original = readFileSync7(absTarget, "utf-8");
3493
+ const absTarget = join12(opts.projectPath, chosen);
3494
+ const original = readFileSync8(absTarget, "utf-8");
3350
3495
  let mod;
3351
3496
  try {
3352
3497
  mod = parseModule2(original);
@@ -3380,14 +3525,14 @@ async function installReactUILintOverlay(opts) {
3380
3525
  }
3381
3526
 
3382
3527
  // src/utils/next-config-inject.ts
3383
- import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
3384
- import { join as join12 } from "path";
3528
+ import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
3529
+ import { join as join13 } from "path";
3385
3530
  import { parseModule as parseModule3, generateCode as generateCode3 } from "magicast";
3386
3531
  var CONFIG_EXTENSIONS2 = [".ts", ".mjs", ".js", ".cjs"];
3387
3532
  function findNextConfigFile(projectPath) {
3388
3533
  for (const ext of CONFIG_EXTENSIONS2) {
3389
- const configPath = join12(projectPath, `next.config${ext}`);
3390
- if (existsSync12(configPath)) {
3534
+ const configPath = join13(projectPath, `next.config${ext}`);
3535
+ if (existsSync13(configPath)) {
3391
3536
  return configPath;
3392
3537
  }
3393
3538
  }
@@ -3500,7 +3645,7 @@ async function installJsxLocPlugin(opts) {
3500
3645
  return { configFile: null, modified: false };
3501
3646
  }
3502
3647
  const configFilename = getNextConfigFilename(configPath);
3503
- const original = readFileSync8(configPath, "utf-8");
3648
+ const original = readFileSync9(configPath, "utf-8");
3504
3649
  let mod;
3505
3650
  try {
3506
3651
  mod = parseModule3(original);
@@ -3530,14 +3675,14 @@ async function installJsxLocPlugin(opts) {
3530
3675
  }
3531
3676
 
3532
3677
  // src/utils/vite-config-inject.ts
3533
- import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
3534
- import { join as join13 } from "path";
3678
+ import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
3679
+ import { join as join14 } from "path";
3535
3680
  import { parseModule as parseModule4, generateCode as generateCode4 } from "magicast";
3536
3681
  var CONFIG_EXTENSIONS3 = [".ts", ".mjs", ".js", ".cjs"];
3537
3682
  function findViteConfigFile2(projectPath) {
3538
3683
  for (const ext of CONFIG_EXTENSIONS3) {
3539
- const configPath = join13(projectPath, `vite.config${ext}`);
3540
- if (existsSync13(configPath)) return configPath;
3684
+ const configPath = join14(projectPath, `vite.config${ext}`);
3685
+ if (existsSync14(configPath)) return configPath;
3541
3686
  }
3542
3687
  return null;
3543
3688
  }
@@ -3712,7 +3857,7 @@ async function installViteJsxLocPlugin(opts) {
3712
3857
  const configPath = findViteConfigFile2(opts.projectPath);
3713
3858
  if (!configPath) return { configFile: null, modified: false };
3714
3859
  const configFilename = getViteConfigFilename(configPath);
3715
- const original = readFileSync9(configPath, "utf-8");
3860
+ const original = readFileSync10(configPath, "utf-8");
3716
3861
  const isCjs = configPath.endsWith(".cjs");
3717
3862
  let mod;
3718
3863
  try {
@@ -3741,9 +3886,9 @@ async function installViteJsxLocPlugin(opts) {
3741
3886
  }
3742
3887
 
3743
3888
  // src/utils/next-routes.ts
3744
- import { existsSync as existsSync14 } from "fs";
3889
+ import { existsSync as existsSync15 } from "fs";
3745
3890
  import { mkdir, writeFile } from "fs/promises";
3746
- import { join as join14 } from "path";
3891
+ import { join as join15 } from "path";
3747
3892
  var DEV_SOURCE_ROUTE_TS = `/**
3748
3893
  * Dev-only API route for fetching source files
3749
3894
  *
@@ -4199,23 +4344,23 @@ export async function GET(request: NextRequest) {
4199
4344
  }
4200
4345
  `;
4201
4346
  async function writeRouteFile(absPath, relPath, content, opts) {
4202
- if (existsSync14(absPath) && !opts.force) return;
4347
+ if (existsSync15(absPath) && !opts.force) return;
4203
4348
  await writeFile(absPath, content, "utf-8");
4204
4349
  }
4205
4350
  async function installNextUILintRoutes(opts) {
4206
- const baseRel = join14(opts.appRoot, "api", ".uilint");
4207
- const baseAbs = join14(opts.projectPath, baseRel);
4208
- await mkdir(join14(baseAbs, "source"), { recursive: true });
4351
+ const baseRel = join15(opts.appRoot, "api", ".uilint");
4352
+ const baseAbs = join15(opts.projectPath, baseRel);
4353
+ await mkdir(join15(baseAbs, "source"), { recursive: true });
4209
4354
  await writeRouteFile(
4210
- join14(baseAbs, "source", "route.ts"),
4211
- join14(baseRel, "source", "route.ts"),
4355
+ join15(baseAbs, "source", "route.ts"),
4356
+ join15(baseRel, "source", "route.ts"),
4212
4357
  DEV_SOURCE_ROUTE_TS,
4213
4358
  opts
4214
4359
  );
4215
- await mkdir(join14(baseAbs, "screenshots"), { recursive: true });
4360
+ await mkdir(join15(baseAbs, "screenshots"), { recursive: true });
4216
4361
  await writeRouteFile(
4217
- join14(baseAbs, "screenshots", "route.ts"),
4218
- join14(baseRel, "screenshots", "route.ts"),
4362
+ join15(baseAbs, "screenshots", "route.ts"),
4363
+ join15(baseRel, "screenshots", "route.ts"),
4219
4364
  SCREENSHOT_ROUTE_TS,
4220
4365
  opts
4221
4366
  );
@@ -4234,7 +4379,7 @@ async function executeAction(action, options) {
4234
4379
  wouldDo: `Create directory: ${action.path}`
4235
4380
  };
4236
4381
  }
4237
- if (!existsSync15(action.path)) {
4382
+ if (!existsSync16(action.path)) {
4238
4383
  mkdirSync3(action.path, { recursive: true });
4239
4384
  }
4240
4385
  return { action, success: true };
@@ -4247,8 +4392,8 @@ async function executeAction(action, options) {
4247
4392
  wouldDo: `Create file: ${action.path}${action.permissions ? ` (mode: ${action.permissions.toString(8)})` : ""}`
4248
4393
  };
4249
4394
  }
4250
- const dir = dirname7(action.path);
4251
- if (!existsSync15(dir)) {
4395
+ const dir = dirname9(action.path);
4396
+ if (!existsSync16(dir)) {
4252
4397
  mkdirSync3(dir, { recursive: true });
4253
4398
  }
4254
4399
  writeFileSync7(action.path, action.content, "utf-8");
@@ -4266,15 +4411,15 @@ async function executeAction(action, options) {
4266
4411
  };
4267
4412
  }
4268
4413
  let existing = {};
4269
- if (existsSync15(action.path)) {
4414
+ if (existsSync16(action.path)) {
4270
4415
  try {
4271
- existing = JSON.parse(readFileSync10(action.path, "utf-8"));
4416
+ existing = JSON.parse(readFileSync11(action.path, "utf-8"));
4272
4417
  } catch {
4273
4418
  }
4274
4419
  }
4275
4420
  const merged = deepMerge(existing, action.merge);
4276
- const dir = dirname7(action.path);
4277
- if (!existsSync15(dir)) {
4421
+ const dir = dirname9(action.path);
4422
+ if (!existsSync16(dir)) {
4278
4423
  mkdirSync3(dir, { recursive: true });
4279
4424
  }
4280
4425
  writeFileSync7(action.path, JSON.stringify(merged, null, 2), "utf-8");
@@ -4288,7 +4433,7 @@ async function executeAction(action, options) {
4288
4433
  wouldDo: `Delete file: ${action.path}`
4289
4434
  };
4290
4435
  }
4291
- if (existsSync15(action.path)) {
4436
+ if (existsSync16(action.path)) {
4292
4437
  unlinkSync(action.path);
4293
4438
  }
4294
4439
  return { action, success: true };
@@ -4301,8 +4446,8 @@ async function executeAction(action, options) {
4301
4446
  wouldDo: `Append to file: ${action.path}`
4302
4447
  };
4303
4448
  }
4304
- if (existsSync15(action.path)) {
4305
- const content = readFileSync10(action.path, "utf-8");
4449
+ if (existsSync16(action.path)) {
4450
+ const content = readFileSync11(action.path, "utf-8");
4306
4451
  if (action.ifNotContains && content.includes(action.ifNotContains)) {
4307
4452
  return { action, success: true };
4308
4453
  }
@@ -4988,7 +5133,7 @@ function displayResults(result) {
4988
5133
  if (summary.nextApp) {
4989
5134
  installedItems.push(
4990
5135
  `${pc.cyan("Next Routes")} \u2192 ${pc.dim(
4991
- join15(summary.nextApp.appRoot, "api/.uilint")
5136
+ join16(summary.nextApp.appRoot, "api/.uilint")
4992
5137
  )}`
4993
5138
  );
4994
5139
  installedItems.push(
@@ -5123,19 +5268,19 @@ async function install(options = {}, prompter = cliPrompter, executeOptions = {}
5123
5268
  }
5124
5269
 
5125
5270
  // src/commands/serve.ts
5126
- import { existsSync as existsSync17, statSync as statSync4, readdirSync as readdirSync5, readFileSync as readFileSync11 } from "fs";
5127
- import { createRequire as createRequire2 } from "module";
5128
- import { dirname as dirname9, resolve as resolve5, relative as relative3, join as join17, parse as parse2 } from "path";
5271
+ import { existsSync as existsSync18, statSync as statSync4, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "fs";
5272
+ import { createRequire as createRequire3 } from "module";
5273
+ import { dirname as dirname11, resolve as resolve5, relative as relative4, join as join18, parse as parse2 } from "path";
5129
5274
  import { WebSocketServer, WebSocket } from "ws";
5130
5275
  import { watch } from "chokidar";
5131
5276
  import {
5132
- findWorkspaceRoot as findWorkspaceRoot5,
5277
+ findWorkspaceRoot as findWorkspaceRoot6,
5133
5278
  getVisionAnalyzer as getCoreVisionAnalyzer
5134
5279
  } from "uilint-core/node";
5135
5280
 
5136
5281
  // src/utils/vision-run.ts
5137
- import { dirname as dirname8, join as join16, parse } from "path";
5138
- import { existsSync as existsSync16, statSync as statSync3, mkdirSync as mkdirSync4, writeFileSync as writeFileSync8 } from "fs";
5282
+ import { dirname as dirname10, join as join17, parse } from "path";
5283
+ import { existsSync as existsSync17, statSync as statSync3, mkdirSync as mkdirSync4, writeFileSync as writeFileSync8 } from "fs";
5139
5284
  import {
5140
5285
  ensureOllamaReady as ensureOllamaReady5,
5141
5286
  findStyleGuidePath as findStyleGuidePath4,
@@ -5149,7 +5294,7 @@ async function resolveVisionStyleGuide(args) {
5149
5294
  const startDir = args.startDir ?? projectPath;
5150
5295
  if (args.styleguide) {
5151
5296
  const styleguideArg = resolvePathSpecifier(args.styleguide, projectPath);
5152
- if (existsSync16(styleguideArg)) {
5297
+ if (existsSync17(styleguideArg)) {
5153
5298
  const stat = statSync3(styleguideArg);
5154
5299
  if (stat.isFile()) {
5155
5300
  return {
@@ -5193,7 +5338,7 @@ function writeVisionDebugDump(params) {
5193
5338
  );
5194
5339
  const safeStamp = params.now.toISOString().replace(/[:.]/g, "-");
5195
5340
  const dumpFile = resolvedDirOrFile.endsWith(".json") || resolvedDirOrFile.endsWith(".jsonl") ? resolvedDirOrFile : `${resolvedDirOrFile}/vision-debug-${safeStamp}.json`;
5196
- mkdirSync4(dirname8(dumpFile), { recursive: true });
5341
+ mkdirSync4(dirname10(dumpFile), { recursive: true });
5197
5342
  writeFileSync8(
5198
5343
  dumpFile,
5199
5344
  JSON.stringify(
@@ -5282,7 +5427,7 @@ async function runVisionAnalysis(args) {
5282
5427
  }
5283
5428
  function writeVisionMarkdownReport(args) {
5284
5429
  const p2 = parse(args.imagePath);
5285
- const outPath = args.outPath ?? join16(p2.dir, `${p2.name || p2.base}.vision.md`);
5430
+ const outPath = args.outPath ?? join17(p2.dir, `${p2.name || p2.base}.vision.md`);
5286
5431
  const lines = [];
5287
5432
  lines.push(`# UILint Vision Report`);
5288
5433
  lines.push(``);
@@ -5318,7 +5463,7 @@ function writeVisionMarkdownReport(args) {
5318
5463
  lines.push("```");
5319
5464
  lines.push(``);
5320
5465
  const content = lines.join("\n");
5321
- mkdirSync4(dirname8(outPath), { recursive: true });
5466
+ mkdirSync4(dirname10(outPath), { recursive: true });
5322
5467
  writeFileSync8(outPath, content, "utf-8");
5323
5468
  return { outPath, content };
5324
5469
  }
@@ -5354,7 +5499,7 @@ var resolvedPathCache = /* @__PURE__ */ new Map();
5354
5499
  var subscriptions = /* @__PURE__ */ new Map();
5355
5500
  var fileWatcher = null;
5356
5501
  var connectedClients = 0;
5357
- var localRequire = createRequire2(import.meta.url);
5502
+ var localRequire = createRequire3(import.meta.url);
5358
5503
  function buildLineStarts(code) {
5359
5504
  const starts = [0];
5360
5505
  for (let i = 0; i < code.length; i++) {
@@ -5432,10 +5577,10 @@ function findESLintCwd(startDir) {
5432
5577
  let dir = startDir;
5433
5578
  for (let i = 0; i < 30; i++) {
5434
5579
  for (const cfg of ESLINT_CONFIG_FILES2) {
5435
- if (existsSync17(join17(dir, cfg))) return dir;
5580
+ if (existsSync18(join18(dir, cfg))) return dir;
5436
5581
  }
5437
- if (existsSync17(join17(dir, "package.json"))) return dir;
5438
- const parent = dirname9(dir);
5582
+ if (existsSync18(join18(dir, "package.json"))) return dir;
5583
+ const parent = dirname11(dir);
5439
5584
  if (parent === dir) break;
5440
5585
  dir = parent;
5441
5586
  }
@@ -5448,7 +5593,7 @@ function normalizeDataLocFilePath(absoluteFilePath, projectCwd) {
5448
5593
  const abs = normalizePathSlashes(resolve5(absoluteFilePath));
5449
5594
  const cwd = normalizePathSlashes(resolve5(projectCwd));
5450
5595
  if (abs === cwd || abs.startsWith(cwd + "/")) {
5451
- return normalizePathSlashes(relative3(cwd, abs));
5596
+ return normalizePathSlashes(relative4(cwd, abs));
5452
5597
  }
5453
5598
  return abs;
5454
5599
  }
@@ -5460,25 +5605,25 @@ function resolveRequestedFilePath(filePath) {
5460
5605
  if (cached) return cached;
5461
5606
  const cwd = process.cwd();
5462
5607
  const fromCwd = resolve5(cwd, filePath);
5463
- if (existsSync17(fromCwd)) {
5608
+ if (existsSync18(fromCwd)) {
5464
5609
  resolvedPathCache.set(filePath, fromCwd);
5465
5610
  return fromCwd;
5466
5611
  }
5467
- const wsRoot = findWorkspaceRoot5(cwd);
5612
+ const wsRoot = findWorkspaceRoot6(cwd);
5468
5613
  const fromWs = resolve5(wsRoot, filePath);
5469
- if (existsSync17(fromWs)) {
5614
+ if (existsSync18(fromWs)) {
5470
5615
  resolvedPathCache.set(filePath, fromWs);
5471
5616
  return fromWs;
5472
5617
  }
5473
5618
  for (const top of ["apps", "packages"]) {
5474
- const base = join17(wsRoot, top);
5475
- if (!existsSync17(base)) continue;
5619
+ const base = join18(wsRoot, top);
5620
+ if (!existsSync18(base)) continue;
5476
5621
  try {
5477
5622
  const entries = readdirSync5(base, { withFileTypes: true });
5478
5623
  for (const ent of entries) {
5479
5624
  if (!ent.isDirectory()) continue;
5480
5625
  const p2 = resolve5(base, ent.name, filePath);
5481
- if (existsSync17(p2)) {
5626
+ if (existsSync18(p2)) {
5482
5627
  resolvedPathCache.set(filePath, p2);
5483
5628
  return p2;
5484
5629
  }
@@ -5493,7 +5638,7 @@ async function getESLintForProject(projectCwd) {
5493
5638
  const cached = eslintInstances.get(projectCwd);
5494
5639
  if (cached) return cached;
5495
5640
  try {
5496
- const req = createRequire2(join17(projectCwd, "package.json"));
5641
+ const req = createRequire3(join18(projectCwd, "package.json"));
5497
5642
  const mod = req("eslint");
5498
5643
  const ESLintCtor = mod?.ESLint ?? mod?.default?.ESLint ?? mod?.default ?? mod;
5499
5644
  if (!ESLintCtor) return null;
@@ -5506,7 +5651,7 @@ async function getESLintForProject(projectCwd) {
5506
5651
  }
5507
5652
  async function lintFile(filePath, onProgress) {
5508
5653
  const absolutePath = resolveRequestedFilePath(filePath);
5509
- if (!existsSync17(absolutePath)) {
5654
+ if (!existsSync18(absolutePath)) {
5510
5655
  onProgress(`File not found: ${pc.dim(absolutePath)}`);
5511
5656
  return [];
5512
5657
  }
@@ -5522,7 +5667,7 @@ async function lintFile(filePath, onProgress) {
5522
5667
  onProgress("Cache hit (unchanged)");
5523
5668
  return cached.issues;
5524
5669
  }
5525
- const fileDir = dirname9(absolutePath);
5670
+ const fileDir = dirname11(absolutePath);
5526
5671
  const projectCwd = findESLintCwd(fileDir);
5527
5672
  onProgress(`Resolving ESLint project... ${pc.dim(projectCwd)}`);
5528
5673
  const eslint = await getESLintForProject(projectCwd);
@@ -5545,7 +5690,7 @@ async function lintFile(filePath, onProgress) {
5545
5690
  let codeLength = 0;
5546
5691
  try {
5547
5692
  onProgress("Building JSX map...");
5548
- const code = readFileSync11(absolutePath, "utf-8");
5693
+ const code = readFileSync12(absolutePath, "utf-8");
5549
5694
  codeLength = code.length;
5550
5695
  lineStarts = buildLineStarts(code);
5551
5696
  spans = buildJsxElementSpans(code, dataLocFile);
@@ -5627,9 +5772,9 @@ async function handleMessage(ws, data) {
5627
5772
  });
5628
5773
  const startedAt = Date.now();
5629
5774
  const resolved = resolveRequestedFilePath(filePath);
5630
- if (!existsSync17(resolved)) {
5775
+ if (!existsSync18(resolved)) {
5631
5776
  const cwd = process.cwd();
5632
- const wsRoot = findWorkspaceRoot5(cwd);
5777
+ const wsRoot = findWorkspaceRoot6(cwd);
5633
5778
  logWarning(
5634
5779
  [
5635
5780
  `${pc.dim("[ws]")} File not found for request`,
@@ -5789,14 +5934,14 @@ async function handleMessage(ws, data) {
5789
5934
  )}`
5790
5935
  );
5791
5936
  } else {
5792
- const screenshotsDir = join17(
5937
+ const screenshotsDir = join18(
5793
5938
  serverAppRootForVision,
5794
5939
  ".uilint",
5795
5940
  "screenshots"
5796
5941
  );
5797
- const imagePath = join17(screenshotsDir, screenshotFile);
5942
+ const imagePath = join18(screenshotsDir, screenshotFile);
5798
5943
  try {
5799
- if (!existsSync17(imagePath)) {
5944
+ if (!existsSync18(imagePath)) {
5800
5945
  logWarning(
5801
5946
  `Skipping vision report write: screenshot file not found ${pc.dim(
5802
5947
  imagePath
@@ -5904,7 +6049,7 @@ function handleFileChange(filePath) {
5904
6049
  async function serve(options) {
5905
6050
  const port = options.port || 9234;
5906
6051
  const cwd = process.cwd();
5907
- const wsRoot = findWorkspaceRoot5(cwd);
6052
+ const wsRoot = findWorkspaceRoot6(cwd);
5908
6053
  const appRoot = pickAppRoot({ cwd, workspaceRoot: wsRoot });
5909
6054
  serverAppRootForVision = appRoot;
5910
6055
  logInfo(`Workspace root: ${pc.dim(wsRoot)}`);
@@ -5957,10 +6102,10 @@ async function serve(options) {
5957
6102
  }
5958
6103
 
5959
6104
  // src/commands/vision.ts
5960
- import { dirname as dirname10, resolve as resolve6, join as join18 } from "path";
6105
+ import { dirname as dirname12, resolve as resolve6, join as join19 } from "path";
5961
6106
  import {
5962
- existsSync as existsSync18,
5963
- readFileSync as readFileSync12,
6107
+ existsSync as existsSync19,
6108
+ readFileSync as readFileSync13,
5964
6109
  readdirSync as readdirSync6
5965
6110
  } from "fs";
5966
6111
  import {
@@ -6006,17 +6151,17 @@ function debugLog3(enabled, message, obj) {
6006
6151
  function findScreenshotsDirUpwards(startDir) {
6007
6152
  let dir = startDir;
6008
6153
  for (let i = 0; i < 20; i++) {
6009
- const candidate = join18(dir, ".uilint", "screenshots");
6010
- if (existsSync18(candidate)) return candidate;
6011
- const parent = dirname10(dir);
6154
+ const candidate = join19(dir, ".uilint", "screenshots");
6155
+ if (existsSync19(candidate)) return candidate;
6156
+ const parent = dirname12(dir);
6012
6157
  if (parent === dir) break;
6013
6158
  dir = parent;
6014
6159
  }
6015
6160
  return null;
6016
6161
  }
6017
6162
  function listScreenshotSidecars(dirPath) {
6018
- if (!existsSync18(dirPath)) return [];
6019
- const entries = readdirSync6(dirPath).filter((f) => f.endsWith(".json")).map((f) => join18(dirPath, f));
6163
+ if (!existsSync19(dirPath)) return [];
6164
+ const entries = readdirSync6(dirPath).filter((f) => f.endsWith(".json")).map((f) => join19(dirPath, f));
6020
6165
  const out = [];
6021
6166
  for (const p2 of entries) {
6022
6167
  try {
@@ -6045,11 +6190,11 @@ function listScreenshotSidecars(dirPath) {
6045
6190
  return out;
6046
6191
  }
6047
6192
  function readImageAsBase64(imagePath) {
6048
- const bytes = readFileSync12(imagePath);
6193
+ const bytes = readFileSync13(imagePath);
6049
6194
  return { base64: bytes.toString("base64"), sizeBytes: bytes.byteLength };
6050
6195
  }
6051
6196
  function loadJsonFile(filePath) {
6052
- const raw = readFileSync12(filePath, "utf-8");
6197
+ const raw = readFileSync13(filePath, "utf-8");
6053
6198
  return JSON.parse(raw);
6054
6199
  }
6055
6200
  function formatIssuesText(issues) {
@@ -6123,13 +6268,13 @@ async function vision(options) {
6123
6268
  await flushLangfuse();
6124
6269
  process.exit(1);
6125
6270
  }
6126
- if (imagePath && !existsSync18(imagePath)) {
6271
+ if (imagePath && !existsSync19(imagePath)) {
6127
6272
  throw new Error(`Image not found: ${imagePath}`);
6128
6273
  }
6129
- if (sidecarPath && !existsSync18(sidecarPath)) {
6274
+ if (sidecarPath && !existsSync19(sidecarPath)) {
6130
6275
  throw new Error(`Sidecar not found: ${sidecarPath}`);
6131
6276
  }
6132
- if (manifestFilePath && !existsSync18(manifestFilePath)) {
6277
+ if (manifestFilePath && !existsSync19(manifestFilePath)) {
6133
6278
  throw new Error(`Manifest file not found: ${manifestFilePath}`);
6134
6279
  }
6135
6280
  const sidecar = sidecarPath ? loadJsonFile(sidecarPath) : null;
@@ -6154,7 +6299,7 @@ async function vision(options) {
6154
6299
  const resolved = await resolveVisionStyleGuide({
6155
6300
  projectPath,
6156
6301
  styleguide: options.styleguide,
6157
- startDir: startPath ? dirname10(startPath) : projectPath
6302
+ startDir: startPath ? dirname12(startPath) : projectPath
6158
6303
  });
6159
6304
  styleGuide = resolved.styleGuide;
6160
6305
  styleguideLocation = resolved.styleguideLocation;
@@ -6203,7 +6348,7 @@ async function vision(options) {
6203
6348
  const resolvedImagePath = imagePath || (() => {
6204
6349
  const screenshotFile = typeof sidecar?.screenshotFile === "string" ? sidecar.screenshotFile : typeof sidecar?.filename === "string" ? sidecar.filename : void 0;
6205
6350
  if (!screenshotFile) return null;
6206
- const baseDir = sidecarPath ? dirname10(sidecarPath) : projectPath;
6351
+ const baseDir = sidecarPath ? dirname12(sidecarPath) : projectPath;
6207
6352
  const abs = resolve6(baseDir, screenshotFile);
6208
6353
  return abs;
6209
6354
  })();
@@ -6212,7 +6357,7 @@ async function vision(options) {
6212
6357
  "No image path could be resolved. Provide --image or a sidecar with `screenshotFile`/`filename`."
6213
6358
  );
6214
6359
  }
6215
- if (!existsSync18(resolvedImagePath)) {
6360
+ if (!existsSync19(resolvedImagePath)) {
6216
6361
  throw new Error(`Image not found: ${resolvedImagePath}`);
6217
6362
  }
6218
6363
  const { base64, sizeBytes } = readImageAsBase64(resolvedImagePath);
@@ -6440,8 +6585,8 @@ async function vision(options) {
6440
6585
  }
6441
6586
 
6442
6587
  // src/commands/session.ts
6443
- import { existsSync as existsSync19, readFileSync as readFileSync13, writeFileSync as writeFileSync10, unlinkSync as unlinkSync2 } from "fs";
6444
- import { basename, dirname as dirname11, resolve as resolve7 } from "path";
6588
+ import { existsSync as existsSync20, readFileSync as readFileSync14, writeFileSync as writeFileSync10, unlinkSync as unlinkSync2 } from "fs";
6589
+ import { basename, dirname as dirname13, resolve as resolve7 } from "path";
6445
6590
  import { createStyleSummary as createStyleSummary3 } from "uilint-core";
6446
6591
  import {
6447
6592
  ensureOllamaReady as ensureOllamaReady7,
@@ -6452,11 +6597,11 @@ import {
6452
6597
  var SESSION_FILE = "/tmp/uilint-session.json";
6453
6598
  var UI_FILE_EXTENSIONS = [".tsx", ".jsx", ".css", ".scss", ".module.css"];
6454
6599
  function readSession() {
6455
- if (!existsSync19(SESSION_FILE)) {
6600
+ if (!existsSync20(SESSION_FILE)) {
6456
6601
  return { files: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
6457
6602
  }
6458
6603
  try {
6459
- const content = readFileSync13(SESSION_FILE, "utf-8");
6604
+ const content = readFileSync14(SESSION_FILE, "utf-8");
6460
6605
  return JSON.parse(content);
6461
6606
  } catch {
6462
6607
  return { files: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
@@ -6474,7 +6619,7 @@ function isScannableMarkupFile(filePath) {
6474
6619
  );
6475
6620
  }
6476
6621
  async function sessionClear() {
6477
- if (existsSync19(SESSION_FILE)) {
6622
+ if (existsSync20(SESSION_FILE)) {
6478
6623
  unlinkSync2(SESSION_FILE);
6479
6624
  }
6480
6625
  console.log(JSON.stringify({ cleared: true }));
@@ -6545,13 +6690,13 @@ async function sessionScan(options = {}) {
6545
6690
  const client = await createLLMClient({});
6546
6691
  const results = [];
6547
6692
  for (const filePath of session.files) {
6548
- if (!existsSync19(filePath)) continue;
6693
+ if (!existsSync20(filePath)) continue;
6549
6694
  if (!isScannableMarkupFile(filePath)) continue;
6550
6695
  try {
6551
6696
  const absolutePath = resolve7(process.cwd(), filePath);
6552
- const htmlLike = readFileSync13(filePath, "utf-8");
6697
+ const htmlLike = readFileSync14(filePath, "utf-8");
6553
6698
  const snapshot = parseCLIInput2(htmlLike);
6554
- const tailwindSearchDir = dirname11(absolutePath);
6699
+ const tailwindSearchDir = dirname13(absolutePath);
6555
6700
  const tailwindTheme = readTailwindThemeTokens3(tailwindSearchDir);
6556
6701
  const styleSummary = createStyleSummary3(snapshot.styles, {
6557
6702
  html: snapshot.html,
@@ -6604,7 +6749,7 @@ async function sessionScan(options = {}) {
6604
6749
  };
6605
6750
  console.log(JSON.stringify(result));
6606
6751
  }
6607
- if (existsSync19(SESSION_FILE)) {
6752
+ if (existsSync20(SESSION_FILE)) {
6608
6753
  unlinkSync2(SESSION_FILE);
6609
6754
  }
6610
6755
  await flushLangfuse();
@@ -6615,9 +6760,9 @@ async function sessionList() {
6615
6760
  }
6616
6761
 
6617
6762
  // src/index.ts
6618
- import { readFileSync as readFileSync14 } from "fs";
6619
- import { dirname as dirname12, join as join19 } from "path";
6620
- import { fileURLToPath as fileURLToPath3 } from "url";
6763
+ import { readFileSync as readFileSync15 } from "fs";
6764
+ import { dirname as dirname14, join as join20 } from "path";
6765
+ import { fileURLToPath as fileURLToPath4 } from "url";
6621
6766
  function assertNodeVersion(minMajor) {
6622
6767
  const ver = process.versions.node || "";
6623
6768
  const majorStr = ver.split(".")[0] || "";
@@ -6633,9 +6778,9 @@ assertNodeVersion(20);
6633
6778
  var program = new Command();
6634
6779
  function getCLIVersion2() {
6635
6780
  try {
6636
- const __dirname2 = dirname12(fileURLToPath3(import.meta.url));
6637
- const pkgPath = join19(__dirname2, "..", "package.json");
6638
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
6781
+ const __dirname3 = dirname14(fileURLToPath4(import.meta.url));
6782
+ const pkgPath = join20(__dirname3, "..", "package.json");
6783
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
6639
6784
  return pkg.version || "0.0.0";
6640
6785
  } catch {
6641
6786
  return "0.0.0";