UNPKG

@sap-ux/project-access

Version:

Library to access SAP Fiori tools projects

164 lines 6.51 kB
import { basename, dirname, join } from 'node:path'; import { UI5Config } from '@sap-ux/ui5-config'; import { DirName, FileName } from '../constants.js'; import { fileExists, findFilesByExtension, findFileUp, readFile } from '../file/index.js'; /** * Default path mappings for each UI5 project type. * */ const PATH_MAPPING_DEFAULTS = { application: { webapp: DirName.Webapp }, library: { src: 'src', test: 'test' }, 'theme-library': { src: 'src', test: 'test' }, module: {} }; /** * Get base directory of the project where package.json is located. * * @param appRoot - root to the application * @param memFs - optional mem-fs editor instance * @returns - base directory of the project */ async function getBaseDir(appRoot, memFs) { const packageJsonPath = await findFileUp(FileName.Package, appRoot, memFs); return packageJsonPath ? dirname(packageJsonPath) : appRoot; } /** * Get path to webapp. * * @param appRoot - root to the application * @param [memFs] - optional mem-fs editor instance * @returns - path to webapp folder */ export async function getWebappPath(appRoot, memFs) { let pathMappings; try { pathMappings = await getPathMappings(appRoot, memFs); } catch { // For backward compatibility ignore errors and use default pathMappings = {}; } return 'webapp' in pathMappings ? pathMappings.webapp : join(appRoot, DirName.Webapp); } /** * Get path mappings defined in 'ui5.yaml' depending on the project type defined in 'ui5.yaml'. * * @param appRoot - root to the application * @param memFs - optional mem-fs editor instance * @param fileName - optional name of yaml file to be read. Defaults to 'ui5.yaml'. * @returns - path mappings * @throws {Error} if ui5.yaml or 'type' cannot be read * @throws {Error} if project type is not 'application', 'library', 'theme-library' or 'module' */ export async function getPathMappings(appRoot, memFs, fileName = FileName.Ui5Yaml) { let ui5Config; let configuration; let type; try { ui5Config = await readUi5Yaml(appRoot, fileName, memFs); configuration = ui5Config.getConfiguration(); type = ui5Config.getType(); } catch { throw new Error(`Could not read 'type' from ${fileName} in project root: ${appRoot}`); } if (!(type in PATH_MAPPING_DEFAULTS)) { throw new Error(`Unsupported project type for path mappings: ${type}`); } const baseDir = await getBaseDir(appRoot, memFs); // Use Record<string, string> to permit index access during the merge loop const result = {}; const configPaths = (configuration?.paths || {}); const defaults = PATH_MAPPING_DEFAULTS[type]; for (const key in defaults) { const value = configPaths[key] ?? defaults[key]; result[key] = join(baseDir, value); } // Cast the merged result to PathMappings to re-enforce strict union keys for the caller return result; } /** * Checks if UI5 config yaml file exists and returns its content. * * @param projectRoot - path to project root * @param fileName - name of yaml file to be read * @param [memFs] - optional mem-fs editor instance * @param options - options * @param [options.validateSchema] - optional flag to validate the schema of the yaml file * @returns {UI5Config} UI5 config file in yaml format * @throws {Error} if file is not found */ export async function readUi5Yaml(projectRoot, fileName, memFs, options) { const ui5YamlPath = join(projectRoot, fileName); if (await fileExists(ui5YamlPath, memFs)) { const yamlString = await readFile(ui5YamlPath, memFs); return await UI5Config.newInstance(yamlString, { validateSchema: options?.validateSchema }); } throw Error(`File '${fileName}' not found in project '${projectRoot}'`); } /** * Scans the project directory for ui5 configuration yaml files. * * @param projectRoot - path to project root, where ui5 configuration y*ml files are located * @param [memFs] - optional mem-fs editor instance * @returns list of valid and invalid UI5 configuration yaml file names * @throws {Error} if an error occurs while reading files from projectRoot */ export async function getAllUi5YamlFileNames(projectRoot, memFs) { try { const yamlFilePaths = await findFilesByExtension('.yaml', projectRoot, [], memFs, true); return yamlFilePaths.map((path) => basename(path)); } catch (error) { throw new Error(`There was an error reading files from the directory '${projectRoot}': ${error}`); } } /** * Retrieves the mock server configuration from the UI5 mock YAML file. * * @param projectRoot - Path to the project root. * @param fileName - Name of the YAML file to read. Defaults to FileName.Ui5MockYaml. * @returns The mock server configuration or null if not found. * @throws {Error} If the sap-fe-mockserver middleware is not found. */ export async function getMockServerConfig(projectRoot, fileName = FileName.Ui5MockYaml) { const ui5MockYamlFile = await readUi5Yaml(projectRoot, fileName); const mockserverMiddleware = ui5MockYamlFile.findCustomMiddleware('sap-fe-mockserver'); if (!mockserverMiddleware) { throw new Error('Could not find sap-fe-mockserver'); } return mockserverMiddleware.configuration; } /** * Retrieves the mock data path from the mock server configuration. * * @param projectRoot - Path to the project root. * @param fileName - Name of the YAML file to read. Defaults to FileName.Ui5MockYaml. * @returns The mock data path as a string. Returns an empty string if not found. */ export async function getMockDataPath(projectRoot, fileName = FileName.Ui5MockYaml) { const mockServerConfig = await getMockServerConfig(projectRoot, fileName); if (!mockServerConfig) { return ''; } const services = extractServices(mockServerConfig); if (!services) { return ''; } const found = services.find((service) => !!service.mockdataPath); return found?.mockdataPath ?? ''; } /** * Helper to extract the services array from a MockServerConfiguration. * * @param config - The mock server configuration object. * @returns An array of MockServerService objects, or undefined if not found. */ function extractServices(config) { if ('services' in config && config.services) { return Array.isArray(config.services) ? config.services : [config.services]; } return undefined; } //# sourceMappingURL=ui5-config.js.map