import { stringifyError } from '@backstage/errors';
import { isInternalFrontendFeatureLoader } from './frontend-plugin-api/src/wiring/createFrontendFeatureLoader.esm.js';

async function resolveAsyncFeatures(options) {
  const features = [];
  for (const item of options?.features ?? []) {
    if ("load" in item) {
      try {
        const result = await item.load({ config: options.config });
        features.push(...result.features);
      } catch (e) {
        throw new Error(
          `Failed to read frontend features from loader '${item.getLoaderName()}', ${stringifyError(
            e
          )}`
        );
      }
    } else {
      features.push(item);
    }
  }
  const loadedFeatures = [];
  const alreadyMetFeatureLoaders = [];
  const maxRecursionDepth = 5;
  async function applyFeatureLoaders(featuresOrLoaders, recursionDepth) {
    if (featuresOrLoaders.length === 0) {
      return;
    }
    for (const featureOrLoader of featuresOrLoaders) {
      if (isBackstageFeatureLoader(featureOrLoader)) {
        if (alreadyMetFeatureLoaders.some((l) => l === featureOrLoader)) {
          continue;
        }
        if (isInternalFrontendFeatureLoader(featureOrLoader)) {
          if (recursionDepth > maxRecursionDepth) {
            throw new Error(
              `Maximum feature loading recursion depth (${maxRecursionDepth}) reached for the feature loader ${featureOrLoader.description}`
            );
          }
          alreadyMetFeatureLoaders.push(featureOrLoader);
          let result;
          try {
            result = await featureOrLoader.loader({ config: options.config });
          } catch (e) {
            throw new Error(
              `Failed to read frontend features from loader ${featureOrLoader.description}: ${stringifyError(e)}`
            );
          }
          await applyFeatureLoaders(result, recursionDepth + 1);
        }
      } else {
        loadedFeatures.push(featureOrLoader);
      }
    }
  }
  await applyFeatureLoaders(features, 1);
  return { features: loadedFeatures };
}
function isBackstageFeatureLoader(obj) {
  return obj !== null && typeof obj === "object" && "$$type" in obj && obj.$$type === "@backstage/FrontendFeatureLoader";
}

export { isBackstageFeatureLoader, resolveAsyncFeatures };
//# sourceMappingURL=resolution.esm.js.map
