uilint 0.2.89 → 0.2.90

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.
@@ -106,6 +106,11 @@ function createPlan(state, choices, options = {}) {
106
106
  type: "inject_next_config",
107
107
  projectPath
108
108
  });
109
+ actions.push({
110
+ type: "inject_tsconfig",
111
+ projectPath,
112
+ addDevtoolsTypes: true
113
+ });
109
114
  }
110
115
  if (items.includes("vite") && choices.vite) {
111
116
  const { projectPath, detection } = choices.vite;
@@ -136,6 +141,11 @@ function createPlan(state, choices, options = {}) {
136
141
  type: "inject_vite_config",
137
142
  projectPath
138
143
  });
144
+ actions.push({
145
+ type: "inject_tsconfig",
146
+ projectPath,
147
+ addDevtoolsTypes: true
148
+ });
139
149
  }
140
150
  if (items.includes("eslint") && choices.eslint) {
141
151
  const { packagePaths, selectedRules } = choices.eslint;
@@ -266,4 +276,4 @@ export {
266
276
  createPlan,
267
277
  getMissingRules
268
278
  };
269
- //# sourceMappingURL=chunk-OL3HPXVB.js.map
279
+ //# sourceMappingURL=chunk-DZA4FNII.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/init/plan.ts"],"sourcesContent":["/**\n * Plan phase - pure function generating InstallPlan from state + choices\n *\n * This function has NO I/O whatsoever. It takes the analyzed ProjectState,\n * user choices, and options, then returns an InstallPlan describing exactly\n * what actions to take.\n */\n\nimport { join } from \"path\";\nimport type { RuleMetadata } from \"uilint-eslint\";\nimport type {\n ProjectState,\n UserChoices,\n InstallPlan,\n InstallAction,\n DependencyInstall,\n PlanOptions,\n} from \"./types.js\";\nimport { GENSTYLEGUIDE_COMMAND_MD } from \"./constants.js\";\nimport { toInstallSpecifier } from \"./versioning.js\";\nimport { loadSkill } from \"../../utils/skill-loader.js\";\nimport { loadSelectedRules } from \"../../utils/rule-loader.js\";\nimport { detectPackageManager } from \"../../utils/package-manager.js\";\n\n/**\n * Create the install plan from project state and user choices\n *\n * @param state - The analyzed project state\n * @param choices - User's installation choices\n * @param options - Planning options (force, etc.)\n * @returns InstallPlan with all actions and dependencies\n */\nexport function createPlan(\n state: ProjectState,\n choices: UserChoices,\n options: PlanOptions = {}\n): InstallPlan {\n const actions: InstallAction[] = [];\n const dependencies: DependencyInstall[] = [];\n\n const { force = false } = options;\n const { items } = choices;\n\n // Ensure .cursor directory exists if needed\n const needsCursorDir =\n items.includes(\"genstyleguide\") || items.includes(\"skill\");\n\n if (needsCursorDir && !state.cursorDir.exists) {\n actions.push({\n type: \"create_directory\",\n path: state.cursorDir.path,\n });\n }\n\n // =========================================================================\n // Genstyleguide Command\n // =========================================================================\n if (items.includes(\"genstyleguide\")) {\n const commandsDir = join(state.cursorDir.path, \"commands\");\n\n actions.push({\n type: \"create_directory\",\n path: commandsDir,\n });\n\n actions.push({\n type: \"create_file\",\n path: join(commandsDir, \"genstyleguide.md\"),\n content: GENSTYLEGUIDE_COMMAND_MD,\n });\n }\n\n // =========================================================================\n // Agent Skill Installation\n // =========================================================================\n if (items.includes(\"skill\")) {\n const skillsDir = join(state.cursorDir.path, \"skills\");\n\n // Create skills directory\n actions.push({\n type: \"create_directory\",\n path: skillsDir,\n });\n\n // Load and install the ui-consistency-enforcer skill\n try {\n const skill = loadSkill(\"ui-consistency-enforcer\");\n const skillDir = join(skillsDir, skill.name);\n\n // Create skill directory\n actions.push({\n type: \"create_directory\",\n path: skillDir,\n });\n\n // Create all skill files\n for (const file of skill.files) {\n const filePath = join(skillDir, file.relativePath);\n\n // Ensure subdirectories exist (e.g., references/)\n const fileDir = join(\n skillDir,\n file.relativePath.split(\"/\").slice(0, -1).join(\"/\")\n );\n if (fileDir !== skillDir && file.relativePath.includes(\"/\")) {\n actions.push({\n type: \"create_directory\",\n path: fileDir,\n });\n }\n\n actions.push({\n type: \"create_file\",\n path: filePath,\n content: file.content,\n });\n }\n } catch {\n // Skill not found - skip silently (shouldn't happen in normal install)\n }\n }\n\n // =========================================================================\n // Next.js Overlay Installation\n // =========================================================================\n if (items.includes(\"next\") && choices.next) {\n const { projectPath, detection, targetFile, createProviders } =\n choices.next;\n\n // Install Next.js routes\n actions.push({\n type: \"install_next_routes\",\n projectPath,\n appRoot: detection.appRoot,\n });\n\n // Install React overlay dependencies using the package manager for this specific target\n dependencies.push({\n packagePath: projectPath,\n packageManager: detectPackageManager(projectPath),\n packages: [\n toInstallSpecifier(\"uilint-react\", {\n preferWorkspaceProtocol: state.packageManager === \"pnpm\",\n workspaceRoot: state.workspaceRoot,\n targetProjectPath: projectPath,\n }),\n toInstallSpecifier(\"uilint-core\", {\n preferWorkspaceProtocol: state.packageManager === \"pnpm\",\n workspaceRoot: state.workspaceRoot,\n targetProjectPath: projectPath,\n }),\n \"jsx-loc-plugin\",\n ],\n });\n\n // Inject <uilint-devtools /> web component into React\n // Use targetFile or createProviders if specified by the user\n actions.push({\n type: \"inject_react\",\n projectPath,\n appRoot: detection.appRoot,\n targetFile,\n createProviders,\n });\n\n // Inject jsx-loc-plugin into next.config\n actions.push({\n type: \"inject_next_config\",\n projectPath,\n });\n\n // Add uilint-react/devtools to tsconfig.json types for TypeScript support\n actions.push({\n type: \"inject_tsconfig\",\n projectPath,\n addDevtoolsTypes: true,\n });\n }\n\n // =========================================================================\n // Vite Overlay Installation\n // =========================================================================\n if (items.includes(\"vite\") && choices.vite) {\n const { projectPath, detection } = choices.vite;\n\n // Install React overlay dependencies using the package manager for this specific target\n dependencies.push({\n packagePath: projectPath,\n packageManager: detectPackageManager(projectPath),\n packages: [\n toInstallSpecifier(\"uilint-react\", {\n preferWorkspaceProtocol: state.packageManager === \"pnpm\",\n workspaceRoot: state.workspaceRoot,\n targetProjectPath: projectPath,\n }),\n toInstallSpecifier(\"uilint-core\", {\n preferWorkspaceProtocol: state.packageManager === \"pnpm\",\n workspaceRoot: state.workspaceRoot,\n targetProjectPath: projectPath,\n }),\n \"jsx-loc-plugin\",\n ],\n });\n\n // Inject <uilint-devtools /> web component into React entry\n actions.push({\n type: \"inject_react\",\n projectPath,\n appRoot: detection.entryRoot,\n mode: \"vite\",\n });\n\n // Inject jsx-loc-plugin into vite.config\n actions.push({\n type: \"inject_vite_config\",\n projectPath,\n });\n\n // Add uilint-react/devtools to tsconfig.json types for TypeScript support\n actions.push({\n type: \"inject_tsconfig\",\n projectPath,\n addDevtoolsTypes: true,\n });\n }\n\n // =========================================================================\n // ESLint Plugin Installation\n // =========================================================================\n if (items.includes(\"eslint\") && choices.eslint) {\n const { packagePaths, selectedRules } = choices.eslint;\n\n for (const pkgPath of packagePaths) {\n const pkgInfo = state.packages.find((p) => p.path === pkgPath);\n\n // Create .uilint/rules directory alongside the target app (not at workspace root)\n const rulesDir = join(pkgPath, \".uilint\", \"rules\");\n actions.push({\n type: \"create_directory\",\n path: rulesDir,\n });\n\n // Load and copy rule files into this target package\n // Use TypeScript rule files if the ESLint config is TypeScript (.ts)\n // This ensures the imports match the actual rule files being copied\n const isTypeScriptConfig =\n pkgInfo?.eslintConfigPath?.endsWith(\".ts\") ?? false;\n const ruleFiles = loadSelectedRules(\n selectedRules.map((r) => r.id),\n {\n typescript: isTypeScriptConfig,\n }\n );\n for (const ruleFile of ruleFiles) {\n // For directory-based rules, create the directory structure first\n if (ruleFile.additionalFiles && ruleFile.additionalFiles.length > 0) {\n // Create rule directory (e.g., .uilint/rules/no-mixed-component-libraries/)\n const ruleDir = join(rulesDir, ruleFile.ruleId);\n actions.push({\n type: \"create_directory\",\n path: ruleDir,\n });\n\n // Create lib/ subdirectory if any files are in lib/\n const hasLibFiles = ruleFile.additionalFiles.some((f) =>\n f.relativePath.includes(\"/lib/\")\n );\n if (hasLibFiles) {\n actions.push({\n type: \"create_directory\",\n path: join(ruleDir, \"lib\"),\n });\n }\n }\n\n // Copy implementation file\n actions.push({\n type: \"create_file\",\n path: join(rulesDir, ruleFile.implementation.relativePath),\n content: ruleFile.implementation.content,\n });\n\n // Copy additional files for directory-based rules\n if (ruleFile.additionalFiles) {\n for (const additionalFile of ruleFile.additionalFiles) {\n actions.push({\n type: \"create_file\",\n path: join(rulesDir, additionalFile.relativePath),\n content: additionalFile.content,\n });\n }\n }\n\n // Copy test file if it exists (only for TypeScript configs)\n if (ruleFile.test && isTypeScriptConfig) {\n actions.push({\n type: \"create_file\",\n path: join(rulesDir, ruleFile.test.relativePath),\n content: ruleFile.test.content,\n });\n }\n }\n\n // Install dependencies using the package manager for this specific target\n const packagesToInstall = [\n toInstallSpecifier(\"uilint-eslint\", {\n preferWorkspaceProtocol: state.packageManager === \"pnpm\",\n workspaceRoot: state.workspaceRoot,\n targetProjectPath: pkgPath,\n }),\n \"typescript-eslint\",\n ];\n\n // If require-test-coverage rule is selected, add coverage package and config\n const hasCoverageRule = selectedRules.some(\n (r) => r.id === \"require-test-coverage\"\n );\n if (hasCoverageRule) {\n packagesToInstall.push(\"@vitest/coverage-v8\");\n\n // Add action to inject coverage config into vitest.config.ts\n actions.push({\n type: \"inject_vitest_coverage\",\n projectPath: pkgPath,\n });\n }\n\n // Collect npm dependencies declared by selected rules\n for (const rule of selectedRules) {\n if (rule.npmDependencies) {\n for (const dep of rule.npmDependencies) {\n if (!packagesToInstall.includes(dep)) {\n packagesToInstall.push(dep);\n }\n }\n }\n }\n\n dependencies.push({\n packagePath: pkgPath,\n packageManager: detectPackageManager(pkgPath),\n packages: packagesToInstall,\n });\n\n // Inject ESLint rules (will reference local .uilint/rules/ files)\n if (pkgInfo?.eslintConfigPath) {\n actions.push({\n type: \"inject_eslint\",\n packagePath: pkgPath,\n configPath: pkgInfo.eslintConfigPath,\n rules: selectedRules,\n hasExistingRules: pkgInfo.hasUilintRules,\n });\n }\n\n // Add .uilint to tsconfig.json exclude to prevent build errors\n // The rule files are loaded by ESLint at runtime, not compiled with the app\n actions.push({\n type: \"inject_tsconfig\",\n projectPath: pkgPath,\n });\n\n // Update manifest with installed rule versions\n const ruleVersions: Record<string, string> = {};\n for (const rule of selectedRules) {\n // Use version from RuleMeta, default to \"1.0.0\" if not specified\n ruleVersions[rule.id] = rule.version ?? \"1.0.0\";\n }\n actions.push({\n type: \"update_manifest\",\n projectPath: pkgPath,\n rules: ruleVersions,\n });\n }\n\n // Add .uilint/.cache to .gitignore at workspace root\n const gitignorePath = join(state.workspaceRoot, \".gitignore\");\n actions.push({\n type: \"append_to_file\",\n path: gitignorePath,\n content: \"\\n# UILint cache\\n.uilint/.cache\\n\",\n ifNotContains: \".uilint/.cache\",\n });\n }\n\n return { actions, dependencies };\n}\n\n/**\n * Get the list of rules that are missing from a package's ESLint config\n */\nexport function getMissingRules(\n configuredRuleIds: string[],\n selectedRules: RuleMetadata[]\n): RuleMetadata[] {\n const configuredSet = new Set(configuredRuleIds);\n return selectedRules.filter((rule) => !configuredSet.has(rule.id));\n}\n"],"mappings":"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","names":[]}
@@ -1996,7 +1996,9 @@ import { findWorkspaceRoot as findWorkspaceRoot2 } from "uilint-core/node";
1996
1996
  // src/utils/tsconfig-inject.ts
1997
1997
  import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
1998
1998
  import { join as join9 } from "path";
1999
- function injectTsconfigExclusion(projectPath) {
1999
+ var DEVTOOLS_TYPE = "uilint-react/devtools";
2000
+ function injectTsconfigExclusion(projectPath, options = {}) {
2001
+ const { addDevtoolsTypes = false } = options;
2000
2002
  const tsconfigPath = join9(projectPath, "tsconfig.json");
2001
2003
  if (!existsSync9(tsconfigPath)) {
2002
2004
  return { modified: false };
@@ -2004,12 +2006,33 @@ function injectTsconfigExclusion(projectPath) {
2004
2006
  try {
2005
2007
  const content = readFileSync7(tsconfigPath, "utf-8");
2006
2008
  const tsconfig = JSON.parse(content);
2009
+ let modified = false;
2007
2010
  const exclude = tsconfig.exclude ?? [];
2008
- if (exclude.includes(".uilint")) {
2011
+ if (!exclude.includes(".uilint")) {
2012
+ tsconfig.exclude = [...exclude, ".uilint"];
2013
+ modified = true;
2014
+ }
2015
+ if (addDevtoolsTypes) {
2016
+ if (!tsconfig.compilerOptions) {
2017
+ tsconfig.compilerOptions = {};
2018
+ }
2019
+ const types = tsconfig.compilerOptions.types;
2020
+ if (types === void 0) {
2021
+ tsconfig.compilerOptions.types = [DEVTOOLS_TYPE];
2022
+ modified = true;
2023
+ } else if (Array.isArray(types) && !types.includes(DEVTOOLS_TYPE)) {
2024
+ tsconfig.compilerOptions.types = [...types, DEVTOOLS_TYPE];
2025
+ modified = true;
2026
+ }
2027
+ }
2028
+ if (!modified) {
2009
2029
  return { modified: false, tsconfigPath };
2010
2030
  }
2011
- tsconfig.exclude = [...exclude, ".uilint"];
2012
- writeFileSync4(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n", "utf-8");
2031
+ writeFileSync4(
2032
+ tsconfigPath,
2033
+ JSON.stringify(tsconfig, null, 2) + "\n",
2034
+ "utf-8"
2035
+ );
2013
2036
  return { modified: true, tsconfigPath };
2014
2037
  } catch (err) {
2015
2038
  return {
@@ -2269,13 +2292,20 @@ async function executeInjectVitestCoverage(action, options) {
2269
2292
  async function executeInjectTsconfig(action, options) {
2270
2293
  const { dryRun = false } = options;
2271
2294
  if (dryRun) {
2295
+ const changes = [];
2296
+ changes.push("Add .uilint to tsconfig.json exclude");
2297
+ if (action.addDevtoolsTypes) {
2298
+ changes.push("Add uilint-react/devtools to compilerOptions.types");
2299
+ }
2272
2300
  return {
2273
2301
  action,
2274
2302
  success: true,
2275
- wouldDo: `Add .uilint to tsconfig.json exclude: ${action.projectPath}`
2303
+ wouldDo: `${changes.join(", ")}: ${action.projectPath}`
2276
2304
  };
2277
2305
  }
2278
- const result = injectTsconfigExclusion(action.projectPath);
2306
+ const result = injectTsconfigExclusion(action.projectPath, {
2307
+ addDevtoolsTypes: action.addDevtoolsTypes
2308
+ });
2279
2309
  return {
2280
2310
  action,
2281
2311
  success: true,
@@ -4045,4 +4075,4 @@ export {
4045
4075
  analyze,
4046
4076
  execute
4047
4077
  };
4048
- //# sourceMappingURL=chunk-KCDJL7K7.js.map
4078
+ //# sourceMappingURL=chunk-GUL4IJOO.js.map