@@ -19,8 +19,8 @@ import { BasicCdsProject } from '../parser/types';
1919 *
2020 * @param cdsFilePath The path to the CDS file to compile, relative to the `sourceRoot`.
2121 * @param sourceRoot The source root directory scanned by the CDS extractor.
22- * CRITICAL: All spawned processes must use this as their cwd to ensure paths in generated
23- * JSON are relative to sourceRoot .
22+ * CRITICAL: All spawned processes will use the project base directory as their ` cwd` to
23+ * ensure that paths in generated JSON are relative to the project base directory .
2424 *
2525 * @param cdsCommand The actual shell command to use for `cds compile`.
2626 * @param cacheDir Full path to the cache directory where dependencies are stored.
@@ -47,8 +47,11 @@ export function compileCdsToJson(
4747 const cdsVersion = getCdsVersion ( cdsCommand , cacheDir ) ;
4848 const versionInfo = cdsVersion ? `with CDS v${ cdsVersion } ` : '' ;
4949
50- // CRITICAL: Create spawn options with sourceRoot as cwd to ensure correct path generation
51- const spawnOptions = createSpawnOptions ( sourceRoot , cdsCommand , cacheDir ) ;
50+ // Calculate project base directory for consistent working directory
51+ const projectBaseDir = join ( sourceRoot , projectDir ) ;
52+
53+ // Create spawn options with project base directory as cwd.
54+ const spawnOptions = createSpawnOptions ( projectBaseDir , cdsCommand , cacheDir ) ;
5255
5356 // Throw an error if projectDir cannot be found in the projectMap.
5457 if ( ! projectMap || ! projectDir || ! projectMap . has ( projectDir ) ) {
@@ -60,7 +63,7 @@ export function compileCdsToJson(
6063 const project = projectMap . get ( projectDir ) ;
6164 const relativePath = relative ( sourceRoot , resolvedCdsFilePath ) ;
6265
63- // Check if this is a project-level compilation marker
66+ // Check if this is a project-level compilation marker.
6467 if ( shouldUseProjectLevelCompilation ( project ) ) {
6568 return compileProjectLevel (
6669 resolvedCdsFilePath ,
@@ -72,7 +75,7 @@ export function compileCdsToJson(
7275 ) ;
7376 }
7477
75- // Check if this file is in the list of files to compile for this project
78+ // Check if this file is in the list of files to compile for this project.
7679 if ( ! shouldCompileIndividually ( project , relativePath ) ) {
7780 cdsExtractorLog (
7881 'info' ,
@@ -107,13 +110,13 @@ export function compileCdsToJson(
107110
108111/**
109112 * Handles project-level compilation for CAP projects with typical directory structure.
110- * CRITICAL: Uses the project directory as cwd and calculates paths relative to project directory.
113+ * CRITICAL: Uses the project base directory as cwd and calculates paths relative to project base directory.
111114 *
112115 * @param resolvedCdsFilePath The resolved CDS file path that triggered this compilation
113116 * @param sourceRoot The source root directory
114117 * @param projectDir The project directory (relative to sourceRoot)
115118 * @param cdsCommand The CDS command to use
116- * @param spawnOptions Pre-configured spawn options with sourceRoot as cwd
119+ * @param spawnOptions Pre-configured spawn options with project base directory as cwd
117120 * @param versionInfo Version information for logging
118121 * @returns Compilation result
119122 */
@@ -158,12 +161,12 @@ function compileProjectLevel(
158161 }
159162
160163 if ( existingDirectories . length === 0 ) {
161- // If no standard directories, check if there are CDS files in the root
164+ // If no standard directories, check if there are CDS files in the root of the project.
162165 const rootCdsFiles = globSync ( join ( projectAbsolutePath , '*.cds' ) ) ;
163166 if ( rootCdsFiles . length > 0 ) {
164167 existingDirectories . push ( '.' ) ;
165168 } else {
166- // Find directories that contain CDS files
169+ // Find directories that contain `.cds` files.
167170 const cdsFileParents = new Set (
168171 allCdsFiles . map ( ( file : string ) => {
169172 const relativePath = relative ( projectAbsolutePath , file ) ;
@@ -175,28 +178,19 @@ function compileProjectLevel(
175178 }
176179 }
177180
178- // Generate output path for the compiled model - relative to sourceRoot for consistency
179- const relativeOutputPath = join ( projectDir , 'model.cds.json' ) ;
180- const projectJsonOutPath = join ( sourceRoot , relativeOutputPath ) ;
181+ // Generate output path for the compiled model - relative to project base directory.
182+ const projectJsonOutPath = join ( sourceRoot , projectDir , 'model.cds.json' ) ;
181183
182- // Use sourceRoot as working directory but provide project-relative paths
183- const projectSpawnOptions : SpawnSyncOptions = {
184- ...spawnOptions ,
185- cwd : sourceRoot , // Use sourceRoot as working directory for consistency
186- } ;
187-
188- // Convert directories to be relative to sourceRoot (include project prefix)
189- const projectRelativeDirectories = existingDirectories . map ( dir =>
190- dir === '.' ? projectDir : join ( projectDir , dir ) ,
191- ) ;
184+ // Convert directories to be relative to project base directory.
185+ const projectRelativeDirectories = existingDirectories ;
192186
193187 const compileArgs = [
194188 'compile' ,
195- ...projectRelativeDirectories , // Use paths relative to sourceRoot
189+ ...projectRelativeDirectories , // Use paths relative to project base directory.
196190 '--to' ,
197191 'json' ,
198192 '--dest' ,
199- join ( projectDir , 'model.cds.json' ) , // Output to specific model.cds.json file
193+ 'model.cds.json' , // TODO : replace ` model.cds.json` with `model.<session_id>.cds.json`
200194 '--locations' ,
201195 '--log-level' ,
202196 'warn' ,
@@ -208,16 +202,14 @@ function compileProjectLevel(
208202 `Running compilation task for CDS project '${ projectDir } ': command='${ cdsCommand } ' args='${ JSON . stringify ( compileArgs ) } '` ,
209203 ) ;
210204
211- // CRITICAL: Use the project directory as cwd
212- // Use array arguments for consistent test behavior
213- const result = spawnSync ( cdsCommand , compileArgs , projectSpawnOptions ) ;
205+ const result = spawnSync ( cdsCommand , compileArgs , spawnOptions ) ;
214206
215207 if ( result . error ) {
216208 cdsExtractorLog ( 'error' , `SpawnSync error: ${ result . error . message } ` ) ;
217209 throw new Error ( `Error executing CDS compiler: ${ result . error . message } ` ) ;
218210 }
219211
220- // Log stderr for debugging even on success (CDS often writes warnings to stderr)
212+ // Log stderr for debugging even on success (CDS often writes warnings to stderr).
221213 if ( result . stderr && result . stderr . length > 0 ) {
222214 cdsExtractorLog ( 'warn' , `CDS stderr output: ${ result . stderr . toString ( ) } ` ) ;
223215 }
@@ -243,13 +235,14 @@ function compileProjectLevel(
243235 ) ;
244236 }
245237
246- // Handle directory output if the CDS compiler generated a directory
238+ // Handle directory output if the CDS compiler generated a directory.
247239 if ( dirExists ( projectJsonOutPath ) ) {
248240 cdsExtractorLog (
249241 'info' ,
250242 `CDS compiler generated JSON to output directory: ${ projectJsonOutPath } ` ,
251243 ) ;
252- // Recursively rename all .json files to have a .cds.json extension
244+ // Recursively rename generated .json files to have a .cds.json extension
245+ // TODO : replace or remove this in favor of session-specific file suffixes (i.e. `.<session_id>.cds.json`).
253246 recursivelyRenameJsonFiles ( projectJsonOutPath ) ;
254247 } else {
255248 cdsExtractorLog ( 'info' , `CDS compiler generated JSON to file: ${ projectJsonOutPath } ` ) ;
@@ -278,19 +271,20 @@ function compileProjectLevel(
278271function compileRootFileAsProject (
279272 resolvedCdsFilePath : string ,
280273 sourceRoot : string ,
281- _projectDir : string ,
274+ projectDir : string ,
282275 cdsCommand : string ,
283276 spawnOptions : SpawnSyncOptions ,
284277 _versionInfo : string ,
285278) : CdsCompilationResult {
286- // Calculate relative path for the output file
287- const relativeCdsPath = relative ( sourceRoot , resolvedCdsFilePath ) ;
279+ // Calculate project base directory and file path relative to project
280+ const projectBaseDir = join ( sourceRoot , projectDir ) ;
281+ const relativeCdsPath = relative ( projectBaseDir , resolvedCdsFilePath ) ;
288282 const cdsJsonOutPath = `${ resolvedCdsFilePath } .json` ;
289283
290284 // Use project-aware compilation with specific file target
291285 const compileArgs = [
292286 'compile' ,
293- relativeCdsPath , // Compile the specific file relative to sourceRoot
287+ relativeCdsPath , // Compile the specific file relative to project base directory
294288 '--to' ,
295289 'json' ,
296290 '--dest' ,
@@ -362,20 +356,20 @@ function compileRootFileAsProject(
362356
363357/**
364358 * Creates spawn options for CDS compilation processes.
365- * CRITICAL: Always sets cwd to sourceRoot to ensure generated JSON paths are relative to sourceRoot .
359+ * CRITICAL: Always sets cwd to project base directory to ensure generated JSON paths are relative to project base directory .
366360 *
367- * @param sourceRoot The source root directory - used as cwd for all spawned processes
361+ * @param projectBaseDir The project base directory (where package.json is located) - used as cwd for all spawned processes
368362 * @param cdsCommand The CDS command to determine if we need Node.js environment setup
369363 * @param cacheDir Optional cache directory for dependencies
370364 * @returns Spawn options configured for CDS compilation
371365 */
372366function createSpawnOptions (
373- sourceRoot : string ,
367+ projectBaseDir : string ,
374368 cdsCommand : string ,
375369 cacheDir ?: string ,
376370) : SpawnSyncOptions {
377371 const spawnOptions : SpawnSyncOptions = {
378- cwd : sourceRoot , // CRITICAL: Always use sourceRoot as cwd to ensure correct path generation
372+ cwd : projectBaseDir , // CRITICAL: Always use project base directory as cwd to ensure correct path generation
379373 shell : false , // Use shell=false to ensure proper argument handling for paths with spaces
380374 stdio : 'pipe' ,
381375 env : { ...process . env } ,
0 commit comments