'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var backendPluginApi = require('@backstage/backend-plugin-api');
var alpha = require('@backstage/backend-plugin-api/alpha');
var path = require('path');
var fs = require('fs-extra');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);

async function findClosestPackageDir(searchDir) {
  let path$1 = searchDir;
  for (let i = 0; i < 1e3; i++) {
    const packagePath = path.resolve(path$1, "package.json");
    const exists = await fs__default["default"].pathExists(packagePath);
    if (exists) {
      return path$1;
    }
    const newPath = path.dirname(path$1);
    if (newPath === path$1) {
      return void 0;
    }
    path$1 = newPath;
  }
  throw new Error(
    `Iteration limit reached when searching for root package.json at ${searchDir}`
  );
}
class PackageDiscoveryService {
  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() {
    var _a;
    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(
      path.resolve(packageDir, "package.json")
    );
    const features = [];
    for (const name of dependencyNames) {
      const depPkg = require(require.resolve(`${name}/package.json`, {
        paths: [packageDir]
      }));
      if (!(depPkg == null ? void 0 : depPkg.backstage) || ((_a = depPkg == null ? void 0 : depPkg.backstage) == null ? void 0 : _a.role) === "cli") {
        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 };
  }
}
const featureDiscoveryServiceFactory = backendPluginApi.createServiceFactory({
  service: alpha.featureDiscoveryServiceRef,
  deps: {
    config: backendPluginApi.coreServices.rootConfig,
    logger: backendPluginApi.coreServices.rootLogger
  },
  factory({ config, logger }) {
    return new PackageDiscoveryService(config, logger);
  }
});
function isBackendFeature(value) {
  return !!value && typeof value === "object" && value.$$type === "@backstage/BackendFeature";
}
function isBackendFeatureFactory(value) {
  return !!value && typeof value === "function" && value.$$type === "@backstage/BackendFeatureFactory";
}

exports.featureDiscoveryServiceFactory = featureDiscoveryServiceFactory;
//# sourceMappingURL=alpha.cjs.js.map
