Skip to content

Commit f337b40

Browse files
Merge branch 'main' into fix/js-jest30-loop-runner
2 parents 3e27d63 + a747513 commit f337b40

15 files changed

Lines changed: 460 additions & 214 deletions

File tree

codeflash/cli_cmds/cli.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,13 @@ def _handle_show_config() -> None:
359359
detected = detect_project(project_root)
360360

361361
# Check if config exists or is auto-detected
362-
config_exists, _ = has_existing_config(project_root)
362+
config_exists, config_file = has_existing_config(project_root)
363363
status = "Saved config" if config_exists else "Auto-detected (not saved)"
364364

365365
console.print()
366366
console.print(f"[bold]Codeflash Configuration[/bold] ({status})")
367+
if config_exists and config_file:
368+
console.print(f"[dim]Config file: {project_root / config_file}[/dim]")
367369
console.print()
368370

369371
table = Table(show_header=True, header_style="bold cyan")

codeflash/code_utils/config_js.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from pathlib import Path
77
from typing import Any
88

9+
from codeflash.setup.detector import is_build_output_dir
10+
911
PACKAGE_JSON_CACHE: dict[Path, Path] = {}
1012
PACKAGE_JSON_DATA_CACHE: dict[Path, dict[str, Any]] = {}
1113

@@ -50,12 +52,15 @@ def detect_module_root(project_root: Path, package_data: dict[str, Any]) -> str:
5052
"""Detect module root from package.json fields or directory conventions.
5153
5254
Detection order:
53-
1. package.json "exports" field (extract directory from main export)
54-
2. package.json "module" field (ESM entry point)
55-
3. package.json "main" field (CJS entry point)
56-
4. "src/" directory if it exists
55+
1. src/, lib/, source/ directories (common source directories)
56+
2. package.json "exports" field (if not in build output directory)
57+
3. package.json "module" field (ESM, if not in build output directory)
58+
4. package.json "main" field (CJS, if not in build output directory)
5759
5. Fall back to "." (project root)
5860
61+
Build output directories (build/, dist/, out/) are skipped since they contain
62+
compiled code, not source files.
63+
5964
Args:
6065
project_root: Root directory of the project.
6166
package_data: Parsed package.json data.
@@ -64,6 +69,11 @@ def detect_module_root(project_root: Path, package_data: dict[str, Any]) -> str:
6469
Detected module root path (relative to project root).
6570
6671
"""
72+
# Check for common source directories first - these are always preferred
73+
for src_dir in ["src", "lib", "source"]:
74+
if (project_root / src_dir).is_dir():
75+
return src_dir
76+
6777
# Check exports field (modern Node.js)
6878
exports = package_data.get("exports")
6979
if exports:
@@ -80,27 +90,38 @@ def detect_module_root(project_root: Path, package_data: dict[str, Any]) -> str:
8090

8191
if entry_path and isinstance(entry_path, str):
8292
parent = Path(entry_path).parent
83-
if parent != Path() and (project_root / parent).is_dir():
93+
if (
94+
parent != Path()
95+
and parent.as_posix() != "."
96+
and (project_root / parent).is_dir()
97+
and not is_build_output_dir(parent)
98+
):
8499
return parent.as_posix()
85100

86101
# Check module field (ESM)
87102
module_field = package_data.get("module")
88103
if module_field and isinstance(module_field, str):
89104
parent = Path(module_field).parent
90-
if parent != Path() and (project_root / parent).is_dir():
105+
if (
106+
parent != Path()
107+
and parent.as_posix() != "."
108+
and (project_root / parent).is_dir()
109+
and not is_build_output_dir(parent)
110+
):
91111
return parent.as_posix()
92112

93113
# Check main field (CJS)
94114
main_field = package_data.get("main")
95115
if main_field and isinstance(main_field, str):
96116
parent = Path(main_field).parent
97-
if parent != Path() and (project_root / parent).is_dir():
117+
if (
118+
parent != Path()
119+
and parent.as_posix() != "."
120+
and (project_root / parent).is_dir()
121+
and not is_build_output_dir(parent)
122+
):
98123
return parent.as_posix()
99124

100-
# Check for src/ directory convention
101-
if (project_root / "src").is_dir():
102-
return "src"
103-
104125
# Default to project root
105126
return "."
106127

