@@ -5,16 +5,28 @@ import { CdsCompilationResult } from './types';
55import { fileExists , dirExists , recursivelyRenameJsonFiles } from '../../filesystem' ;
66
77/**
8- * Determine the `cds` command to use based on the environment.
8+ * Determine the `cds` command to use based on the environment and cache directory.
9+ * @param cacheDir Optional path to a directory containing installed dependencies
910 * @returns A string representing the CLI command to run to invoke the
1011 * CDS compiler.
1112 */
12- export function determineCdsCommand ( ) : string {
13+ export function determineCdsCommand ( cacheDir ?: string ) : string {
14+ // If we have a cache directory, use the cds binary from there
15+ if ( cacheDir ) {
16+ const localCdsBin = join ( cacheDir , 'node_modules' , '.bin' , 'cds' ) ;
17+
18+ // Check if the local cds binary exists in the cache directory
19+ if ( fileExists ( localCdsBin ) ) {
20+ // We need to use node to execute the local bin directly to ensure correct resolution
21+ return `node "${ localCdsBin } "` ;
22+ }
23+
24+ // If there's a cache directory but no local binary, use npx with NODE_PATH
25+ return `npx --no-install cds` ;
26+ }
27+
28+ // Default behavior when no cache directory is provided
1329 let cdsCommand = 'cds' ;
14- // TODO : create a mapping of project sub-directories to the correct
15- // cds command to use, which will also determine the version of the cds
16- // compiler that will be used for compiling `.cds` files to `.cds.json`
17- // files for that sub-directory / project.
1830 try {
1931 execFileSync ( 'cds' , [ '--version' ] , { stdio : 'ignore' } ) ;
2032 } catch {
@@ -24,6 +36,51 @@ export function determineCdsCommand(): string {
2436 return cdsCommand ;
2537}
2638
39+ /**
40+ * Get the CDS compiler version from a specific command or cache directory
41+ * @param cdsCommand The CDS command to use
42+ * @param cacheDir Optional path to a directory containing installed dependencies
43+ * @returns The CDS compiler version string, or undefined if it couldn't be determined
44+ */
45+ export function getCdsVersion ( cdsCommand : string , cacheDir ?: string ) : string | undefined {
46+ try {
47+ // Set up environment vars if using a cache directory
48+ const spawnOptions : SpawnSyncOptions = {
49+ shell : true ,
50+ stdio : 'pipe' ,
51+ env : { ...process . env } ,
52+ } ;
53+
54+ // If a cache directory is provided, set NODE_PATH to use that cache
55+ if ( cacheDir ) {
56+ const nodePath = join ( cacheDir , 'node_modules' ) ;
57+
58+ // Set up environment to use the cached dependencies
59+ spawnOptions . env = {
60+ ...process . env ,
61+ NODE_PATH : `${ nodePath } ${ delimiter } ${ process . env . NODE_PATH ?? '' } ` ,
62+ PATH : `${ join ( nodePath , '.bin' ) } ${ delimiter } ${ process . env . PATH } ` ,
63+ npm_config_prefix : cacheDir ,
64+ } ;
65+ }
66+
67+ // Execute the CDS command with the --version flag
68+ const result = spawnSync ( cdsCommand , [ '--version' ] , spawnOptions ) ;
69+ if ( result . status === 0 && result . stdout ) {
70+ const versionOutput = result . stdout . toString ( ) . trim ( ) ;
71+ // Extract version number, which is typically in formats like "@sap/cds: 6.1.3" or similar
72+ const match = versionOutput . match ( / @ s a p \/ c d s [ ^ 0 - 9 ] * ( [ 0 - 9 ] + \. [ 0 - 9 ] + \. [ 0 - 9 ] + ) / ) ;
73+ if ( match ?. [ 1 ] ) {
74+ return match [ 1 ] ; // Return just the version number
75+ }
76+ return versionOutput ; // Return full output if we couldn't parse it
77+ }
78+ return undefined ;
79+ } catch {
80+ return undefined ;
81+ }
82+ }
83+
2784/**
2885 * Compile a CDS file to JSON
2986 * @param cdsFilePath Path to the CDS file
@@ -45,23 +102,33 @@ export function compileCdsToJson(
45102 }
46103
47104 const cdsJsonOutPath = `${ resolvedCdsFilePath } .json` ;
48- console . log ( `Processing CDS file ${ resolvedCdsFilePath } to ${ cdsJsonOutPath } ...` ) ;
105+
106+ // Get and log the CDS version
107+ const cdsVersion = getCdsVersion ( cdsCommand , cacheDir ) ;
108+ const versionInfo = cdsVersion ? `with CDS v${ cdsVersion } ` : '' ;
109+ console . log ( `Processing CDS file ${ resolvedCdsFilePath } ${ versionInfo } ...` ) ;
49110
50111 // Prepare spawn options
51112 const spawnOptions : SpawnSyncOptions = {
52113 cwd : sourceRoot ,
53114 shell : true ,
54115 stdio : 'pipe' ,
116+ env : { ...process . env } ,
55117 } ;
56118
57119 // If a cache directory is provided, set NODE_PATH to use that cache
58120 if ( cacheDir ) {
59121 const nodePath = join ( cacheDir , 'node_modules' ) ;
122+
123+ // Set up environment to use the cached dependencies
60124 spawnOptions . env = {
61125 ...process . env ,
62126 NODE_PATH : `${ nodePath } ${ delimiter } ${ process . env . NODE_PATH ?? '' } ` ,
63127 PATH : `${ join ( nodePath , '.bin' ) } ${ delimiter } ${ process . env . PATH } ` ,
128+ // Add NPM configuration to ensure dependencies are resolved from the cache directory
129+ npm_config_prefix : cacheDir ,
64130 } ;
131+
65132 console . log ( `Using cached dependencies from: ${ cacheDir } ` ) ;
66133 }
67134
0 commit comments