@getcoherent/cli 0.6.43 → 0.6.45

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.
@@ -6,7 +6,7 @@ import {
6
6
  getPageGroup,
7
7
  installPackages,
8
8
  sanitizeMetadataStrings
9
- } from "./chunk-KJRBBLXT.js";
9
+ } from "./chunk-VLBVBF6V.js";
10
10
  import {
11
11
  toKebabCase
12
12
  } from "./chunk-4TLYDTT3.js";
@@ -2147,7 +2147,7 @@ async function regeneratePage(pageId, config, projectRoot) {
2147
2147
  const code = await generator.generate(page, appType);
2148
2148
  const route = page.route || "/";
2149
2149
  const isAuth = isAuthRoute(route) || isAuthRoute(page.name || page.id || "");
2150
- const { loadPlan: loadPlanForPath } = await import("./plan-generator-YOPF773K.js");
2150
+ const { loadPlan: loadPlanForPath } = await import("./plan-generator-PIDLFRWZ.js");
2151
2151
  const planForPath = loadPlanForPath(projectRoot);
2152
2152
  const filePath = routeToFsPath(projectRoot, route, planForPath || isAuth);
2153
2153
  await mkdir3(dirname3(filePath), { recursive: true });
@@ -2336,7 +2336,7 @@ export default function AppLayout({
2336
2336
  {children}
2337
2337
  </main>
2338
2338
  <footer className="border-t px-4 py-3 text-xs text-muted-foreground">
2339
- \\u00A9 ${year} ${name}
2339
+ \xA9 ${year} ${name}
2340
2340
  </footer>
2341
2341
  </SidebarInset>
2342
2342
  </SidebarProvider>
@@ -93,6 +93,15 @@ COMPONENT VARIANT RULES (CRITICAL):
93
93
  CONTENT (zero placeholders):
94
94
  - NEVER: "Lorem ipsum", "Card content", "Description here"
95
95
  - ALWAYS: Real, contextual content. Realistic metric names, values, dates.
96
+
97
+ MOCK/SAMPLE DATA (for demo arrays, fake users, fake tasks, etc.):
98
+ - Dates: ALWAYS ISO 8601 strings in data ("2024-06-15T10:30:00Z").
99
+ Display with date formatting: new Date(item.date).toLocaleDateString() or
100
+ Intl.RelativeTimeFormat, or date-fns if already imported.
101
+ BAD: { createdAt: "2 hours ago" }
102
+ GOOD: { createdAt: "2024-06-15T10:30:00Z" }
103
+ - Images: "/placeholder.svg?height=40&width=40" (Next.js placeholder). Never broken paths.
104
+ - IDs: sequential numbers (1, 2, 3) or short slugs ("proj-1"). Never random UUIDs.
96
105
  `;
97
106
  var DESIGN_QUALITY_COMMON = `
98
107
  ## DESIGN QUALITY \u2014 COMMON
@@ -509,11 +518,17 @@ EMPTY STATES: See the Empty State reference pattern in DESIGN QUALITY \u2014 APP
509
518
  - Filtered empty: "No items match your filters." + reset filters button.
510
519
 
511
520
  DATA FORMATTING:
512
- - Dates: use relative for recent ("2 hours ago", "Yesterday"), absolute for older ("Jan 26, 2026"). Never ISO format in UI.
521
+ - Dates in rendered output: use relative for recent ("2 hours ago"), absolute for older ("Jan 26, 2026"). Never show raw ISO in the UI.
522
+ - Dates in source data (mock arrays, state): ALWAYS store as ISO 8601 strings. Compute display format at render time.
513
523
  - Numbers: use Intl.NumberFormat or toLocaleString(). 1,234 not 1234. Always include separator for 1000+.
514
524
  - Currency: $1,234.56 format. Symbol before number. Two decimal places for amounts.
515
525
  - Percentages: one decimal max. "+12.5%" with sign for changes.
516
526
 
527
+ MOCK DATA IN COMPONENTS:
528
+ - All date/time values in sample data arrays MUST be valid ISO 8601 strings.
529
+ - Render with: new Date(item.date).toLocaleDateString(), Intl.RelativeTimeFormat, or date-fns if imported.
530
+ - NEVER store display strings ("2 hours ago", "Yesterday") in data \u2014 always compute from ISO date.
531
+
517
532
  STATUS INDICATORS (dot + text):
518
533
  - Pattern: <div className="flex items-center gap-2"><div className="size-2 rounded-full bg-emerald-500" /><span className="text-sm">Active</span></div>
519
534
  - Colors: bg-emerald-500 (active/online), bg-destructive (error/offline), bg-yellow-500 (warning), bg-muted-foreground (inactive).
@@ -2,7 +2,7 @@ import {
2
2
  CORE_CONSTRAINTS,
3
3
  getDesignQualityForType,
4
4
  inferPageTypeFromRoute
5
- } from "./chunk-5AHG4NNX.js";
5
+ } from "./chunk-E23FJX2I.js";
6
6
  import {
7
7
  autoFixCode
8
8
  } from "./chunk-NOM47EB4.js";
@@ -12,10 +12,10 @@ import {
12
12
  regeneratePage,
13
13
  scanAndInstallSharedDeps,
14
14
  validateAndFixGeneratedCode
15
- } from "./chunk-662O2QEG.js";
16
- import "./chunk-KJRBBLXT.js";
15
+ } from "./chunk-4I7ATX6G.js";
16
+ import "./chunk-VLBVBF6V.js";
17
17
  import "./chunk-4TLYDTT3.js";
18
- import "./chunk-5AHG4NNX.js";
18
+ import "./chunk-E23FJX2I.js";
19
19
  import "./chunk-NOM47EB4.js";
20
20
  import "./chunk-3RG5ZIWI.js";
21
21
  export {
@@ -18,7 +18,7 @@ import {
18
18
  getDesignQualityForType,
19
19
  inferPageTypeFromRoute,
20
20
  selectContextualRules
21
- } from "./chunk-5AHG4NNX.js";
21
+ } from "./chunk-E23FJX2I.js";
22
22
  import "./chunk-3RG5ZIWI.js";
23
23
  export {
24
24
  CORE_CONSTRAINTS,
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  warnIfVolatile,
35
35
  warnInlineDuplicates,
36
36
  writeFile
37
- } from "./chunk-662O2QEG.js";
37
+ } from "./chunk-4I7ATX6G.js";
38
38
  import {
39
39
  COHERENT_REQUIRED_PACKAGES,
40
40
  ensureUseClientIfNeeded,
@@ -52,7 +52,7 @@ import {
52
52
  sanitizeMetadataStrings,
53
53
  savePlan,
54
54
  updateArchitecturePlan
55
- } from "./chunk-KJRBBLXT.js";
55
+ } from "./chunk-VLBVBF6V.js";
56
56
  import {
57
57
  toKebabCase,
58
58
  toTitleCase
@@ -70,7 +70,7 @@ import {
70
70
  getDesignQualityForType,
71
71
  inferPageTypeFromRoute,
72
72
  selectContextualRules
73
- } from "./chunk-5AHG4NNX.js";
73
+ } from "./chunk-E23FJX2I.js";
74
74
  import {
75
75
  fixGlobalsCss,
76
76
  generateV4GlobalsCss,
@@ -3896,7 +3896,7 @@ async function splitGeneratePages(spinner, message, modCtx, provider, parseOpts)
3896
3896
  if (plan && plan.sharedComponents.length > 0) {
3897
3897
  spinner.start(`Phase 4.5/6 \u2014 Generating ${plan.sharedComponents.length} shared components from plan...`);
3898
3898
  try {
3899
- const { generateSharedComponentsFromPlan } = await import("./plan-generator-YOPF773K.js");
3899
+ const { generateSharedComponentsFromPlan } = await import("./plan-generator-PIDLFRWZ.js");
3900
3900
  const generated = await generateSharedComponentsFromPlan(
3901
3901
  plan,
3902
3902
  styleContext,
@@ -6224,7 +6224,7 @@ Return JSON: { "requests": [{ "type": "add-page", "changes": { "name": "${compon
6224
6224
  }
6225
6225
  try {
6226
6226
  const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
6227
- const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-EIP2XM7T.js");
6227
+ const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-HGNEY3W3.js");
6228
6228
  const manifest2 = await loadManifest7(projectRoot);
6229
6229
  const reuseplan = projectRoot ? loadPlan(projectRoot) : null;
6230
6230
  if (manifest2.shared.length > 0) {
@@ -8214,7 +8214,7 @@ async function fixCommand(opts = {}) {
8214
8214
  }
8215
8215
  }
8216
8216
  const appDir = resolve8(projectRoot, "app");
8217
- const allTsxFiles = listTsxFiles(appDir);
8217
+ let allTsxFiles = listTsxFiles(appDir);
8218
8218
  const componentsTsxFiles = listTsxFiles(resolve8(projectRoot, "components"));
8219
8219
  const allComponentIds = /* @__PURE__ */ new Set();
8220
8220
  for (const file of [...allTsxFiles, ...componentsTsxFiles]) {
@@ -8377,25 +8377,29 @@ async function fixCommand(opts = {}) {
8377
8377
  }
8378
8378
  }
8379
8379
  }
8380
- const userTsxFiles = allTsxFiles.filter((f) => !f.includes("/design-system/"));
8380
+ let userTsxFiles = allTsxFiles.filter((f) => !f.includes("/design-system/"));
8381
8381
  let syntaxFixed = 0;
8382
8382
  for (const file of userTsxFiles) {
8383
- const content = readFileSync11(file, "utf-8");
8384
- const fixed = fixUnescapedLtInJsx(
8385
- fixEscapedClosingQuotes(sanitizeMetadataStrings(ensureUseClientIfNeeded(content)))
8386
- );
8387
- if (fixed !== content) {
8388
- if (!dryRun) {
8389
- const result = safeWrite(file, fixed, projectRoot, backups);
8390
- if (result.ok) {
8391
- modifiedFiles.push(file);
8392
- syntaxFixed++;
8383
+ try {
8384
+ const content = readFileSync11(file, "utf-8");
8385
+ const fixed = fixUnescapedLtInJsx(
8386
+ fixEscapedClosingQuotes(sanitizeMetadataStrings(ensureUseClientIfNeeded(content)))
8387
+ );
8388
+ if (fixed !== content) {
8389
+ if (!dryRun) {
8390
+ const result = safeWrite(file, fixed, projectRoot, backups);
8391
+ if (result.ok) {
8392
+ modifiedFiles.push(file);
8393
+ syntaxFixed++;
8394
+ } else {
8395
+ console.log(chalk15.yellow(` \u26A0 Syntax fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8396
+ }
8393
8397
  } else {
8394
- console.log(chalk15.yellow(` \u26A0 Syntax fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8398
+ syntaxFixed++;
8395
8399
  }
8396
- } else {
8397
- syntaxFixed++;
8398
8400
  }
8401
+ } catch (err) {
8402
+ remaining.push(`${relative5(projectRoot, file)}: syntax fix error \u2014 ${err instanceof Error ? err.message : "unknown"}`);
8399
8403
  }
8400
8404
  }
8401
8405
  if (syntaxFixed > 0) {
@@ -8404,8 +8408,8 @@ async function fixCommand(opts = {}) {
8404
8408
  console.log(chalk15.green(` \u2714 ${verb} syntax: ${syntaxFixed} file(s) (use client, metadata, quotes)`));
8405
8409
  }
8406
8410
  try {
8407
- const { loadPlan: loadPlan2 } = await import("./plan-generator-YOPF773K.js");
8408
- const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-CV54KQFF.js");
8411
+ const { loadPlan: loadPlan2 } = await import("./plan-generator-PIDLFRWZ.js");
8412
+ const { ensurePlanGroupLayouts: ensurePlanGroupLayouts2 } = await import("./code-generator-YSGVHVNN.js");
8409
8413
  const plan = loadPlan2(projectRoot);
8410
8414
  if (plan) {
8411
8415
  if (!dsm) {
@@ -8459,7 +8463,7 @@ async function fixCommand(opts = {}) {
8459
8463
  const publicExists = existsSync15(publicLayoutPath);
8460
8464
  const needsPublicLayout = !publicExists || !readFileSync11(publicLayoutPath, "utf-8").includes("<Header");
8461
8465
  if (needsPublicLayout) {
8462
- const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-CV54KQFF.js");
8466
+ const { buildPublicLayoutCodeForSidebar } = await import("./code-generator-YSGVHVNN.js");
8463
8467
  mkdirSync7(resolve8(projectRoot, "app", "(public)"), { recursive: true });
8464
8468
  const publicResult = safeWrite(publicLayoutPath, buildPublicLayoutCodeForSidebar(), projectRoot, backups);
8465
8469
  if (publicResult.ok) {
@@ -8508,7 +8512,7 @@ async function fixCommand(opts = {}) {
8508
8512
  }
8509
8513
  const themeTogglePath = resolve8(projectRoot, "components", "shared", "theme-toggle.tsx");
8510
8514
  if (!existsSync15(themeTogglePath)) {
8511
- const { generateThemeToggleCode } = await import("./code-generator-CV54KQFF.js");
8515
+ const { generateThemeToggleCode } = await import("./code-generator-YSGVHVNN.js");
8512
8516
  mkdirSync7(resolve8(projectRoot, "components", "shared"), { recursive: true });
8513
8517
  const themeResult = safeWrite(themeTogglePath, generateThemeToggleCode(), projectRoot, backups);
8514
8518
  if (themeResult.ok) {
@@ -8529,7 +8533,7 @@ async function fixCommand(opts = {}) {
8529
8533
  const isMinimal = appLayoutCode.length < 500 && !appLayoutCode.includes("Header") && !appLayoutCode.includes("Footer") && !appLayoutCode.includes("Sidebar") && !appLayoutCode.includes("SidebarProvider") && !appLayoutCode.includes("SidebarTrigger") && !appLayoutCode.includes("Sheet");
8530
8534
  const navType = dsm.getConfig().navigation?.type || "header";
8531
8535
  if (isMinimal && navType !== "none") {
8532
- const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-CV54KQFF.js");
8536
+ const { buildAppLayoutCode, buildGroupLayoutCode } = await import("./code-generator-YSGVHVNN.js");
8533
8537
  const isSidebar = navType === "sidebar" || navType === "both";
8534
8538
  const newLayout = isSidebar ? buildAppLayoutCode(navType, dsm.getConfig().name) : buildGroupLayoutCode("header", dsm.getConfig().pages?.map((p) => p.name) || [], dsm.getConfig().name);
8535
8539
  if (!dryRun) {
@@ -8544,26 +8548,34 @@ async function fixCommand(opts = {}) {
8544
8548
  }
8545
8549
  }
8546
8550
  }
8551
+ allTsxFiles = listTsxFiles(appDir);
8552
+ userTsxFiles = allTsxFiles.filter((f) => !f.includes("/design-system/"));
8553
+ const sharedTsxFiles = listTsxFiles(resolve8(projectRoot, "components", "shared"));
8554
+ const allValidationFiles = [...userTsxFiles, ...sharedTsxFiles];
8547
8555
  if (!skipQuality) {
8548
8556
  let qualityFixCount = 0;
8549
8557
  const qualityFixDetails = [];
8550
- for (const file of userTsxFiles) {
8551
- const content = readFileSync11(file, "utf-8");
8552
- const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8553
- if (autoFixed !== content) {
8554
- if (!dryRun) {
8555
- const qResult = safeWrite(file, autoFixed, projectRoot, backups);
8556
- if (qResult.ok) {
8557
- modifiedFiles.push(file);
8558
+ for (const file of allValidationFiles) {
8559
+ try {
8560
+ const content = readFileSync11(file, "utf-8");
8561
+ const { code: autoFixed, fixes: fileFixes } = await autoFixCode(content);
8562
+ if (autoFixed !== content) {
8563
+ if (!dryRun) {
8564
+ const qResult = safeWrite(file, autoFixed, projectRoot, backups);
8565
+ if (qResult.ok) {
8566
+ modifiedFiles.push(file);
8567
+ qualityFixCount++;
8568
+ qualityFixDetails.push(...fileFixes);
8569
+ } else {
8570
+ console.log(chalk15.yellow(` \u26A0 Quality fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8571
+ }
8572
+ } else {
8558
8573
  qualityFixCount++;
8559
8574
  qualityFixDetails.push(...fileFixes);
8560
- } else {
8561
- console.log(chalk15.yellow(` \u26A0 Quality fix rolled back for ${relative5(projectRoot, file)} (parse error)`));
8562
8575
  }
8563
- } else {
8564
- qualityFixCount++;
8565
- qualityFixDetails.push(...fileFixes);
8566
8576
  }
8577
+ } catch (err) {
8578
+ remaining.push(`${relative5(projectRoot, file)}: quality fix error \u2014 ${err instanceof Error ? err.message : "unknown"}`);
8567
8579
  }
8568
8580
  }
8569
8581
  if (qualityFixCount > 0) {
@@ -8573,6 +8585,37 @@ async function fixCommand(opts = {}) {
8573
8585
  console.log(chalk15.green(` \u2714 ${verb} ${uniqueFixes.length} quality issue type(s): ${uniqueFixes.join(", ")}`));
8574
8586
  }
8575
8587
  }
8588
+ try {
8589
+ const { validateMockData, applyMockDataFixes } = await import("./mock-data-validator-JEWUOMFY.js");
8590
+ let mockFixed = 0;
8591
+ for (const file of allValidationFiles) {
8592
+ try {
8593
+ const content = readFileSync11(file, "utf-8");
8594
+ const mockIssues = validateMockData(content);
8595
+ if (mockIssues.length > 0) {
8596
+ const fixed = applyMockDataFixes(content, mockIssues);
8597
+ if (fixed !== content && !dryRun) {
8598
+ const result = safeWrite(file, fixed, projectRoot, backups);
8599
+ if (result.ok) {
8600
+ mockFixed++;
8601
+ modifiedFiles.push(file);
8602
+ }
8603
+ } else if (dryRun) {
8604
+ mockFixed++;
8605
+ }
8606
+ }
8607
+ } catch (fileErr) {
8608
+ remaining.push(`${relative5(projectRoot, file)}: mock data fix error \u2014 ${fileErr instanceof Error ? fileErr.message : "unknown"}`);
8609
+ }
8610
+ }
8611
+ if (mockFixed > 0) {
8612
+ const verb = dryRun ? "Would fix" : "Fixed";
8613
+ fixes.push(`${verb} mock data in ${mockFixed} file(s)`);
8614
+ console.log(chalk15.green(` \u2714 ${verb} mock data: ${mockFixed} file(s)`));
8615
+ }
8616
+ } catch (importErr) {
8617
+ console.log(chalk15.dim(" \u2298 mock-data-validator not available, skipping"));
8618
+ }
8576
8619
  for (const file of modifiedFiles) {
8577
8620
  if (!backups.has(file)) continue;
8578
8621
  const before = backups.get(file);
@@ -8587,29 +8630,34 @@ async function fixCommand(opts = {}) {
8587
8630
  let totalErrors = 0;
8588
8631
  let totalWarnings = 0;
8589
8632
  const fileIssues = [];
8590
- for (const file of allTsxFiles) {
8591
- const code = dryRun ? readFileSync11(file, "utf-8") : readFileSync11(file, "utf-8");
8592
- const relativePath = file.replace(projectRoot + "/", "");
8593
- const baseName = file.split("/").pop() || "";
8594
- const isAuthPage = relativePath.includes("(auth)");
8595
- const isNonPageFile = baseName === "layout.tsx" || baseName === "AppNav.tsx" || baseName === "not-found.tsx" || baseName === "ShowWhenNotAuthRoute.tsx";
8596
- const isHomePage = relativePath === "app/page.tsx";
8597
- const isDesignSystem = relativePath.includes("design-system");
8598
- if (isDesignSystem) continue;
8599
- const issues = validatePageQuality(code);
8600
- const suppressH1 = isNonPageFile || isAuthPage;
8601
- const filteredIssues = issues.filter((i) => {
8602
- if (suppressH1 && (i.type === "NO_H1" || i.type === "MULTIPLE_H1")) return false;
8603
- if (isHomePage && i.type === "NO_EMPTY_STATE") return false;
8604
- return true;
8605
- });
8606
- if (filteredIssues.length === 0) continue;
8607
- const errors = filteredIssues.filter((i) => i.severity === "error").length;
8608
- const warnings = filteredIssues.filter((i) => i.severity === "warning").length;
8609
- totalErrors += errors;
8610
- totalWarnings += warnings;
8611
- const report = formatIssues(filteredIssues);
8612
- fileIssues.push({ path: relativePath, report });
8633
+ for (const file of allValidationFiles) {
8634
+ try {
8635
+ const code = readFileSync11(file, "utf-8");
8636
+ const relativePath = file.replace(projectRoot + "/", "");
8637
+ const baseName = file.split("/").pop() || "";
8638
+ const isAuthPage = relativePath.includes("(auth)");
8639
+ const isSharedComponent = relativePath.includes("components/shared/");
8640
+ const isNonPageFile = baseName === "layout.tsx" || baseName === "AppNav.tsx" || baseName === "not-found.tsx" || baseName === "ShowWhenNotAuthRoute.tsx";
8641
+ const isHomePage = relativePath === "app/page.tsx";
8642
+ const isDesignSystem = relativePath.includes("design-system");
8643
+ if (isDesignSystem) continue;
8644
+ const issues = validatePageQuality(code);
8645
+ const suppressH1 = isNonPageFile || isAuthPage || isSharedComponent;
8646
+ const filteredIssues = issues.filter((i) => {
8647
+ if (suppressH1 && (i.type === "NO_H1" || i.type === "MULTIPLE_H1")) return false;
8648
+ if (isHomePage && i.type === "NO_EMPTY_STATE") return false;
8649
+ return true;
8650
+ });
8651
+ if (filteredIssues.length === 0) continue;
8652
+ const errors = filteredIssues.filter((i) => i.severity === "error").length;
8653
+ const warnings = filteredIssues.filter((i) => i.severity === "warning").length;
8654
+ totalErrors += errors;
8655
+ totalWarnings += warnings;
8656
+ const report = formatIssues(filteredIssues);
8657
+ fileIssues.push({ path: relativePath, report });
8658
+ } catch (err) {
8659
+ remaining.push(`${relative5(projectRoot, file)}: validation error \u2014 ${err instanceof Error ? err.message : "unknown"}`);
8660
+ }
8613
8661
  }
8614
8662
  try {
8615
8663
  let manifest = await loadManifest9(project.root);
@@ -8690,6 +8738,29 @@ async function fixCommand(opts = {}) {
8690
8738
  );
8691
8739
  }
8692
8740
  }
8741
+ try {
8742
+ const tsconfigPath = resolve8(projectRoot, "tsconfig.json");
8743
+ if (existsSync15(tsconfigPath)) {
8744
+ const { execSync: execSync2 } = await import("child_process");
8745
+ execSync2("npx tsc --noEmit --pretty 2>&1", {
8746
+ cwd: projectRoot,
8747
+ timeout: 3e4,
8748
+ encoding: "utf-8"
8749
+ });
8750
+ fixes.push("TypeScript compilation clean");
8751
+ console.log(chalk15.green(" \u2714 TypeScript compilation clean"));
8752
+ }
8753
+ } catch (err) {
8754
+ const output = (err.stdout || "") + (err.stderr || "");
8755
+ const errorLines = output.split("\n").filter((l) => l.includes("error TS"));
8756
+ if (errorLines.length > 0) {
8757
+ for (const line of errorLines.slice(0, 10)) {
8758
+ remaining.push(line.trim());
8759
+ }
8760
+ if (errorLines.length > 10) remaining.push(`... and ${errorLines.length - 10} more TypeScript errors`);
8761
+ console.log(chalk15.yellow(` \u26A0 TypeScript: ${errorLines.length} error(s)`));
8762
+ }
8763
+ }
8693
8764
  if (fixes.length === 0 && totalErrors === 0 && totalWarnings === 0 && remaining.length === 0) {
8694
8765
  console.log(chalk15.green("\n \u2705 Everything looks good \u2014 no issues found\n"));
8695
8766
  console.log(chalk15.cyan(" Run: coherent preview\n"));
@@ -8965,7 +9036,7 @@ async function checkCommand(opts = {}) {
8965
9036
  if (!skipShared) {
8966
9037
  try {
8967
9038
  const { validateReuse } = await import("./reuse-validator-XR2ZEYC4.js");
8968
- const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-EIP2XM7T.js");
9039
+ const { inferPageTypeFromRoute: inferPageTypeFromRoute2 } = await import("./design-constraints-HGNEY3W3.js");
8969
9040
  const manifest = await loadManifest10(projectRoot);
8970
9041
  const appDir = resolve9(projectRoot, "app");
8971
9042
  const pageFiles = existsSync16(appDir) ? findTsxFiles(appDir) : [];
@@ -9816,7 +9887,7 @@ function checkMissingCssVars(projectRoot) {
9816
9887
  function patchGlobalsCss(projectRoot, missingVars) {
9817
9888
  const globalsPath = join15(projectRoot, "app", "globals.css");
9818
9889
  if (!existsSync19(globalsPath) || missingVars.length === 0) return;
9819
- const { writeFileSync: writeFileSync13 } = __require("fs");
9890
+ const { writeFileSync: writeFileSync12 } = __require("fs");
9820
9891
  let content = readFileSync13(globalsPath, "utf-8");
9821
9892
  const defaultValues = {
9822
9893
  "--chart-1": "220 70% 50%",
@@ -9845,7 +9916,7 @@ function patchGlobalsCss(projectRoot, missingVars) {
9845
9916
  const lightSectionEnd = content.indexOf("}");
9846
9917
  if (lightSectionEnd > 0) {
9847
9918
  content = content.slice(0, lightSectionEnd) + "\n" + injection + "\n" + content.slice(lightSectionEnd);
9848
- writeFileSync13(globalsPath, content, "utf-8");
9919
+ writeFileSync12(globalsPath, content, "utf-8");
9849
9920
  }
9850
9921
  }
9851
9922
 
@@ -10377,7 +10448,7 @@ async function syncCommand(options = {}) {
10377
10448
  // src/commands/migrate.ts
10378
10449
  import chalk28 from "chalk";
10379
10450
  import ora10 from "ora";
10380
- import { existsSync as existsSync21, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync11, readFileSync as readFileSync15, readdirSync as readdirSync9 } from "fs";
10451
+ import { existsSync as existsSync21, mkdirSync as mkdirSync8, cpSync, rmSync as rmSync6, writeFileSync as writeFileSync10, readFileSync as readFileSync15, readdirSync as readdirSync9 } from "fs";
10381
10452
  import { join as join17 } from "path";
10382
10453
  function backupDir(projectRoot) {
10383
10454
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
@@ -10402,7 +10473,7 @@ function createBackup2(projectRoot) {
10402
10473
  function setGuard(projectRoot, backupPath) {
10403
10474
  const guard = guardPath(projectRoot);
10404
10475
  mkdirSync8(join17(projectRoot, ".coherent"), { recursive: true });
10405
- writeFileSync11(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10476
+ writeFileSync10(guard, JSON.stringify({ backup: backupPath, startedAt: (/* @__PURE__ */ new Date()).toISOString() }));
10406
10477
  }
10407
10478
  function clearGuard(projectRoot) {
10408
10479
  const guard = guardPath(projectRoot);
@@ -10506,7 +10577,7 @@ Found ${migratable.length} component(s) to migrate:`));
10506
10577
  }
10507
10578
 
10508
10579
  // src/utils/update-notifier.ts
10509
- import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
10580
+ import { existsSync as existsSync22, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
10510
10581
  import { join as join18 } from "path";
10511
10582
  import { homedir } from "os";
10512
10583
  import chalk29 from "chalk";
@@ -10529,7 +10600,7 @@ function readCache() {
10529
10600
  function writeCache(data) {
10530
10601
  try {
10531
10602
  if (!existsSync22(CACHE_DIR)) mkdirSync9(CACHE_DIR, { recursive: true });
10532
- writeFileSync12(CACHE_FILE, JSON.stringify(data), "utf-8");
10603
+ writeFileSync11(CACHE_FILE, JSON.stringify(data), "utf-8");
10533
10604
  } catch (e) {
10534
10605
  if (DEBUG5) console.error("Failed to write update cache:", e);
10535
10606
  }
@@ -0,0 +1,70 @@
1
+ import "./chunk-3RG5ZIWI.js";
2
+
3
+ // src/utils/mock-data-validator.ts
4
+ function generateRecentIsoDate(offsetHours = 0) {
5
+ const d = /* @__PURE__ */ new Date();
6
+ d.setHours(d.getHours() - offsetHours);
7
+ return d.toISOString();
8
+ }
9
+ function getLineAndCol(code, index) {
10
+ const lines = code.slice(0, index).split("\n");
11
+ return { line: lines.length, column: (lines[lines.length - 1]?.length ?? 0) + 1 };
12
+ }
13
+ function validateMockData(code) {
14
+ const issues = [];
15
+ let offset = 0;
16
+ const dateCtorRe = /new Date\(["']([^"']+)["']\)/g;
17
+ let m;
18
+ while ((m = dateCtorRe.exec(code)) !== null) {
19
+ const dateStr = m[1];
20
+ if (isNaN(new Date(dateStr).getTime())) {
21
+ const { line, column } = getLineAndCol(code, m.index);
22
+ const valueStart = m.index + m[0].indexOf(dateStr);
23
+ const valueEnd = valueStart + dateStr.length;
24
+ issues.push({
25
+ line,
26
+ column,
27
+ message: `Invalid Date: new Date("${dateStr}") will throw at runtime`,
28
+ fixable: true,
29
+ replacement: {
30
+ start: valueStart,
31
+ end: valueEnd,
32
+ text: generateRecentIsoDate(offset++)
33
+ }
34
+ });
35
+ }
36
+ }
37
+ const mockFieldRe = /(?:timestamp|date|createdAt|updatedAt|time|startDate|endDate|dueDate)\s*:\s*["']((?:\d+\s+(?:hours?|minutes?|days?|weeks?|months?|years?)\s+ago)|yesterday|today|last\s+\w+|just\s+now|recently)["']/gi;
38
+ while ((m = mockFieldRe.exec(code)) !== null) {
39
+ const dateStr = m[1];
40
+ const { line, column } = getLineAndCol(code, m.index);
41
+ const fullMatch = m[0];
42
+ const valueStart = m.index + fullMatch.indexOf(dateStr);
43
+ const valueEnd = valueStart + dateStr.length;
44
+ issues.push({
45
+ line,
46
+ column,
47
+ message: `Mock data "${dateStr}" is a display string, not a valid Date \u2014 use ISO 8601`,
48
+ fixable: true,
49
+ replacement: {
50
+ start: valueStart,
51
+ end: valueEnd,
52
+ text: generateRecentIsoDate(offset++)
53
+ }
54
+ });
55
+ }
56
+ return issues;
57
+ }
58
+ function applyMockDataFixes(code, issues) {
59
+ const fixable = issues.filter((i) => i.fixable && i.replacement).sort((a, b) => b.replacement.start - a.replacement.start);
60
+ let result = code;
61
+ for (const issue of fixable) {
62
+ const r = issue.replacement;
63
+ result = result.slice(0, r.start) + r.text + result.slice(r.end);
64
+ }
65
+ return result;
66
+ }
67
+ export {
68
+ applyMockDataFixes,
69
+ validateMockData
70
+ };
@@ -11,8 +11,8 @@ import {
11
11
  routeToKey,
12
12
  savePlan,
13
13
  updateArchitecturePlan
14
- } from "./chunk-KJRBBLXT.js";
15
- import "./chunk-5AHG4NNX.js";
14
+ } from "./chunk-VLBVBF6V.js";
15
+ import "./chunk-E23FJX2I.js";
16
16
  import "./chunk-NOM47EB4.js";
17
17
  import "./chunk-3RG5ZIWI.js";
18
18
  export {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.43",
6
+ "version": "0.6.45",
7
7
  "description": "CLI interface for Coherent Design Method",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "ora": "^7.0.1",
44
44
  "prompts": "^2.4.2",
45
45
  "zod": "^3.22.4",
46
- "@getcoherent/core": "0.6.43"
46
+ "@getcoherent/core": "0.6.45"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^20.11.0",