codeflash/languages/javascript/module_system.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ def _convert_destructuring_to_imports(names_str: str) -> str:
222222
223223
Returns:
224224
Import names string with aliases using 'as' syntax
225+
225226
"""
226227
# Split by commas and process each name
227228
parts = []

codeflash/setup/detector.py

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
import tomlkit
2323

24+
_BUILD_DIRS = frozenset({"build", "dist", "out", ".next", ".nuxt"})
25+
2426

2527
@dataclass
2628
class DetectedProject:
@@ -310,14 +312,21 @@ def _detect_js_module_root(project_root: Path) -> tuple[Path, str]:
310312
"""Detect JavaScript/TypeScript module root.
311313
312314
Priority:
313-
1. package.json "exports" field
314-
2. package.json "module" field (ESM)
315-
3. package.json "main" field (CJS)
316-
4. src/ directory
317-
5. lib/ directory
318-
6. Project root
315+
1. src/, lib/, source/ directories (common source directories)
316+
2. package.json "exports" field (if not in build output directory)
317+
3. package.json "module" field (ESM, if not in build output directory)
318+
4. package.json "main" field (CJS, if not in build output directory)
319+
5. Project root
320+
321+
Build output directories (build/, dist/, out/) are skipped since they contain
322+
compiled code, not source files.
319323
320324
"""
325+
# Check for common source directories first - these are always preferred
326+
for src_dir in ["src", "lib", "source"]:
327+
if (project_root / src_dir).is_dir():
328+
return project_root / src_dir, f"{src_dir}/ directory"
329+
321330
package_json_path = project_root / "package.json"
322331
package_data: dict[str, Any] = {}
323332

@@ -334,32 +343,52 @@ def _detect_js_module_root(project_root: Path) -> tuple[Path, str]:
334343
entry_path = _extract_entry_path(exports)
335344
if entry_path:
336345
parent = Path(entry_path).parent
337-
if parent != Path() and parent.as_posix() != "." and (project_root / parent).is_dir():
346+
if (
347+
parent != Path()
348+
and parent.as_posix() != "."
349+
and (project_root / parent).is_dir()
350+
and not is_build_output_dir(parent)
351+
):
338352
return project_root / parent, f'{parent.as_posix()}/ (from package.json "exports")'
339353

340354
# Check module field (ESM)
341355
module_field = package_data.get("module")
342356
if module_field and isinstance(module_field, str):
343357
parent = Path(module_field).parent
344-
if parent != Path() and parent.as_posix() != "." and (project_root / parent).is_dir():
358+
if (
359+
parent != Path()
360+
and parent.as_posix() != "."
361+
and (project_root / parent).is_dir()
362+
and not is_build_output_dir(parent)
363+
):
345364
return project_root / parent, f'{parent.as_posix()}/ (from package.json "module")'
346365

347366
# Check main field (CJS)
348367
main_field = package_data.get("main")
349368
if main_field and isinstance(main_field, str):
350369
parent = Path(main_field).parent
351-
if parent != Path() and parent.as_posix() != "." and (project_root / parent).is_dir():
370+
if (
371+
parent != Path()
372+
and parent.as_posix() != "."
373+
and (project_root / parent).is_dir()
374+
and not is_build_output_dir(parent)
375+
):
352376
return project_root / parent, f'{parent.as_posix()}/ (from package.json "main")'
353377

354-
# Check for common source directories
355-
for src_dir in ["src", "lib", "source"]:
356-
if (project_root / src_dir).is_dir():
357-
return project_root / src_dir, f"{src_dir}/ directory"
358-
359378
# Default to project root
360379
return project_root, "project root"
361380

362381

382+
def is_build_output_dir(path: Path) -> bool:
383+
"""Check if a path is within a common build output directory.
384+
385+
Build output directories contain compiled code and should be skipped
386+
in favor of source directories.
387+
388+
"""
389+
return not _BUILD_DIRS.isdisjoint(path.parts)
390+
391+
363392
def _extract_entry_path(exports: Any) -> str | None:
364393
"""Extract entry path from package.json exports field."""
365394
if isinstance(exports, str):

npm-package/README.md

Lines changed: 0 additions & 60 deletions
This file was deleted.

npm-package/bin/codeflash

Lines changed: 0 additions & 47 deletions
This file was deleted.

npm-package/package.json

Lines changed: 0 additions & 47 deletions
This file was deleted.

packages/codeflash/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/codeflash/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeflash",
3-
"version": "0.5.0",
3+
"version": "0.7.0",
44
"description": "Codeflash - AI-powered code optimization for JavaScript and TypeScript",
55
"main": "runtime/index.js",
66
"types": "runtime/index.d.ts",

0 commit comments

Comments
 (0)