UNPKG

@backstage/backend-defaults

Version:

Backend defaults used by Backstage backend apps

122 lines (116 loc) 3.97 kB
'use strict'; var fs = require('fs-extra'); var platformPath = require('path'); var errors = require('@backstage/errors'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var fs__default = /*#__PURE__*/_interopDefaultCompat(fs); const DETECTED_PACKAGE_ROLES = [ "node-library", "backend", "backend-plugin", "backend-plugin-module" ]; function isBackendFeature(value) { return !!value && ["object", "function"].includes(typeof value) && value.$$type === "@backstage/BackendFeature"; } function isBackendFeatureFactory(value) { return !!value && typeof value === "function" && value.$$type === "@backstage/BackendFeatureFactory"; } async function findClosestPackageDir(searchDir) { let path = searchDir; for (let i = 0; i < 1e3; i++) { const packagePath = platformPath.resolve(path, "package.json"); const exists = await fs__default.default.pathExists(packagePath); if (exists) { return path; } const newPath = platformPath.dirname(path); if (newPath === path) { return void 0; } path = newPath; } throw new Error( `Iteration limit reached when searching for root package.json at ${searchDir}` ); } class PackageDiscoveryService { config; logger; constructor(config, logger) { this.config = config; this.logger = logger; } getDependencyNames(path) { const { dependencies } = require(path); const packagesConfig = this.config.getOptional("backend.packages"); const dependencyNames = Object.keys(dependencies || {}); if (packagesConfig === "all") { return dependencyNames; } const includedPackagesConfig = this.config.getOptionalStringArray( "backend.packages.include" ); const includedPackages = includedPackagesConfig ? new Set(includedPackagesConfig) : dependencyNames; const excludedPackagesSet = new Set( this.config.getOptionalStringArray("backend.packages.exclude") ); return [...includedPackages].filter((name) => !excludedPackagesSet.has(name)); } async getBackendFeatures() { const packagesConfig = this.config.getOptional("backend.packages"); if (!packagesConfig || Object.keys(packagesConfig).length === 0) { return { features: [] }; } const packageDir = await findClosestPackageDir(process.argv[1]); if (!packageDir) { throw new Error("Package discovery failed to find package.json"); } const dependencyNames = this.getDependencyNames( platformPath.resolve(packageDir, "package.json") ); const features = []; for (const name of dependencyNames) { let depPkg; try { const packageJsonPath = require.resolve(`${name}/package.json`, { paths: [packageDir] }); depPkg = require(packageJsonPath); } catch (error) { if (errors.isError(error) && error.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") { continue; } throw error; } if (!depPkg?.backstage?.role || !DETECTED_PACKAGE_ROLES.includes(depPkg.backstage.role)) { continue; } const exportedModulePaths = [ require.resolve(name, { paths: [packageDir] }) ]; try { exportedModulePaths.push( require.resolve(`${name}/alpha`, { paths: [packageDir] }) ); } catch { } for (const modulePath of exportedModulePaths) { const mod = require(modulePath); if (isBackendFeature(mod.default)) { this.logger.info(`Detected: ${name}`); features.push(mod.default); } if (isBackendFeatureFactory(mod.default)) { this.logger.info(`Detected: ${name}`); features.push(mod.default()); } } } return { features: Array.from(new Set(features)) }; } } exports.PackageDiscoveryService = PackageDiscoveryService; //# sourceMappingURL=PackageDiscoveryService.cjs.js.map