From b0f36725b69d40c83e2835ae0bd6e7112db5ed4d Mon Sep 17 00:00:00 2001 From: "Dr. David A. Kunz" Date: Tue, 29 Jul 2025 12:10:15 +0200 Subject: [PATCH 1/3] projectpath --- lib/setModel.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/setModel.js b/lib/setModel.js index d0544d2..ddb7f23 100644 --- a/lib/setModel.js +++ b/lib/setModel.js @@ -3,7 +3,7 @@ import fs from 'fs' // Ensures only one CDS model compilation is ever in-flight. // The moment setModel is called, cds.model is set to a promise. -export default async function setModel(path) { +export default async function setModel(projectPath) { if (cds.model) { // If cds.model is a promise, await it; if it's resolved, return it if (typeof cds.model.then === 'function') await cds.model @@ -11,7 +11,7 @@ export default async function setModel(path) { } // Assign a promise immediately to cds.model to prevent duplicate compilations cds.model = (async () => { - const compiled = await compileModel(path) + const compiled = await compileModel(projectPath) cds.model = compiled return compiled })() @@ -20,16 +20,16 @@ export default async function setModel(path) { } // Loads and compiles the CDS model, returns the compiled model or throws on error -async function compileModel(path) { - cds.root = path +async function compileModel(projectPath) { + cds.root = projectPath const startTime = Date.now() - const resolved = cds.resolve(path + '/*', { cache: {} }) // make sure NOT to use the cache + const resolved = cds.resolve(projectPath + '/*', { cache: {} }) // make sure NOT to use the cache let compiled = await cds.load(resolved, { docs: true, locations: true }) if (!compiled || (Array.isArray(compiled) && compiled.length === 0)) { - throw new Error(`Failed to load CDS model from path: ${path}`) + throw new Error(`Failed to load CDS model from path: ${projectPath}`) } if (!compiled.definitions || Object.keys(compiled.definitions).length === 0) { - throw new Error(`Compiled CDS model is invalid or empty for path: ${path}`) + throw new Error(`Compiled CDS model is invalid or empty for path: ${projectPath}`) } compiled = cds.compile.for.nodejs(compiled) // to include drafts, show effective types const serviceInfo = cds.compile.to.serviceinfo(compiled) @@ -81,9 +81,9 @@ async function compileModel(path) { ? parseInt(process.env.CDS_MCP_REFRESH_MS, 10) : Math.max(compileDuration * 10, 20000) changeWatcher = setInterval(async () => { - const hasChanged = await cdsFilesChanged(path) + const hasChanged = await cdsFilesChanged(projectPath) if (hasChanged) { - await refreshModel(path) + await refreshModel(projectPath) } }, intervalMs).unref() // Uses CDS_MCP_REFRESH_MS if set, otherwise defaults to 10x compile duration or 20s } @@ -91,9 +91,9 @@ async function compileModel(path) { } // Refreshes the CDS model, only replaces cds.model if compilation succeeds -async function refreshModel(path) { +async function refreshModel(projectPath) { try { - const compiled = await compileModel(path) + const compiled = await compileModel(projectPath) cds.model = compiled return compiled } catch { @@ -105,9 +105,9 @@ async function refreshModel(path) { const cache = { cdsFiles: new Map() } let changeWatcher = null -async function cdsFilesChanged(path) { - if (path.endsWith('/')) path = path.slice(0, -1) - const files = cds.resolve(path + '/*', { cache: {} }) || [] +async function cdsFilesChanged(projectPath) { + if (projectPath.endsWith('/')) projectPath = projectPath.slice(0, -1) + const files = cds.resolve(projectPath + '/*', { cache: {} }) || [] const currentTimestamps = new Map() await Promise.all( files.map(file => From 6ed000b0e00441abeb7d85ad374fb53075790ee8 Mon Sep 17 00:00:00 2001 From: "Dr. David A. Kunz" Date: Tue, 29 Jul 2025 12:18:48 +0200 Subject: [PATCH 2/3] custom files finder --- lib/setModel.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/setModel.js b/lib/setModel.js index ddb7f23..4d48d37 100644 --- a/lib/setModel.js +++ b/lib/setModel.js @@ -1,5 +1,22 @@ import cds from '@sap/cds' import fs from 'fs' +import path from 'path' + +// Recursively find all .cds files under root, ignoring node_modules +async function findCdsFiles(dir) { + let results = [] + const entries = await fs.promises.readdir(dir, { withFileTypes: true }) + for (const entry of entries) { + const fullPath = path.join(dir, entry.name) + if (entry.isDirectory()) { + if (entry.name === 'node_modules') continue + results = results.concat(await findCdsFiles(fullPath)) + } else if (entry.isFile() && entry.name.endsWith('.cds')) { + results.push(fullPath) + } + } + return results +} // Ensures only one CDS model compilation is ever in-flight. // The moment setModel is called, cds.model is set to a promise. @@ -23,7 +40,7 @@ export default async function setModel(projectPath) { async function compileModel(projectPath) { cds.root = projectPath const startTime = Date.now() - const resolved = cds.resolve(projectPath + '/*', { cache: {} }) // make sure NOT to use the cache + const resolved = cds.resolve(projectPath + '/*', { cache: {} }) // use CAP standard resolution for model compilation let compiled = await cds.load(resolved, { docs: true, locations: true }) if (!compiled || (Array.isArray(compiled) && compiled.length === 0)) { throw new Error(`Failed to load CDS model from path: ${projectPath}`) @@ -41,7 +58,10 @@ async function compileModel(projectPath) { } for (const name in compiled.definitions) { - Object.defineProperty(compiled.definitions[name], 'name', { value: name, enumerable: true }) + Object.defineProperty(compiled.definitions[name], 'name', { + value: name, + enumerable: true + }) } const _entities_in = service => { @@ -107,7 +127,7 @@ let changeWatcher = null async function cdsFilesChanged(projectPath) { if (projectPath.endsWith('/')) projectPath = projectPath.slice(0, -1) - const files = cds.resolve(projectPath + '/*', { cache: {} }) || [] + const files = await findCdsFiles(projectPath) const currentTimestamps = new Map() await Promise.all( files.map(file => From 0e602cfaba8d4f729c09cd2e067e6d6cf540569b Mon Sep 17 00:00:00 2001 From: "Dr. David A. Kunz" Date: Tue, 29 Jul 2025 13:09:07 +0200 Subject: [PATCH 3/3] use files --- lib/setModel.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/setModel.js b/lib/setModel.js index 4d48d37..c61caa3 100644 --- a/lib/setModel.js +++ b/lib/setModel.js @@ -2,22 +2,6 @@ import cds from '@sap/cds' import fs from 'fs' import path from 'path' -// Recursively find all .cds files under root, ignoring node_modules -async function findCdsFiles(dir) { - let results = [] - const entries = await fs.promises.readdir(dir, { withFileTypes: true }) - for (const entry of entries) { - const fullPath = path.join(dir, entry.name) - if (entry.isDirectory()) { - if (entry.name === 'node_modules') continue - results = results.concat(await findCdsFiles(fullPath)) - } else if (entry.isFile() && entry.name.endsWith('.cds')) { - results.push(fullPath) - } - } - return results -} - // Ensures only one CDS model compilation is ever in-flight. // The moment setModel is called, cds.model is set to a promise. export default async function setModel(projectPath) { @@ -126,6 +110,22 @@ const cache = { cdsFiles: new Map() } let changeWatcher = null async function cdsFilesChanged(projectPath) { + // Recursively find all .cds files under root, ignoring node_modules + async function findCdsFiles(dir) { + let results = [] + const entries = await fs.promises.readdir(dir, { withFileTypes: true }) + for (const entry of entries) { + const fullPath = path.join(dir, entry.name) + if (entry.isDirectory()) { + if (entry.name === 'node_modules') continue + results = results.concat(await findCdsFiles(fullPath)) + } else if (entry.isFile() && entry.name.endsWith('.cds')) { + results.push(fullPath) + } + } + return results + } + if (projectPath.endsWith('/')) projectPath = projectPath.slice(0, -1) const files = await findCdsFiles(projectPath) const currentTimestamps = new Map()