@getcoherent/cli 0.6.46 → 0.6.48

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.
@@ -0,0 +1,50 @@
1
+ // src/commands/fix-validation.ts
2
+ import { createRequire } from "module";
3
+ import { existsSync, readFileSync, writeFileSync } from "fs";
4
+ import { join } from "path";
5
+ var cachedTs = null;
6
+ var cachedProjectRoot = null;
7
+ function isValidTsx(code, projectRoot, ext = ".tsx") {
8
+ if (ext !== ".tsx" && ext !== ".ts") return true;
9
+ const pkgJson = join(projectRoot, "package.json");
10
+ if (!existsSync(pkgJson)) return true;
11
+ try {
12
+ if (!cachedTs || cachedProjectRoot !== projectRoot) {
13
+ const req = createRequire(pkgJson);
14
+ cachedTs = req("typescript");
15
+ cachedProjectRoot = projectRoot;
16
+ }
17
+ const sf = cachedTs.createSourceFile(
18
+ "check.tsx",
19
+ code,
20
+ cachedTs.ScriptTarget.Latest,
21
+ false,
22
+ cachedTs.ScriptKind.TSX
23
+ );
24
+ const diagnostics = sf.parseDiagnostics;
25
+ return !diagnostics || diagnostics.length === 0;
26
+ } catch {
27
+ return true;
28
+ }
29
+ }
30
+ function safeWrite(filePath, newContent, projectRoot, backups) {
31
+ if (!backups.has(filePath)) {
32
+ try {
33
+ backups.set(filePath, readFileSync(filePath, "utf-8"));
34
+ } catch {
35
+ }
36
+ }
37
+ const ext = filePath.slice(filePath.lastIndexOf("."));
38
+ writeFileSync(filePath, newContent, "utf-8");
39
+ if (!isValidTsx(newContent, projectRoot, ext)) {
40
+ const original = backups.get(filePath);
41
+ if (original) writeFileSync(filePath, original, "utf-8");
42
+ return { ok: false };
43
+ }
44
+ return { ok: true };
45
+ }
46
+
47
+ export {
48
+ isValidTsx,
49
+ safeWrite
50
+ };
@@ -0,0 +1,260 @@
1
+ import {
2
+ safeWrite
3
+ } from "./chunk-U6M76BKY.js";
4
+
5
+ // src/utils/tsc-autofix.ts
6
+ import { existsSync, readFileSync } from "fs";
7
+ import { execSync } from "child_process";
8
+ import { resolve } from "path";
9
+
10
+ // src/utils/tsc-error-parser.ts
11
+ var ERROR_RE = /^(.+?)\((\d+),(\d+)\): error (TS\d+): (.+)$/;
12
+ var RELATED_LOCATION_RE = /^(.+?)\((\d+),(\d+)\):\s/;
13
+ function parseTscOutput(output) {
14
+ const lines = output.split("\n");
15
+ const errors = [];
16
+ const seen = /* @__PURE__ */ new Set();
17
+ let current = null;
18
+ for (const raw of lines) {
19
+ const trimmed = raw.trimStart();
20
+ const match = trimmed.match(ERROR_RE);
21
+ if (match) {
22
+ const [, file, lineStr, colStr, code, msg] = match;
23
+ const isRelated = raw.startsWith(" ");
24
+ if (isRelated && current) {
25
+ const cleanFile = file.trim();
26
+ if (!current.relatedFiles.includes(cleanFile)) {
27
+ current.relatedFiles.push(cleanFile);
28
+ }
29
+ } else {
30
+ flushCurrent();
31
+ current = {
32
+ file: file.trim(),
33
+ line: parseInt(lineStr, 10),
34
+ col: parseInt(colStr, 10),
35
+ code,
36
+ message: msg,
37
+ relatedFiles: []
38
+ };
39
+ }
40
+ } else if (current && raw.startsWith(" ") && raw.trim().length > 0) {
41
+ const locMatch = trimmed.match(RELATED_LOCATION_RE);
42
+ if (locMatch) {
43
+ const cleanFile = locMatch[1].trim();
44
+ if (!current.relatedFiles.includes(cleanFile)) {
45
+ current.relatedFiles.push(cleanFile);
46
+ }
47
+ } else {
48
+ current.message += "\n" + raw.trim();
49
+ }
50
+ }
51
+ }
52
+ flushCurrent();
53
+ return errors;
54
+ function flushCurrent() {
55
+ if (!current) return;
56
+ const key = `${current.file}:${current.line}:${current.code}`;
57
+ if (!seen.has(key)) {
58
+ seen.add(key);
59
+ errors.push(current);
60
+ }
61
+ current = null;
62
+ }
63
+ }
64
+
65
+ // src/utils/tsc-autofix.ts
66
+ function runTscCheck(projectRoot, timeout = 3e4) {
67
+ const tsconfigPath = resolve(projectRoot, "tsconfig.json");
68
+ if (!existsSync(tsconfigPath)) return [];
69
+ try {
70
+ execSync("npx tsc --noEmit 2>&1", {
71
+ cwd: projectRoot,
72
+ timeout,
73
+ encoding: "utf-8"
74
+ });
75
+ return [];
76
+ } catch (err) {
77
+ if (err && typeof err === "object" && "killed" in err && err.killed) {
78
+ console.log(" \u26A0 TypeScript check timed out \u2014 skipping");
79
+ return [];
80
+ }
81
+ const e = err;
82
+ const output = (e.stdout || "") + (e.stderr || "");
83
+ return parseTscOutput(output);
84
+ }
85
+ }
86
+ function levenshtein(a, b) {
87
+ const m = a.length, n = b.length;
88
+ const dp = Array.from(
89
+ { length: m + 1 },
90
+ (_, i) => Array.from({ length: n + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
91
+ );
92
+ for (let i = 1; i <= m; i++)
93
+ for (let j = 1; j <= n; j++)
94
+ dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
95
+ return dp[m][n];
96
+ }
97
+ function maxLevenshtein(fieldName) {
98
+ return Math.max(1, Math.floor(fieldName.length * 0.4));
99
+ }
100
+ function escapeRegExp(s) {
101
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
102
+ }
103
+ var MISSING_PROP_RE = /Property '(\w+)' is missing in type '\{([^}]*)\}'/;
104
+ var UNION_RE = /Type 'string' is not assignable to type '((?:"[^"]+"\s*\|\s*)*"[^"]+")'/;
105
+ var MISSING_REQUIRED_RE = /Property '(\w+)' is missing in type .* but required/;
106
+ function extractFieldsFromCode(code, line) {
107
+ const lines = code.split("\n");
108
+ const searchRange = lines.slice(Math.max(0, line - 3), line + 3).join(" ");
109
+ const fieldMatches = searchRange.match(/(\w+)\s*:/g);
110
+ if (!fieldMatches) return [];
111
+ return fieldMatches.map((m) => m.replace(/\s*:$/, ""));
112
+ }
113
+ function fixFieldRename(code, error, errorLine) {
114
+ const match = error.message.match(MISSING_PROP_RE);
115
+ const expectedField = match?.[1] ?? error.message.match(/Property '(\w+)' is missing/)?.[1];
116
+ if (!expectedField) return null;
117
+ let typeFields;
118
+ if (match?.[2]) {
119
+ typeFields = match[2].split(";").map((f) => f.trim().split(":")[0]?.trim()).filter(Boolean);
120
+ } else {
121
+ typeFields = extractFieldsFromCode(code, errorLine ?? error.line);
122
+ }
123
+ let bestMatch = null;
124
+ let bestDist = Infinity;
125
+ for (const field of typeFields) {
126
+ if (field === expectedField) continue;
127
+ if (field.includes(expectedField) || expectedField.includes(field)) {
128
+ bestMatch = field;
129
+ bestDist = 0;
130
+ break;
131
+ }
132
+ const dist = levenshtein(field.toLowerCase(), expectedField.toLowerCase());
133
+ if (dist <= maxLevenshtein(expectedField) && dist < bestDist) {
134
+ bestDist = dist;
135
+ bestMatch = field;
136
+ }
137
+ }
138
+ if (!bestMatch) return null;
139
+ const targetLine = errorLine ?? error.line;
140
+ const lines = code.split("\n");
141
+ const targetIdx = targetLine - 1;
142
+ const windowStart = Math.max(0, targetIdx - 5);
143
+ const windowEnd = Math.min(lines.length, targetIdx + 6);
144
+ const fieldRe = new RegExp(`(\\b)${escapeRegExp(bestMatch)}(\\s*:)`, "g");
145
+ for (let i = windowStart; i < windowEnd; i++) {
146
+ if (fieldRe.test(lines[i])) {
147
+ lines[i] = lines[i].replace(fieldRe, `$1${expectedField}$2`);
148
+ }
149
+ fieldRe.lastIndex = 0;
150
+ }
151
+ const newCode = lines.join("\n");
152
+ if (newCode === code) return null;
153
+ return { code: newCode, field: `${bestMatch} \u2192 ${expectedField}` };
154
+ }
155
+ function fixUnionType(code, error) {
156
+ const match = error.message.match(UNION_RE);
157
+ if (!match) return null;
158
+ const variants = match[1].match(/"([^"]+)"/g)?.map((v) => v.replace(/"/g, ""));
159
+ if (!variants || variants.length === 0) return null;
160
+ const lines = code.split("\n");
161
+ const errorLine = lines[error.line - 1];
162
+ if (!errorLine) return null;
163
+ for (const variant of variants) {
164
+ const caseInsensitiveRe = new RegExp(`['"]${escapeRegExp(variant)}['"]`, "i");
165
+ const exactRe = new RegExp(`['"]${escapeRegExp(variant)}['"]`);
166
+ if (caseInsensitiveRe.test(errorLine) && !exactRe.test(errorLine)) {
167
+ lines[error.line - 1] = errorLine.replace(caseInsensitiveRe, `'${variant}'`);
168
+ return { code: lines.join("\n"), fix: `union case: '${variant}'` };
169
+ }
170
+ }
171
+ return null;
172
+ }
173
+ function fixMissingEventHandler(code, error) {
174
+ const match = error.message.match(MISSING_REQUIRED_RE);
175
+ if (!match) return null;
176
+ const propName = match[1];
177
+ if (!propName.startsWith("on") || propName.length < 3) return null;
178
+ if (propName[2] !== propName[2].toUpperCase()) return null;
179
+ const lines = code.split("\n");
180
+ const errorLine = lines[error.line - 1];
181
+ if (!errorLine) return null;
182
+ const closingMatch = errorLine.match(/(\s*\/?>)/);
183
+ if (!closingMatch) return null;
184
+ const insertPos = errorLine.lastIndexOf(closingMatch[1]);
185
+ lines[error.line - 1] = errorLine.slice(0, insertPos) + ` ${propName}={() => {}}` + errorLine.slice(insertPos);
186
+ return { code: lines.join("\n"), prop: propName };
187
+ }
188
+ function deduplicateErrors(errors) {
189
+ const seen = /* @__PURE__ */ new Set();
190
+ return errors.filter((e) => {
191
+ const key = `${e.file}:${e.line}:${e.code}`;
192
+ if (seen.has(key)) return false;
193
+ seen.add(key);
194
+ return true;
195
+ });
196
+ }
197
+ async function applyDeterministicFixes(errors, projectRoot, backups) {
198
+ const deduped = deduplicateErrors(errors);
199
+ const fixed = [];
200
+ const remaining = [];
201
+ const fileErrors = /* @__PURE__ */ new Map();
202
+ for (const err of deduped) {
203
+ const list = fileErrors.get(err.file) || [];
204
+ list.push(err);
205
+ fileErrors.set(err.file, list);
206
+ }
207
+ for (const [file, errs] of fileErrors) {
208
+ const absPath = resolve(projectRoot, file);
209
+ let code;
210
+ try {
211
+ code = readFileSync(absPath, "utf-8");
212
+ } catch {
213
+ remaining.push(...errs);
214
+ continue;
215
+ }
216
+ let changed = false;
217
+ const fileRemaining = [];
218
+ for (const e of errs) {
219
+ const renameResult = fixFieldRename(code, e, e.line);
220
+ if (renameResult) {
221
+ code = renameResult.code;
222
+ changed = true;
223
+ continue;
224
+ }
225
+ const unionResult = fixUnionType(code, e);
226
+ if (unionResult) {
227
+ code = unionResult.code;
228
+ changed = true;
229
+ continue;
230
+ }
231
+ const handlerResult = fixMissingEventHandler(code, e);
232
+ if (handlerResult) {
233
+ code = handlerResult.code;
234
+ changed = true;
235
+ continue;
236
+ }
237
+ fileRemaining.push(e);
238
+ }
239
+ if (changed) {
240
+ const { ok } = safeWrite(absPath, code, projectRoot, backups);
241
+ if (ok) {
242
+ fixed.push(file);
243
+ remaining.push(...fileRemaining);
244
+ } else {
245
+ remaining.push(...errs);
246
+ }
247
+ } else {
248
+ remaining.push(...fileRemaining);
249
+ }
250
+ }
251
+ return { fixed, remaining };
252
+ }
253
+
254
+ export {
255
+ runTscCheck,
256
+ fixFieldRename,
257
+ fixUnionType,
258
+ fixMissingEventHandler,
259
+ applyDeterministicFixes
260
+ };
package/dist/index.js CHANGED
@@ -53,6 +53,10 @@ import {
53
53
  savePlan,
54
54
  updateArchitecturePlan
55
55
  } from "./chunk-VLBVBF6V.js";
