"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.AspectMain = void 0;
function _aspectLoader() {
  const data = require("@teambit/aspect-loader");
  _aspectLoader = function () {
    return data;
  };
  return data;
}
function _logger() {
  const data = require("@teambit/logger");
  _logger = function () {
    return data;
  };
  return data;
}
function _builder() {
  const data = require("@teambit/builder");
  _builder = function () {
    return data;
  };
  return data;
}
function _lodash() {
  const data = require("lodash");
  _lodash = function () {
    return data;
  };
  return data;
}
function _dependencyResolver() {
  const data = require("@teambit/dependency-resolver");
  _dependencyResolver = function () {
    return data;
  };
  return data;
}
function _bitError() {
  const data = require("@teambit/bit-error");
  _bitError = function () {
    return data;
  };
  return data;
}
function _cli() {
  const data = require("@teambit/cli");
  _cli = function () {
    return data;
  };
  return data;
}
function _envs() {
  const data = require("@teambit/envs");
  _envs = function () {
    return data;
  };
  return data;
}
function _react() {
  const data = require("@teambit/react");
  _react = function () {
    return data;
  };
  return data;
}
function _generator() {
  const data = require("@teambit/generator");
  _generator = function () {
    return data;
  };
  return data;
}
function _componentId() {
  const data = require("@teambit/component-id");
  _componentId = function () {
    return data;
  };
  return data;
}
function _worker() {
  const data = require("@teambit/worker");
  _worker = function () {
    return data;
  };
  return data;
}
function _workspace() {
  const data = require("@teambit/workspace");
  _workspace = function () {
    return data;
  };
  return data;
}
function _compiler() {
  const data = require("@teambit/compiler");
  _compiler = function () {
    return data;
  };
  return data;
}
function _aspect() {
  const data = require("./aspect.aspect");
  _aspect = function () {
    return data;
  };
  return data;
}
function _aspect2() {
  const data = require("./aspect.env");
  _aspect2 = function () {
    return data;
  };
  return data;
}
function _coreExporter() {
  const data = require("./core-exporter.task");
  _coreExporter = function () {
    return data;
  };
  return data;
}
function _babelConfig() {
  const data = require("./babel/babel-config");
  _babelConfig = function () {
    return data;
  };
  return data;
}
function _aspect3() {
  const data = require("./aspect.cmd");
  _aspect3 = function () {
    return data;
  };
  return data;
}
function _aspect4() {
  const data = require("./aspect.templates");
  _aspect4 = function () {
    return data;
  };
  return data;
}
function _devFiles() {
  const data = require("@teambit/dev-files");
  _devFiles = function () {
    return data;
  };
  return data;
}
function _legacy() {
  const data = require("@teambit/legacy.extension-data");
  _legacy = function () {
    return data;
  };
  return data;
}
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class AspectMain {
  constructor(aspectEnv, envs, workspace, aspectLoader, depsResolver) {
    this.aspectEnv = aspectEnv;
    this.envs = envs;
    this.workspace = workspace;
    this.aspectLoader = aspectLoader;
    this.depsResolver = depsResolver;
  }

  /**
   * compose your own aspect environment.
   */
  compose(transformers = [], targetEnv = {}) {
    return this.envs.compose(this.envs.merge(targetEnv, this.aspectEnv), transformers);
  }
  async listAspectsOfComponent(pattern) {
    const getIds = async () => {
      if (!pattern) return this.workspace.listIds();
      return this.workspace.idsByPattern(pattern);
    };
    const componentIds = await getIds();
    const results = {};
    await Promise.all(componentIds.map(async id => {
      const aspectSources = await this.getAspectNamesForComponent(id);
      results[id.toString()] = aspectSources;
    }));
    return results;
  }
  listCoreAspects() {
    return this.aspectLoader.getCoreAspectIds();
  }
  get babelConfig() {
    return _babelConfig().babelConfig;
  }
  async getAspectNamesForComponent(id) {
    const componentFromScope = await this.workspace.scope.get(id);
    const {
      beforeMerge
    } = await this.workspace.componentExtensions(id, componentFromScope);
    const aspectSources = [];
    beforeMerge.forEach(source => {
      source.extensions.forEach(ext => {
        const aspectName = ext.name || ext.extensionId?.toString() || '<no-name>';
        const alreadySaved = aspectSources.find(_ => _.aspectName === aspectName);
        if (alreadySaved) return;
        aspectSources.push({
          aspectName,
          source: source.origin,
          level: this.getLevelBySourceOrigin(source.origin)
        });
      });
    });
    return aspectSources;
  }
  getLevelBySourceOrigin(origin) {
    switch (origin) {
      case 'BitmapFile':
      case 'ComponentJsonFile':
      case 'ModelSpecific':
        return 'component';
      default:
        return 'workspace';
    }
  }
  async setAspectsToComponents(pattern, aspectId, config = {}, options = {}) {
    const componentIds = await this.workspace.idsByPattern(pattern);
    await Promise.all(componentIds.map(async componentId => {
      await this.workspace.addSpecificComponentConfig(componentId, aspectId, config, {
        shouldMergeWithExisting: options.merge
      });
    }));
    await this.workspace.bitMap.write(`aspect-set (${aspectId})`);
    return componentIds;
  }
  async unsetAspectsFromComponents(pattern, aspectIdStr) {
    const componentIds = await this.workspace.idsByPattern(pattern);
    const aspectId = await this.workspace.resolveComponentId(aspectIdStr);
    const components = await this.workspace.getMany(componentIds);
    const updatedCompIds = [];
    await Promise.all(components.map(async component => {
      const existAspect = component.state.aspects.get(aspectId.toStringWithoutVersion());
      if (!existAspect) return;
      await this.workspace.removeSpecificComponentConfig(component.id, existAspect.id.toString(), true);
      updatedCompIds.push(component.id);
    }));
    await this.workspace.bitMap.write(`aspect-unset (${aspectId})`);
    return updatedCompIds;
  }

  /**
   * returns all aspects info of a component, include the config and the data.
   */
  async getAspectsOfComponent(id) {
    if (typeof id === 'string') {
      id = await this.workspace.resolveComponentId(id);
    }
    const component = await this.workspace.get(id);
    return component.state.aspects;
  }

  /**
   * helps debugging why/how an aspect was set to a component
   */
  async getAspectsOfComponentForDebugging(id) {
    if (typeof id === 'string') {
      id = await this.workspace.resolveComponentId(id);
    }
    const componentFromScope = await this.workspace.scope.get(id);
    const {
      extensions,
      beforeMerge
    } = await this.workspace.componentExtensions(id, componentFromScope);
    const component = await this.workspace.get(id);
    return {
      aspects: component.state.aspects,
      extensions,
      beforeMerge
    };
  }
  async updateAspectsToComponents(aspectId, pattern) {
    let aspectCompId = await this.workspace.resolveComponentId(aspectId);
    if (!aspectCompId.hasVersion()) {
      try {
        const fromRemote = await this.workspace.scope.getRemoteComponent(aspectCompId);
        aspectCompId = aspectCompId.changeVersion(fromRemote.id.version);
      } catch {
        throw new (_bitError().BitError)(`unable to find ${aspectId} in the remote. if this is a local aspect, please provide a version with your aspect (${aspectId}) to update to`);
      }
    }
    const allCompIds = pattern ? await this.workspace.idsByPattern(pattern) : this.workspace.listIds();
    const allComps = await this.workspace.getMany(allCompIds);
    const alreadyUpToDate = [];
    const updatedComponentIds = await Promise.all(allComps.map(async comp => {
      const aspect = comp.state.aspects.get(aspectCompId.toStringWithoutVersion());
      if (!aspect) return undefined;
      if (aspect.id.version === aspectCompId.version) {
        // nothing to update
        alreadyUpToDate.push(comp.id);
        return undefined;
      }
      // don't mark with minus if not exist in .bitmap. it's not needed. when the component is loaded, the
      // merge-operation of the aspects removes duplicate aspect-id with different versions.
      await this.workspace.removeSpecificComponentConfig(comp.id, aspect.id.toString(), false);
      await this.workspace.addSpecificComponentConfig(comp.id, aspectCompId.toString(), aspect.config);
      return comp.id;
    }));
    await this.workspace.bitMap.write(`aspect-update (${aspectCompId})`);
    return {
      updated: (0, _lodash().compact)(updatedComponentIds),
      alreadyUpToDate
    };
  }

  /**
   * override the dependency configuration of the component environment.
   */
  overrideDependencies(dependencyPolicy) {
    return this.envs.override({
      getDependencies: async () => {
        const reactDeps = await this.aspectEnv.getDependencies();
        return (0, _lodash().merge)(reactDeps, dependencyPolicy);
      }
    });
  }

  /**
   * currently, it validates envs/envs only. If needed for other aspects, create a slot, let aspects register to it,
   * then call the validation of all aspects from here.
   */
  validateAspectsBeforePersist(extensionDataList) {
    const envExt = extensionDataList.findCoreExtension(_envs().EnvsAspect.id);
    if (envExt) {
      const result = this.envs.validateEnvId(envExt);
      if (result) return result;
    }
    const depResolverExt = extensionDataList.findCoreExtension(_dependencyResolver().DependencyResolverAspect.id);
    if (depResolverExt) {
      const result = this.depsResolver.validateAspectData(depResolverExt.data);
      if (result) return result;
    }
  }
  static async provider([react, envs, builder, aspectLoader, compiler, generator, workspace, cli, loggerMain, workerMain, devFilesMain, depResolver], config, slots, harmony) {
    const logger = loggerMain.createLogger(_aspect().AspectAspect.id);
    const aspectEnv = envs.merge(new (_aspect2().AspectEnv)(react.reactEnv, aspectLoader, devFilesMain, compiler, workerMain, logger), react.reactEnv);
    const coreExporterTask = new (_coreExporter().CoreExporterTask)(aspectEnv, aspectLoader);
    if (!__dirname.includes('@teambit/bit')) {
      builder.registerBuildTasks([coreExporterTask]);
    }
    envs.registerEnv(aspectEnv);
    if (generator) {
      const envContext = new (_envs().EnvContext)(_componentId().ComponentID.fromString(_react().ReactAspect.id), loggerMain, workerMain, harmony);
      generator.registerComponentTemplate(() => (0, _aspect4().getTemplates)(envContext));
    }
    const aspectMain = new AspectMain(aspectEnv, envs, workspace, aspectLoader, depResolver);
    const aspectCmd = new (_aspect3().AspectCmd)();
    aspectCmd.commands = [new (_aspect3().ListAspectCmd)(aspectMain), new (_aspect3().ListCoreAspectCmd)(aspectMain), new (_aspect3().GetAspectCmd)(aspectMain), new (_aspect3().SetAspectCmd)(aspectMain), new (_aspect3().UnsetAspectCmd)(aspectMain), new (_aspect3().UpdateAspectCmd)(aspectMain)];
    cli.register(aspectCmd);
    _legacy().ExtensionDataList.validateBeforePersistHook = aspectMain.validateAspectsBeforePersist.bind(aspectMain);
    return aspectMain;
  }
}
exports.AspectMain = AspectMain;
_defineProperty(AspectMain, "runtime", _cli().MainRuntime);
_defineProperty(AspectMain, "dependencies", [_react().ReactAspect, _envs().EnvsAspect, _builder().BuilderAspect, _aspectLoader().AspectLoaderAspect, _compiler().CompilerAspect, _generator().GeneratorAspect, _workspace().WorkspaceAspect, _cli().CLIAspect, _logger().LoggerAspect, _worker().WorkerAspect, _devFiles().DevFilesAspect, _dependencyResolver().DependencyResolverAspect]);
_aspect().AspectAspect.addRuntime(AspectMain);

//# sourceMappingURL=aspect.main.runtime.js.map