56
+ import {
57
+ isValidTsx,
58
+ safeWrite
59
+ } from "./chunk-U6M76BKY.js";
56
60
  import {
57
61
  toKebabCase,
58
62
  toTitleCase
@@ -5018,6 +5022,65 @@ async function applyModification(request, dsm, cm, pm, projectRoot, aiProvider,
5018
5022
  allFixes.forEach((f) => console.log(chalk8.dim(` ${f}`)));
5019
5023
  }
5020
5024
  await writeFile(filePath, codeToWrite);
5025
+ try {
5026
+ const { runTscCheck, applyDeterministicFixes } = await import("./tsc-autofix-S5PKMFSC.js");
5027
+ const tscBackups = /* @__PURE__ */ new Map();
5028
+ const relPath = filePath.replace(projectRoot + "/", "").replace(projectRoot + "\\", "");
5029
+ const tscErrors = runTscCheck(projectRoot).filter((e) => e.file === relPath);
5030
+ if (tscErrors.length > 0) {
5031
+ let bestSnapshot = codeToWrite;
5032
+ const detResult = await applyDeterministicFixes(tscErrors, projectRoot, tscBackups);
5033
+ const bestErrorCount = detResult.remaining.length;
5034
+ if (detResult.fixed.length > 0) {
5035
+ codeToWrite = await readFile(filePath);
5036
+ bestSnapshot = codeToWrite;
5037
+ console.log(
5038
+ chalk8.green(` \u2714 Fixed ${tscErrors.length - detResult.remaining.length} TypeScript error(s)`)
5039
+ );
5040
+ }
5041
+ if (detResult.remaining.length > 0 && aiProvider) {
5042
+ try {
5043
+ const ai = await createAIProvider(aiProvider);
5044
+ if (ai.editPageCode) {
5045
+ const errorList = detResult.remaining.map((e) => `Line ${e.line}: [${e.code}] ${e.message.split("\n")[0]}`).join("\n");
5046
+ const tscFixed = await ai.editPageCode(
5047
+ codeToWrite,
5048
+ `Fix these TypeScript errors:
5049
+ ${errorList}
5050
+
5051
+ Keep all existing functionality intact.`,
5052
+ page.name || page.id || "Page"
5053
+ );
5054
+ if (tscFixed && tscFixed.length > 100) {
5055
+ const { code: reFixed } = await autoFixCode(tscFixed, autoFixCtx);
5056
+ await writeFile(filePath, reFixed);
5057
+ const afterErrors = runTscCheck(projectRoot).filter((e) => e.file === relPath);
5058
+ if (afterErrors.length > bestErrorCount) {
5059
+ await writeFile(filePath, bestSnapshot);
5060
+ codeToWrite = bestSnapshot;
5061
+ console.log(chalk8.yellow(` \u26A0 AI fix regressed TypeScript errors. Reverted to best version.`));
5062
+ } else {
5063
+ codeToWrite = reFixed;
5064
+ console.log(
5065
+ chalk8.green(
5066
+ ` \u2714 Fixed ${detResult.remaining.length - afterErrors.length} TypeScript error(s) via AI`
5067
+ )
5068
+ );
5069
+ }
5070
+ }
5071
+ }
5072
+ } catch (tscAiErr) {
5073
+ console.log(
5074
+ chalk8.dim(` \u26A0 AI tsc fix skipped: ${tscAiErr instanceof Error ? tscAiErr.message : "unknown"}`)
5075
+ );
5076
+ }
5077
+ }
5078
+ }
5079
+ } catch (tscErr) {
5080
+ console.log(
5081
+ chalk8.dim(` \u26A0 TypeScript check skipped: ${tscErr instanceof Error ? tscErr.message : "unknown"}`)
5082
+ );
5083
+ }
5021
5084
  const pageIdx = dsm.getConfig().pages.findIndex((p) => p.id === page.id);
5022
5085
  if (pageIdx !== -1) {
5023
5086
  const cfg = dsm.getConfig();
@@ -8084,8 +8147,8 @@ async function regenerateDocsCommand() {
8084
8147
 
8085
8148
  // src/commands/fix.ts
8086
8149
  import chalk15 from "chalk";
8087
- import { readdirSync as readdirSync7, readFileSync as readFileSync11, existsSync as existsSync15, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8088
- import { resolve as resolve8, join as join12, relative as relative5, basename as basename3 } from "path";
8150
+ import { readdirSync as readdirSync7, readFileSync as readFileSync10, existsSync as existsSync14, rmSync as rmSync5, mkdirSync as mkdirSync7 } from "fs";
8151
+ import { resolve as resolve8, join as join11, relative as relative5, basename as basename3 } from "path";
8089
8152
  import {
8090
8153
  DesignSystemManager as DesignSystemManager9,
8091
8154
  ComponentManager as ComponentManager5,
@@ -8094,54 +8157,6 @@ import {
8094
8157
  loadManifest as loadManifest9,
8095
8158
  saveManifest as saveManifest5
8096
8159
  } from "@getcoherent/core";
8097
-
8098
- // src/commands/fix-validation.ts
8099
- import { createRequire } from "module";
8100
- import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
8101
- import { join as join11 } from "path";
8102
- var cachedTs = null;
8103
- var cachedProjectRoot = null;
8104
- function isValidTsx(code, projectRoot, ext = ".tsx") {
8105
- if (ext !== ".tsx" && ext !== ".ts") return true;
8106
- const pkgJson = join11(projectRoot, "package.json");
8107
- if (!existsSync14(pkgJson)) return true;
8108
- try {
8109
- if (!cachedTs || cachedProjectRoot !== projectRoot) {
8110
- const req = createRequire(pkgJson);
8111
- cachedTs = req("typescript");
8112
- cachedProjectRoot = projectRoot;
8113
- }
8114
- const sf = cachedTs.createSourceFile(
8115
- "check.tsx",
8116
- code,
8117
- cachedTs.ScriptTarget.Latest,
8118
- false,
8119
- cachedTs.ScriptKind.TSX
8120
- );
8121
- const diagnostics = sf.parseDiagnostics;
8122
- return !diagnostics || diagnostics.length === 0;
8123
- } catch {
8124
- return true;
8125
- }
8126
- }
8127
- function safeWrite(filePath, newContent, projectRoot, backups) {
8128
- if (!backups.has(filePath)) {
8129
- try {
8130
- backups.set(filePath, readFileSync10(filePath, "utf-8"));
8131
- } catch {
8132
- }
8133
- }
8134
- const ext = filePath.slice(filePath.lastIndexOf("."));
8135
- writeFileSync9(filePath, newContent, "utf-8");
8136
- if (!isValidTsx(newContent, projectRoot, ext)) {
8137
- const original = backups.get(filePath);
8138
- if (original) writeFileSync9(filePath, original, "utf-8");
8139
- return { ok: false };
8140
- }
8141
- return { ok: true };
8142
- }
8143
-
8144
- // src/commands/fix.ts
8145
8160
  function extractComponentIdsFromCode2(code) {
8146
8161
  const ids = /* @__PURE__ */ new Set();
8147
8162
  const allMatches = code.matchAll(/@\/components\/((?:ui\/)?[a-z0-9-]+)/g);
@@ -8159,7 +8174,7 @@ function listTsxFiles(dir) {
8159
8174
  try {
8160
8175
  const entries = readdirSync7(dir, { withFileTypes: true });
8161
8176
  for (const e of entries) {
8162
- const full = join12(dir, e.name);
8177
+ const full = join11(dir, e.name);
8163
8178
  if (e.isDirectory() && e.name !== "node_modules" && !e.name.startsWith(".")) {
8164
8179
  files.push(...listTsxFiles(full));
8165
8180
  } else if (e.isFile() && e.name.endsWith(".tsx")) {
@@ -8190,8 +8205,8 @@ async function fixCommand(opts = {}) {
8190
8205
  console.log(chalk15.cyan("\ncoherent fix\n"));
8191
8206
  }
8192
8207
  if (!skipCache) {
8193
- const nextDir = join12(projectRoot, ".next");
8194
- if (existsSync15(nextDir)) {
8208
+ const nextDir = join11(projectRoot, ".next");
8209
+ if (existsSync14(nextDir)) {
8195
8210
  if (!dryRun) rmSync5(nextDir, { recursive: true, force: true });
8196
8211
  fixes.push("Cleared build cache");
8197
8212
  console.log(chalk15.green(" \u2714 Cleared build cache"));
@@ -8218,7 +8233,7 @@ async function fixCommand(opts = {}) {
8218
8233
  const componentsTsxFiles = listTsxFiles(resolve8(projectRoot, "components"));
8219
8234
  const allComponentIds = /* @__PURE__ */ new Set();
8220
8235
  for (const file of [...allTsxFiles, ...componentsTsxFiles]) {
8221
- const content = readFileSync11(file, "utf-8");
8236
+ const content = readFileSync10(file, "utf-8");
8222
8237
  extractComponentIdsFromCode2(content).forEach((id) => allComponentIds.add(id));
8223
8238
  }
8224
8239
  let dsm = null;
@@ -8238,7 +8253,7 @@ async function fixCommand(opts = {}) {
8238
8253
  } else {
8239
8254
  const fileName = toKebabCase(id) + ".tsx";
8240
8255
  const filePath = resolve8(projectRoot, "components", "ui", fileName);
8241
- if (!existsSync15(filePath)) missingFiles.push(id);
8256
+ if (!existsSync14(filePath)) missingFiles.push(id);
8242
8257
  }
8243
8258
  }
8244
8259
  const provider = getComponentProvider();
@@ -8287,7 +8302,7 @@ async function fixCommand(opts = {}) {
8287
8302
  }
8288
8303
  }
8289
8304
  }
8290
- if (!dsm && existsSync15(project.configPath)) {
8305
+ if (!dsm && existsSync14(project.configPath)) {
8291
8306
  dsm = new DesignSystemManager9(project.configPath);
8292
8307
  await dsm.load();
8293
8308
  }
@@ -8296,8 +8311,8 @@ async function fixCommand(opts = {}) {
8296
8311
  let derivedName = null;
8297
8312
  try {
8298
8313
  const pkgPath = resolve8(projectRoot, "package.json");
8299
- if (existsSync15(pkgPath)) {
8300
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
8314
+ if (existsSync14(pkgPath)) {
8315
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
8301
8316
  if (typeof pkg.name === "string" && pkg.name) {
8302
8317
  derivedName = toTitleCase2(pkg.name);
8303
8318
  }
@@ -8334,8 +8349,8 @@ async function fixCommand(opts = {}) {
8334
8349
  const configName = dsm.getConfig().name;
8335
8350
  if (configName && configName !== "My App") {
8336
8351
  const appLayoutPath = resolve8(projectRoot, "app", "(app)", "layout.tsx");
8337
- if (existsSync15(appLayoutPath)) {
8338
- let appLayoutCode = readFileSync11(appLayoutPath, "utf-8");
8352
+ if (existsSync14(appLayoutPath)) {
8353
+ let appLayoutCode = readFileSync10(appLayoutPath, "utf-8");
8339
8354
  if (appLayoutCode.includes("My App")) {
8340
8355
  appLayoutCode = appLayoutCode.replace(/My App/g, configName);
8341
8356
  if (!dryRun) {
@@ -8353,11 +8368,11 @@ async function fixCommand(opts = {}) {
8353
8368
  }
8354
8369
  }
8355
8370
  const sharedDir = resolve8(projectRoot, "components", "shared");
8356
- if (existsSync15(sharedDir)) {
8371
+ if (existsSync14(sharedDir)) {
8357
8372
  try {
8358
8373
  for (const f of readdirSync7(sharedDir).filter((n) => n.endsWith(".tsx"))) {
8359
- const sharedPath = join12(sharedDir, f);
8360
- const sharedCode = readFileSync11(sharedPath, "utf-8");
8374
+ const sharedPath = join11(sharedDir, f);
8375
+ const sharedCode = readFileSync10(sharedPath, "utf-8");
8361
8376
  if (sharedCode.includes("My App")) {
8362
8377
  const updated = sharedCode.replace(/My App/g, configName);
8363
8378
  if (!dryRun) {
@@ -8381,7 +8396,7 @@ async function fixCommand(opts = {}) {
8381
8396
  let syntaxFixed = 0;
8382
8397
  for (const file of userTsxFiles) {
8383
8398
  try {
8384
- const content = readFileSync11(file, "utf-8");
8399
+ const content = readFileSync10(file, "utf-8");
8385
8400
  const fixed = fixUnescapedLtInJsx(
8386
8401
  fixEscapedClosingQuotes(sanitizeMetadataStrings(ensureUseClientIfNeeded(content)))
8387
8402
  );
@@ -8424,7 +8439,7 @@ async function fixCommand(opts = {}) {
8424
8439
  console.log(chalk15.green(` \u2714 Verified group layouts: ${layoutTypes}`));
8425
8440
  const hasSidebar = plan.groups.some((g) => g.layout === "sidebar" || g.layout === "both");
8426
8441
  const sidebarPath = resolve8(projectRoot, "components", "shared", "sidebar.tsx");
8427
- if (hasSidebar && !existsSync15(sidebarPath) && !dryRun) {
8442
+ if (hasSidebar && !existsSync14(sidebarPath) && !dryRun) {
8428
8443
  if (!dsm) {
8429
8444
  dsm = new DesignSystemManager9(project.configPath);
8430
8445
  await dsm.load();
@@ -8443,8 +8458,8 @@ async function fixCommand(opts = {}) {
8443
8458
  }
8444
8459
  if (hasSidebar && !dryRun) {
8445
8460
  const rootLayoutPath = resolve8(projectRoot, "app", "layout.tsx");
8446
- if (existsSync15(rootLayoutPath)) {
8447
- let rootCode = readFileSync11(rootLayoutPath, "utf-8");
8461
+ if (existsSync14(rootLayoutPath)) {
8462
+ let rootCode = readFileSync10(rootLayoutPath, "utf-8");
8448
8463
  if (rootCode.includes("<Header")) {
8449
8464
  rootCode = rootCode.replace(/import\s*\{[^}]*Header[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s*\{[^}]*Footer[^}]*\}[^;\n]*[;\n]?\s*/g, "").replace(/import\s+ShowWhenNotAuthRoute[^;\n]*[;\n]?\s*/g, "").replace(/<ShowWhenNotAuthRoute>[\s\S]*?<\/ShowWhenNotAuthRoute>/g, (match) => {
8450
8465
  const inner = match.replace(/<\/?ShowWhenNotAuthRoute>/g, "").trim();
@@ -8462,8 +8477,8 @@ async function fixCommand(opts = {}) {
8462
8477
  }
8463
8478
  }
8464
8479
  const publicLayoutPath = resolve8(projectRoot, "app", "(public)", "layout.tsx");
8465
- const publicExists = existsSync15(publicLayoutPath);
8466
- const needsPublicLayout = !publicExists || !readFileSync11(publicLayoutPath, "utf-8").includes("<Header");
8480
+ const publicExists = existsSync14(publicLayoutPath);
8481
+ const needsPublicLayout = !publicExists || !readFileSync10(publicLayoutPath, "utf-8").includes("<Header");
8467
8482
  if (needsPublicLayout) {
8468
8483
  const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-YSGVHVNN.js");
8469
8484
  mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
@@ -8476,8 +8491,8 @@ async function fixCommand(opts = {}) {
8476
8491
  }
8477
8492
  }
8478
8493
  const sidebarComponentPath2 = resolve8(projectRoot, "components", "shared", "sidebar.tsx");
8479
- if (existsSync15(sidebarComponentPath2)) {
8480
- const existingSidebarCode = readFileSync11(sidebarComponentPath2, "utf-8");
8494
+ if (existsSync14(sidebarComponentPath2)) {
8495
+ const existingSidebarCode = readFileSync10(sidebarComponentPath2, "utf-8");
8481
8496
  const sidebarConfigName = dsm?.getConfig().name ?? "";
8482
8497
  const hasWrongName = existingSidebarCode.includes("My App") && sidebarConfigName !== "My App";
8483
8498
  const hasTrigger = existingSidebarCode.includes("SidebarTrigger");
@@ -8505,7 +8520,7 @@ async function fixCommand(opts = {}) {
8505
8520
  }
8506
8521
  const rootPagePath = resolve8(projectRoot, "app", "page.tsx");
8507
8522
  const publicPagePath = resolve8(projectRoot, "app", "(public)", "page.tsx");
8508
- if (existsSync15(rootPagePath) && !existsSync15(publicPagePath)) {
8523
+ if (existsSync14(rootPagePath) && !existsSync14(publicPagePath)) {
8509
8524
  const { renameSync } = await import("fs");
8510
8525
  mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
8511
8526
  renameSync(rootPagePath, publicPagePath);
@@ -8513,7 +8528,7 @@ async function fixCommand(opts = {}) {
8513
8528
  console.log(chalk15.green(" \u2714 Moved app/page.tsx \u2192 app/(public)/page.tsx (gets Header/Footer)"));
8514
8529
  }
8515
8530
  const themeTogglePath = resolve8(projectRoot, "components", "shared", "theme-toggle.tsx");
8516
- if (!existsSync15(themeTogglePath)) {
8531
+ if (!existsSync14(themeTogglePath)) {
8517
8532
  const { generateThemeToggleCode } = await import("./code-generator-YSGVHVNN.js");
8518
8533
  mkdirSync7(resolve8(projectRoot, "components", "shared"), { recursive: true });
8519
8534
  const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
@@ -8530,8 +8545,8 @@ async function fixCommand(opts = {}) {
8530
8545
  console.log(chalk15.yellow(` \u26A0 Layout repair skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8531
8546
  }
8532
8547
  const appLayoutRepairPath = resolve8(projectRoot, "app", "(app)", "layout.tsx");
8533
- if (existsSync15(appLayoutRepairPath) && dsm) {
8534
- const appLayoutCode = readFileSync11(appLayoutRepairPath, "utf-8");
8548
+ if (existsSync14(appLayoutRepairPath) && dsm) {
8549
+ const appLayoutCode = readFileSync10(appLayoutRepairPath, "utf-8");
8535
8550
  const isMinimal = appLayoutCode.length < 500 && !appLayoutCode.includes("Header") && !appLayoutCode.includes("Footer") && !appLayoutCode.includes("Sidebar") && !appLayoutCode.includes("SidebarProvider") && !appLayoutCode.includes("SidebarTrigger") && !appLayoutCode.includes("Sheet");
8536
8551
  const navType = dsm.getConfig().navigation?.type || "header";
8537
8552
  if (isMinimal && navType !== "none") {
@@ -8559,7 +8574,7 @@ async function fixCommand(opts = {}) {
8559
8574
  const qualityFixDetails = [];
8560
8575
  for (const file of allValidationFiles) {
8561
8576
  try {
8562
- const content = readFileSync11(file, "utf-8");
8577
+ const content = readFileSync10(file, "utf-8");
8563
8578
  const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8564
8579
  if (autoFixed !== content) {
8565
8580
  if (!dryRun) {
@@ -8594,7 +8609,7 @@ async function fixCommand(opts = {}) {
8594
8609
  let mockFixed = 0;
8595
8610
  for (const file of allValidationFiles) {
8596
8611
  try {
8597
- const content = readFileSync11(file, "utf-8");
8612
+ const content = readFileSync10(file, "utf-8");
8598
8613
  const mockIssues = validateMockData(content);
8599
8614
  if (mockIssues.length > 0) {
8600
8615
  const fixed = applyMockDataFixes(content, mockIssues);
@@ -8625,7 +8640,7 @@ async function fixCommand(opts = {}) {
8625
8640
  for (const file of modifiedFiles) {
8626
8641
  if (!backups.has(file)) continue;
8627
8642
  const before = backups.get(file);
8628
- const after = readFileSync11(file, "utf-8");
8643
+ const after = readFileSync10(file, "utf-8");
8629
8644
  const issues = verifyIncrementalEdit(before, after);
8630
8645
  if (issues.length > 0) {
8631
8646
  for (const issue of issues) {
@@ -8638,7 +8653,7 @@ async function fixCommand(opts = {}) {
8638
8653
  const fileIssues = [];
8639
8654
  for (const file of allValidationFiles) {
8640
8655
  try {
8641
- const code = readFileSync11(file, "utf-8");
8656
+ const code = readFileSync10(file, "utf-8");
8642
8657
  const relativePath = file.replace(projectRoot + "/", "");
8643
8658
  const baseName = file.split("/").pop() || "";
8644
8659
  const isAuthPage = relativePath.includes("(auth)");
@@ -8748,26 +8763,64 @@ async function fixCommand(opts = {}) {
8748
8763
  }
8749
8764
  try {
8750
8765
  const tsconfigPath = resolve8(projectRoot, "tsconfig.json");
8751
- if (existsSync15(tsconfigPath)) {
8752
- const { execSync: execSync2 } = await import("child_process");
8753
- execSync2("npx tsc --noEmit 2>&1", {
8754
- cwd: projectRoot,
8755
- timeout: 3e4,
8756
- encoding: "utf-8"
8757
- });
8758
- fixes.push("TypeScript compilation clean");
8759
- console.log(chalk15.green(" \u2714 TypeScript compilation clean"));
8760
- }
8761
- } catch (err) {
8762
- const output = (err.stdout || "") + (err.stderr || "");
8763
- const errorLines = output.split("\n").filter((l) => l.includes("error TS"));
8764
- if (errorLines.length > 0) {
8765
- for (const line of errorLines.slice(0, 10)) {
8766
- remaining.push(line.trim());
8766
+ if (existsSync14(tsconfigPath)) {
8767
+ const { runTscCheck, applyDeterministicFixes } = await import("./tsc-autofix-S5PKMFSC.js");
8768
+ const { applyAiFixes } = await import("./tsc-ai-fix-O3EMRWV2.js");
8769
+ const tscErrors = runTscCheck(projectRoot);
8770
+ if (tscErrors.length === 0) {
8771
+ fixes.push("TypeScript compilation clean");
8772
+ console.log(chalk15.green(" \u2714 TypeScript compilation clean"));
8773
+ } else {
8774
+ const detResult = await applyDeterministicFixes(tscErrors, projectRoot, backups);
8775
+ if (detResult.fixed.length > 0) {
8776
+ fixes.push(`TypeScript: fixed ${detResult.fixed.length} file(s) deterministically`);
8777
+ console.log(chalk15.green(` \u2714 TypeScript: fixed ${detResult.fixed.length} file(s) deterministically`));
8778
+ }
8779
+ if (detResult.remaining.length > 0) {
8780
+ let aiProvider;
8781
+ try {
8782
+ const { createAIProvider: createAIProvider2 } = await import("./ai-provider-CGSIYFZT.js");
8783
+ aiProvider = await createAIProvider2("auto");
8784
+ } catch {
8785
+ }
8786
+ if (aiProvider?.editPageCode) {
8787
+ console.log(chalk15.dim(` \u23F3 Using AI to fix ${detResult.remaining.length} TypeScript error(s)...`));
8788
+ const aiResult = await applyAiFixes(detResult.remaining, projectRoot, backups, aiProvider);
8789
+ if (aiResult.fixed.length > 0) {
8790
+ fixes.push(`TypeScript: fixed ${aiResult.fixed.length} file(s) via AI`);
8791
+ console.log(chalk15.green(` \u2714 TypeScript: fixed ${aiResult.fixed.length} file(s) via AI`));
8792
+ }
8793
+ if (aiResult.failed.length > 0) {
8794
+ for (const e of aiResult.failed.slice(0, 10)) {
8795
+ remaining.push(`${e.file}(${e.line}): [${e.code}] ${e.message.split("\n")[0]}`);
8796
+ }
8797
+ if (aiResult.failed.length > 10) {
8798
+ remaining.push(`... and ${aiResult.failed.length - 10} more TypeScript errors`);
8799
+ }
8800
+ console.log(chalk15.yellow(` \u26A0 TypeScript: ${aiResult.failed.length} error(s) remaining`));
8801
+ }
8802
+ } else {
8803
+ for (const e of detResult.remaining.slice(0, 10)) {
8804
+ remaining.push(`${e.file}(${e.line}): [${e.code}] ${e.message.split("\n")[0]}`);
8805
+ }
8806
+ if (detResult.remaining.length > 10) {
8807
+ remaining.push(`... and ${detResult.remaining.length - 10} more TypeScript errors`);
8808
+ }
8809
+ console.log(
8810
+ chalk15.yellow(
8811
+ ` \u26A0 TypeScript: ${detResult.remaining.length} error(s) remaining. Configure API key for auto-fix.`
8812
+ )
8813
+ );
8814
+ }
8815
+ }
8816
+ const finalErrors = runTscCheck(projectRoot);
8817
+ if (finalErrors.length === 0) {
8818
+ console.log(chalk15.green(" \u2714 TypeScript compilation now clean"));
8819
+ }
8767
8820
  }
8768
- if (errorLines.length > 10) remaining.push(`... and ${errorLines.length - 10} more TypeScript errors`);
8769
- console.log(chalk15.yellow(` \u26A0 TypeScript: ${errorLines.length} error(s)`));
8770
8821
  }
8822
+ } catch (err) {
8823
+ console.log(chalk15.yellow(` \u26A0 TypeScript check skipped: ${err instanceof Error ? err.message : "unknown error"}`));
8771
8824
  }
8772
8825
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
8773
8826
  console.log(chalk15.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
@@ -8798,7 +8851,7 @@ async function fixCommand(opts = {}) {
8798
8851
  // src/commands/check.ts
8799
8852
  import chalk16 from "chalk";
8800
8853
  import { resolve as resolve9 } from "path";
8801
- import { readdirSync as readdirSync8, readFileSync as readFileSync12, statSync as statSync3, existsSync as existsSync16 } from "fs";
8854
+ import { readdirSync as readdirSync8, readFileSync as readFileSync11, statSync as statSync3, existsSync as existsSync15 } from "fs";
8802
8855
  import { loadManifest as loadManifest10 } from "@getcoherent/core";
8803
8856
  var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", "design-system"]);
8804
8857
  function findTsxFiles(dir) {
@@ -8855,7 +8908,7 @@ async function checkCommand(opts = {}) {
8855
8908
  "NATIVE_TABLE"
8856
8909
  ]);
8857
8910
  for (const file of files) {
8858
- const code = readFileSync12(file, "utf-8");
8911
+ const code = readFileSync11(file, "utf-8");
8859
8912
  const relativePath = file.replace(projectRoot + "/", "");
8860
8913
  const baseName = file.split("/").pop() || "";
8861
8914
  const isAuthPage = relativePath.includes("(auth)");
@@ -8897,7 +8950,7 @@ async function checkCommand(opts = {}) {
8897
8950
  routeSet.add("/");
8898
8951
  routeSet.add("#");
8899
8952
  for (const file of files) {
8900
- const code = readFileSync12(file, "utf-8");
8953
+ const code = readFileSync11(file, "utf-8");
8901
8954
  const relativePath = file.replace(projectRoot + "/", "");
8902
8955
  const lines = code.split("\n");
8903
8956
  const linkHrefRe = /href\s*=\s*["'](\/[a-z0-9/-]*)["']/gi;
@@ -8930,7 +8983,7 @@ async function checkCommand(opts = {}) {
8930
8983
  if (manifest.shared.length > 0) {
8931
8984
  for (const entry of manifest.shared) {
8932
8985
  const fullPath = resolve9(project.root, entry.file);
8933
- if (!existsSync16(fullPath)) {
8986
+ if (!existsSync15(fullPath)) {
8934
8987
  result.pages.withErrors++;
8935
8988
  if (!opts.json) console.log(chalk16.red(`
8936
8989
  \u2717 Missing shared component file: ${entry.id} (${entry.file})`));
@@ -8955,7 +9008,7 @@ async function checkCommand(opts = {}) {
8955
9008
  let _nameMismatch = 0;
8956
9009
  for (const entry of manifest.shared) {
8957
9010
  const filePath = resolve9(projectRoot, entry.file);
8958
- const fileExists = existsSync16(filePath);
9011
+ const fileExists = existsSync15(filePath);
8959
9012
  if (!fileExists) {
8960
9013
  _orphaned++;
8961
9014
  if (!opts.json) {
@@ -8965,7 +9018,7 @@ async function checkCommand(opts = {}) {
8965
9018
  continue;
8966
9019
  }
8967
9020
  try {
8968
- const code = readFileSync12(filePath, "utf-8");
9021
+ const code = readFileSync11(filePath, "utf-8");
8969
9022
  const actualExports = extractExportedComponentNames(code);
8970
9023
  if (actualExports.length > 0 && !actualExports.includes(entry.name)) {
8971
9024
  _nameMismatch++;
@@ -9033,7 +9086,7 @@ async function checkCommand(opts = {}) {
9033
9086
  id: e.id,
9034
9087
  name: e.name,
9035
9088
  type: e.type,
9036
- status: existsSync16(resolve9(projectRoot, e.file)) ? "ok" : "unused",
9089
+ status: existsSync15(resolve9(projectRoot, e.file)) ? "ok" : "unused",
9037
9090
  message: "",
9038
9091
  suggestions: void 0
9039
9092
  }))
@@ -9047,11 +9100,11 @@ async function checkCommand(opts = {}) {
9047
9100
  const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-HGNEY3W3.js");
9048
9101
  const manifest = await loadManifest10(projectRoot);
9049
9102
  const appDir = resolve9(projectRoot, "app");
9050
- const pageFiles = existsSync16(appDir) ? findTsxFiles(appDir) : [];
9103
+ const pageFiles = existsSync15(appDir) ? findTsxFiles(appDir) : [];
9051
9104
  if (manifest.shared.length > 0 && pageFiles.length > 0) {
9052
9105
  const reuseWarnings = [];
9053
9106
  for (const file of pageFiles) {
9054
- const code = readFileSync12(file, "utf-8");
9107
+ const code = readFileSync11(file, "utf-8");
9055
9108
  const relativePath = file.replace(projectRoot + "/", "");
9056
9109
  const route = "/" + relativePath.replace(/^app\//, "").replace(/\/page\.tsx$/, "").replace(/^\(.*?\)\//, "");
9057
9110
  const pageType = inferPageTypeFromRoute2(route);
@@ -9162,12 +9215,12 @@ import {
9162
9215
  generateSharedComponent as generateSharedComponent4,
9163
9216
  integrateSharedLayoutIntoRootLayout as integrateSharedLayoutIntoRootLayout2
9164
9217
  } from "@getcoherent/core";
9165
- import { existsSync as existsSync17 } from "fs";
9218
+ import { existsSync as existsSync16 } from "fs";
9166
9219
  import { resolve as resolve10 } from "path";
9167
9220
 
9168
9221
  // src/utils/ds-files.ts
9169
9222
  import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
9170
- import { join as join13, dirname as dirname5 } from "path";
9223
+ import { join as join12, dirname as dirname5 } from "path";
9171
9224
  import { DesignSystemGenerator } from "@getcoherent/core";
9172
9225
  var SHARED_DS_KEYS = [
9173
9226
  "app/design-system/shared/page.tsx",
@@ -9181,7 +9234,7 @@ async function writeDesignSystemFiles(projectRoot, config2, options) {
9181
9234
  const toWrite = options?.sharedOnly ? new Map([...files].filter(([path3]) => SHARED_DS_KEYS.includes(path3))) : files;
9182
9235
  const written = [];
9183
9236
  for (const [relativePath, content] of toWrite) {
9184
- const fullPath = join13(projectRoot, relativePath);
9237
+ const fullPath = join12(projectRoot, relativePath);
9185
9238
  await mkdir3(dirname5(fullPath), { recursive: true });
9186
9239
  await writeFile4(fullPath, content, "utf-8");
9187
9240
  written.push(relativePath);
@@ -9317,7 +9370,7 @@ function createComponentsCommand() {
9317
9370
  if (updated) console.log(chalk22.cyan(" Updated app/layout.tsx to use shared layout components.\n"));
9318
9371
  }
9319
9372
  const sharedPagePath = resolve10(project.root, "app/design-system/shared/page.tsx");
9320
- if (!existsSync17(sharedPagePath)) {
9373
+ if (!existsSync16(sharedPagePath)) {
9321
9374
  try {
9322
9375
  const dsm = new DesignSystemManager10(project.configPath);
9323
9376
  await dsm.load();
@@ -9343,8 +9396,8 @@ function createComponentsCommand() {
9343
9396
  import chalk23 from "chalk";
9344
9397
  import ora6 from "ora";
9345
9398
  import { writeFile as writeFile5, mkdir as mkdir4 } from "fs/promises";
9346
- import { resolve as resolve11, join as join14, dirname as dirname6 } from "path";
9347
- import { existsSync as existsSync18 } from "fs";
9399
+ import { resolve as resolve11, join as join13, dirname as dirname6 } from "path";
9400
+ import { existsSync as existsSync17 } from "fs";
9348
9401
  import {
9349
9402
  FigmaClient,
9350
9403
  parseFigmaFileResponse,
@@ -9491,7 +9544,7 @@ async function importFigmaAction(urlOrKey, opts) {
9491
9544
  stats.filesWritten.push(filePath);
9492
9545
  return;
9493
9546
  }
9494
- const fullPath = join14(projectRoot, filePath);
9547
+ const fullPath = join13(projectRoot, filePath);
9495
9548
  await mkdir4(dirname6(fullPath), { recursive: true });
9496
9549
  await writeFile5(fullPath, content, "utf-8");
9497
9550
  stats.filesWritten.push(filePath);
@@ -9593,7 +9646,7 @@ async function importFigmaAction(urlOrKey, opts) {
9593
9646
  spinner.start("Updating design-system.config.ts...");
9594
9647
  const configPath = resolve11(projectRoot, DESIGN_SYSTEM_CONFIG_PATH);
9595
9648
  const dsm = new DesignSystemManager11(configPath);
9596
- if (existsSync18(configPath)) {
9649
+ if (existsSync17(configPath)) {
9597
9650
  await dsm.load();
9598
9651
  const existing = dsm.getConfig();
9599
9652
  dsm.updateConfig({
@@ -9622,8 +9675,8 @@ export const config = ${JSON.stringify(fullConfig, null, 2)} as const
9622
9675
  stats.configUpdated = true;
9623
9676
  spinner.succeed("design-system.config.ts updated");
9624
9677
  spinner.start("Ensuring root layout...");
9625
- const layoutPath = join14(projectRoot, "app/layout.tsx");
9626
- if (!existsSync18(layoutPath)) {
9678
+ const layoutPath = join13(projectRoot, "app/layout.tsx");
9679
+ if (!existsSync17(layoutPath)) {
9627
9680
  await mkdir4(dirname6(layoutPath), { recursive: true });
9628
9681
  await writeFile5(layoutPath, MINIMAL_ROOT_LAYOUT, "utf-8");
9629
9682
  stats.filesWritten.push("app/layout.tsx");
@@ -9713,8 +9766,8 @@ async function dsRegenerateCommand() {
9713
9766
  // src/commands/update.ts
9714
9767
  import chalk25 from "chalk";
9715
9768
  import ora8 from "ora";
9716
- import { readFileSync as readFileSync13, existsSync as existsSync19 } from "fs";
9717
- import { join as join15 } from "path";
9769
+ import { readFileSync as readFileSync12, existsSync as existsSync18 } from "fs";
9770
+ import { join as join14 } from "path";
9718
9771
  import { DesignSystemManager as DesignSystemManager13, CLI_VERSION as CLI_VERSION4 } from "@getcoherent/core";
9719
9772
 
9720
9773
  // src/utils/migrations.ts
@@ -9883,20 +9936,20 @@ var EXPECTED_CSS_VARS = [
9883
9936
  "--sidebar-ring"
9884
9937
  ];
9885
9938
  function checkMissingCssVars(projectRoot) {
9886
- const globalsPath = join15(projectRoot, "app", "globals.css");
9887
- if (!existsSync19(globalsPath)) return [];
9939
+ const globalsPath = join14(projectRoot, "app", "globals.css");
9940
+ if (!existsSync18(globalsPath)) return [];
9888
9941
  try {
9889
- const content = readFileSync13(globalsPath, "utf-8");
9942
+ const content = readFileSync12(globalsPath, "utf-8");
9890
9943
  return EXPECTED_CSS_VARS.filter((v) => !content.includes(v));
9891
9944
  } catch {
9892
9945
  return [];
9893
9946
  }
9894
9947
  }
9895
9948
  function patchGlobalsCss(projectRoot, missingVars) {
9896
- const globalsPath = join15(projectRoot, "app", "globals.css");
9897
- if (!existsSync19(globalsPath) || missingVars.length === 0) return;
9898
- const { writeFileSync: writeFileSync12 } = __require("fs");
9899
- let content = readFileSync13(globalsPath, "utf-8");
9949
+ const globalsPath = join14(projectRoot, "app", "globals.css");
9950
+ if (!existsSync18(globalsPath) || missingVars.length === 0) return;
9951
+ const { writeFileSync: writeFileSync11 } = __require("fs");
9952
+ let content = readFileSync12(globalsPath, "utf-8");
9900
9953
  const defaultValues = {
9901
9954
  "--chart-1": "220 70% 50%",
9902
9955
  "--chart-2": "160 60% 45%",
@@ -9924,7 +9977,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
9924
9977
  const lightSectionEnd = content.indexOf("}");
9925
9978
  if (lightSectionEnd > 0) {
9926
9979
  content = content.slice(0, lightSectionEnd) + "\n" + injection + "\n" + content.slice(lightSectionEnd);
9927
- writeFileSync12(globalsPath, content, "utf-8");
9980
+ writeFileSync11(globalsPath, content, "utf-8");
9928
9981
  }
9929
9982
  }
9930
9983
 
@@ -9974,26 +10027,26 @@ async function undoCommand(options) {
9974
10027
  // src/commands/sync.ts
9975
10028
  import chalk27 from "chalk";
9976
10029
  import ora9 from "ora";
9977
- import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
9978
- import { join as join16, relative as relative6, dirname as dirname7 } from "path";
10030
+ import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
10031
+ import { join as join15, relative as relative6, dirname as dirname7 } from "path";
9979
10032
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
9980
10033
  import { DesignSystemManager as DesignSystemManager14 } from "@getcoherent/core";
9981
10034
  import { loadManifest as loadManifest12, saveManifest as saveManifest6, findSharedComponent } from "@getcoherent/core";
9982
10035
  function extractTokensFromProject(projectRoot) {
9983
10036
  const lightColors = {};
9984
10037
  const darkColors = {};
9985
- const globalsPath = join16(projectRoot, "app", "globals.css");
9986
- if (existsSync20(globalsPath)) {
9987
- const css = readFileSync14(globalsPath, "utf-8");
10038
+ const globalsPath = join15(projectRoot, "app", "globals.css");
10039
+ if (existsSync19(globalsPath)) {
10040
+ const css = readFileSync13(globalsPath, "utf-8");
9988
10041
  const rootMatch = css.match(/:root\s*\{([^}]+)\}/s);
9989
10042
  if (rootMatch) parseVarsInto(rootMatch[1], lightColors);
9990
10043
  const darkMatch = css.match(/\.dark\s*\{([^}]+)\}/s);
9991
10044
  if (darkMatch) parseVarsInto(darkMatch[1], darkColors);
9992
10045
  }
9993
- const layoutPath = join16(projectRoot, "app", "layout.tsx");
10046
+ const layoutPath = join15(projectRoot, "app", "layout.tsx");
9994
10047
  let layoutCode = "";
9995
- if (existsSync20(layoutPath)) {
9996
- layoutCode = readFileSync14(layoutPath, "utf-8");
10048
+ if (existsSync19(layoutPath)) {
10049
+ layoutCode = readFileSync13(layoutPath, "utf-8");
9997
10050
  const rootInline = layoutCode.match(/:root\s*\{([^}]+)\}/s);
9998
10051
  if (rootInline && Object.keys(lightColors).length === 0) {
9999
10052
  parseVarsInto(rootInline[1], lightColors);
@@ -10011,7 +10064,7 @@ function extractTokensFromProject(projectRoot) {
10011
10064
  defaultMode = "dark";
10012
10065
  }
10013
10066
  let radius;
10014
- const allCss = [existsSync20(globalsPath) ? readFileSync14(globalsPath, "utf-8") : "", layoutCode].join("\n");
10067
+ const allCss = [existsSync19(globalsPath) ? readFileSync13(globalsPath, "utf-8") : "", layoutCode].join("\n");
10015
10068
  const radiusMatch = allCss.match(/--radius:\s*([^;]+);/);
10016
10069
  if (radiusMatch) radius = radiusMatch[1].trim();
10017
10070
  return {
@@ -10034,8 +10087,8 @@ function parseVarsInto(block, target) {
10034
10087
  }
10035
10088
  async function detectCustomComponents(projectRoot, allPageCode) {
10036
10089
  const results = [];
10037
- const componentsDir = join16(projectRoot, "components");
10038
- if (!existsSync20(componentsDir)) return results;
10090
+ const componentsDir = join15(projectRoot, "components");
10091
+ if (!existsSync19(componentsDir)) return results;
10039
10092
  const files = [];
10040
10093
  await walkForTsx(componentsDir, files, ["ui"]);
10041
10094
  const fileResults = await Promise.all(
@@ -10062,7 +10115,7 @@ async function walkForTsx(dir, files, skipDirs) {
10062
10115
  return;
10063
10116
  }
10064
10117
  for (const e of entries) {
10065
- const full = join16(dir, e.name);
10118
+ const full = join15(dir, e.name);
10066
10119
  if (e.isDirectory()) {
10067
10120
  if (skipDirs.includes(e.name) || e.name.startsWith(".")) continue;
10068
10121
  await walkForTsx(full, files, skipDirs);
@@ -10136,7 +10189,7 @@ async function discoverPages(appDir) {
10136
10189
  return;
10137
10190
  }
10138
10191
  for (const entry of entries) {
10139
- const full = join16(dir, entry.name);
10192
+ const full = join15(dir, entry.name);
10140
10193
  if (entry.isDirectory()) {
10141
10194
  if (["design-system", "api", "_not-found"].includes(entry.name)) continue;
10142
10195
  if (entry.name.startsWith(".")) continue;
@@ -10225,8 +10278,8 @@ async function syncCommand(options = {}) {
10225
10278
  if (dryRun) console.log(chalk27.yellow(" [dry-run] No files will be written\n"));
10226
10279
  const spinner = ora9("Scanning project files...").start();
10227
10280
  try {
10228
- const appDir = join16(project.root, "app");
10229
- if (!existsSync20(appDir)) {
10281
+ const appDir = join15(project.root, "app");
10282
+ if (!existsSync19(appDir)) {
10230
10283
  spinner.fail("No app/ directory found");
10231
10284
  process.exit(1);
10232
10285
  }
@@ -10456,53 +10509,53 @@ async function syncCommand(options = {}) {
10456
10509
  // src/commands/migrate.ts
10457
10510
  import chalk28 from "chalk";
10458
10511
  import ora10 from "ora";
10459
- import { existsSync as existsSync21, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync15, readdirSync as readdirSync9 } from "fs";
10460
- import { join as join17 } from "path";
10512
+ import { existsSync as existsSync20, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync9, readFileSync as readFileSync14, readdirSync as readdirSync9 } from "fs";
10513
+ import { join as join16 } from "path";
10461
10514
  function backupDir(projectRoot) {
10462
10515
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
10463
- return join17(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10516
+ return join16(projectRoot, ".coherent", "backups", `pre-migrate-${ts}`);
10464
10517
  }
10465
10518
  function guardPath(projectRoot) {
10466
- return join17(projectRoot, ".coherent", "migration-in-progress");
10519
+ return join16(projectRoot, ".coherent", "migration-in-progress");
10467
10520
  }
10468
10521
  function createBackup2(projectRoot) {
10469
- const uiDir = join17(projectRoot, "components", "ui");
10522
+ const uiDir = join16(projectRoot, "components", "ui");
10470
10523
  const dest = backupDir(projectRoot);
10471
10524
  mkdirSync8(dest, { recursive: true });
10472
- if (existsSync21(uiDir)) {
10473
- cpSync(uiDir, join17(dest, "components-ui"), { recursive: true });
10525
+ if (existsSync20(uiDir)) {
10526
+ cpSync(uiDir, join16(dest, "components-ui"), { recursive: true });
10474
10527
  }
10475
- const configPath = join17(projectRoot, "design-system.config.ts");
10476
- if (existsSync21(configPath)) {
10477
- cpSync(configPath, join17(dest, "design-system.config.ts"));
10528
+ const configPath = join16(projectRoot, "design-system.config.ts");
10529
+ if (existsSync20(configPath)) {
10530
+ cpSync(configPath, join16(dest, "design-system.config.ts"));
10478
10531
  }
10479
10532
  return dest;
10480
10533
  }
10481
10534
  function setGuard(projectRoot, backupPath) {
10482
10535
  const guard = guardPath(projectRoot);
10483
- mkdirSync8(join17(projectRoot, ".coherent"), { recursive: true });
10484
- writeFileSync10(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10536
+ mkdirSync8(join16(projectRoot, ".coherent"), { recursive: true });
10537
+ writeFileSync9(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10485
10538
  }
10486
10539
  function clearGuard(projectRoot) {
10487
10540
  const guard = guardPath(projectRoot);
10488
- if (existsSync21(guard)) rmSync6(guard);
10541
+ if (existsSync20(guard)) rmSync6(guard);
10489
10542
  }
10490
10543
  function rollback(projectRoot) {
10491
10544
  const guard = guardPath(projectRoot);
10492
- if (!existsSync21(guard)) return false;
10545
+ if (!existsSync20(guard)) return false;
10493
10546
  try {
10494
- const data = JSON.parse(readFileSync15(guard, "utf-8"));
10547
+ const data = JSON.parse(readFileSync14(guard, "utf-8"));
10495
10548
  const backup = data.backup;
10496
- if (!existsSync21(backup)) return false;
10497
- const uiBackup = join17(backup, "components-ui");
10498
- const uiDir = join17(projectRoot, "components", "ui");
10499
- if (existsSync21(uiBackup)) {
10500
- if (existsSync21(uiDir)) rmSync6(uiDir, { recursive: true });
10549
+ if (!existsSync20(backup)) return false;
10550
+ const uiBackup = join16(backup, "components-ui");
10551
+ const uiDir = join16(projectRoot, "components", "ui");
10552
+ if (existsSync20(uiBackup)) {
10553
+ if (existsSync20(uiDir)) rmSync6(uiDir, { recursive: true });
10501
10554
  cpSync(uiBackup, uiDir, { recursive: true });
10502
10555
  }
10503
- const configBackup = join17(backup, "design-system.config.ts");
10504
- const configDest = join17(projectRoot, "design-system.config.ts");
10505
- if (existsSync21(configBackup)) {
10556
+ const configBackup = join16(backup, "design-system.config.ts");
10557
+ const configDest = join16(projectRoot, "design-system.config.ts");
10558
+ if (existsSync20(configBackup)) {
10506
10559
  cpSync(configBackup, configDest);
10507
10560
  }
10508
10561
  clearGuard(projectRoot);
@@ -10530,13 +10583,13 @@ async function migrateAction(options) {
10530
10583
  return;
10531
10584
  }
10532
10585
  const guard = guardPath(projectRoot);
10533
- if (existsSync21(guard)) {
10586
+ if (existsSync20(guard)) {
10534
10587
  console.log(chalk28.yellow("A migration is already in progress."));
10535
10588
  console.log(chalk28.dim("Run `coherent migrate --rollback` to undo, or delete .coherent/migration-in-progress"));
10536
10589
  return;
10537
10590
  }
10538
- const uiDir = join17(projectRoot, "components", "ui");
10539
- if (!existsSync21(uiDir)) {
10591
+ const uiDir = join16(projectRoot, "components", "ui");
10592
+ if (!existsSync20(uiDir)) {
10540
10593
  console.log(chalk28.yellow("No components/ui directory found. Nothing to migrate."));
10541
10594
  return;
10542
10595
  }
@@ -10562,8 +10615,8 @@ Found ${migratable.length} component(s) to migrate:`));
10562
10615
  setGuard(projectRoot, backup);
10563
10616
  try {
10564
10617
  for (const id of migratable) {
10565
- const filePath = join17(uiDir, `${id}.tsx`);
10566
- if (existsSync21(filePath)) rmSync6(filePath);
10618
+ const filePath = join16(uiDir, `${id}.tsx`);
10619
+ if (existsSync20(filePath)) rmSync6(filePath);
10567
10620
  }
10568
10621
  const results = await provider.installBatch(migratable, projectRoot, { force: true });
10569
10622
  let migrated = 0;
@@ -10585,20 +10638,20 @@ Found ${migratable.length} component(s) to migrate:`));
10585
10638
  }
10586
10639
 
10587
10640
  // src/utils/update-notifier.ts
10588
- import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
10589
- import { join as join18 } from "path";
10641
+ import { existsSync as existsSync21, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "fs";
10642
+ import { join as join17 } from "path";
10590
10643
  import { homedir } from "os";
10591
10644
  import chalk29 from "chalk";
10592
10645
  import { CLI_VERSION as CLI_VERSION5 } from "@getcoherent/core";
10593
10646
  var DEBUG5 = process.env.COHERENT_DEBUG === "1";
10594
10647
  var PACKAGE_NAME = "@getcoherent/cli";
10595
- var CACHE_DIR = join18(homedir(), ".coherent");
10596
- var CACHE_FILE = join18(CACHE_DIR, "update-check.json");
10648
+ var CACHE_DIR = join17(homedir(), ".coherent");
10649
+ var CACHE_FILE = join17(CACHE_DIR, "update-check.json");
10597
10650
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10598
10651
  function readCache() {
10599
10652
  try {
10600
- if (!existsSync22(CACHE_FILE)) return null;
10601
- const raw = readFileSync16(CACHE_FILE, "utf-8");
10653
+ if (!existsSync21(CACHE_FILE)) return null;
10654
+ const raw = readFileSync15(CACHE_FILE, "utf-8");
10602
10655
  return JSON.parse(raw);
10603
10656
  } catch (e) {
10604
10657
  if (DEBUG5) console.error("Failed to read update cache:", e);
@@ -10607,8 +10660,8 @@ function readCache() {
10607
10660
  }
10608
10661
  function writeCache(data) {
10609
10662
  try {
10610
- if (!existsSync22(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10611
- writeFileSync11(CACHE_FILE, JSON.stringify(data), "utf-8");
10663
+ if (!existsSync21(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10664
+ writeFileSync10(CACHE_FILE, JSON.stringify(data), "utf-8");
10612
10665
  } catch (e) {
10613
10666
  if (DEBUG5) console.error("Failed to write update cache:", e);
10614
10667
  }
@@ -0,0 +1,98 @@
1
+ import {
2
+ runTscCheck
3
+ } from "./chunk-XPBD3L7V.js";
4
+ import {
5
+ safeWrite
6
+ } from "./chunk-U6M76BKY.js";
7
+ import "./chunk-3RG5ZIWI.js";
8
+
9
+ // src/utils/tsc-ai-fix.ts
10
+ import { readFileSync } from "fs";
11
+ import { resolve } from "path";
12
+ var MAX_AI_FILES = 5;
13
+ async function applyAiFixes(errors, projectRoot, backups, aiProvider) {
14
+ if (!aiProvider?.editPageCode) {
15
+ return { fixed: [], failed: errors };
16
+ }
17
+ const fileErrors = /* @__PURE__ */ new Map();
18
+ for (const err of errors) {
19
+ const list = fileErrors.get(err.file) || [];
20
+ list.push(err);
21
+ fileErrors.set(err.file, list);
22
+ }
23
+ const fixed = [];
24
+ const failed = [];
25
+ let filesProcessed = 0;
26
+ for (const [file, errs] of fileErrors) {
27
+ filesProcessed++;
28
+ if (filesProcessed > MAX_AI_FILES) {
29
+ failed.push(...errs);
30
+ continue;
31
+ }
32
+ const absPath = resolve(projectRoot, file);
33
+ let code;
34
+ try {
35
+ code = readFileSync(absPath, "utf-8");
36
+ } catch {
37
+ failed.push(...errs);
38
+ continue;
39
+ }
40
+ const relatedContext = gatherRelatedContext(errs, projectRoot);
41
+ const errorList = errs.map((e) => `Line ${e.line}: [${e.code}] ${e.message}`).join("\n");
42
+ const instruction = [
43
+ "Fix these TypeScript compilation errors:",
44
+ errorList,
45
+ "",
46
+ relatedContext ? `Reference interfaces (DO NOT modify these):
47
+ ${relatedContext}` : "",
48
+ "",
49
+ "Rules:",
50
+ "- Fix the data/props to match the expected types",
51
+ "- Do NOT change component interfaces or imports from shared components",
52
+ "- Keep all existing functionality intact"
53
+ ].filter(Boolean).join("\n");
54
+ try {
55
+ const fixedCode = await aiProvider.editPageCode(code, instruction, file);
56
+ if (!fixedCode || fixedCode.length < 50) {
57
+ failed.push(...errs);
58
+ continue;
59
+ }
60
+ const { ok } = safeWrite(absPath, fixedCode, projectRoot, backups);
61
+ if (!ok) {
62
+ failed.push(...errs);
63
+ continue;
64
+ }
65
+ const afterErrors = runTscCheck(projectRoot).filter((e) => e.file === file);
66
+ if (afterErrors.length >= errs.length) {
67
+ const original = backups.get(absPath);
68
+ if (original) safeWrite(absPath, original, projectRoot, backups);
69
+ failed.push(...errs);
70
+ } else {
71
+ fixed.push(file);
72
+ if (afterErrors.length > 0) failed.push(...afterErrors);
73
+ }
74
+ } catch {
75
+ failed.push(...errs);
76
+ }
77
+ }
78
+ return { fixed, failed };
79
+ }
80
+ function gatherRelatedContext(errors, projectRoot) {
81
+ const relatedFiles = /* @__PURE__ */ new Set();
82
+ for (const err of errors) {
83
+ for (const f of err.relatedFiles) relatedFiles.add(f);
84
+ }
85
+ const parts = [];
86
+ for (const file of relatedFiles) {
87
+ try {
88
+ const content = readFileSync(resolve(projectRoot, file), "utf-8");
89
+ parts.push(`// --- ${file} ---
90
+ ${content}`);
91
+ } catch {
92
+ }
93
+ }
94
+ return parts.join("\n\n");
95
+ }
96
+ export {
97
+ applyAiFixes
98
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ applyDeterministicFixes,
3
+ fixFieldRename,
4
+ fixMissingEventHandler,
5
+ fixUnionType,
6
+ runTscCheck
7
+ } from "./chunk-XPBD3L7V.js";
8
+ import "./chunk-U6M76BKY.js";
9
+ import "./chunk-3RG5ZIWI.js";
10
+ export {
11
+ applyDeterministicFixes,
12
+ fixFieldRename,
13
+ fixMissingEventHandler,
14
+ fixUnionType,
15
+ runTscCheck
16
+ };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.46",
6
+ "version": "0.6.48",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",