'use strict';

var chalk = require('chalk');
var fs = require('fs-extra');
var path = require('path');
var pLimit = require('p-limit');
var os = require('os');
var tar = require('tar');
var partition = require('lodash/partition');
var index = require('./index-CCLafGQH.cjs.js');
var run = require('./run-BcxUFacd.cjs.js');
var rollup = require('rollup');
var commonjs = require('@rollup/plugin-commonjs');
var resolve = require('@rollup/plugin-node-resolve');
var postcss = require('rollup-plugin-postcss');
var esbuild = require('rollup-plugin-esbuild');
var svgr = require('@svgr/rollup');
var dts = require('rollup-plugin-dts');
var json = require('@rollup/plugin-json');
var yaml = require('@rollup/plugin-yaml');
var rollupPluginutils = require('rollup-pluginutils');
var svgrTemplate = require('./svgrTemplate-BTjBQ3by.cjs.js');
var entryPoints = require('./entryPoints-CoHH4lBA.cjs.js');
var cliNode = require('@backstage/cli-node');
var parallel = require('./parallel-BszNaKyc.cjs.js');
var productionPack = require('./productionPack-DotlEIE2.cjs.js');

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

var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
var pLimit__default = /*#__PURE__*/_interopDefaultCompat(pLimit);
var tar__default = /*#__PURE__*/_interopDefaultCompat(tar);
var partition__default = /*#__PURE__*/_interopDefaultCompat(partition);
var commonjs__default = /*#__PURE__*/_interopDefaultCompat(commonjs);
var resolve__default = /*#__PURE__*/_interopDefaultCompat(resolve);
var postcss__default = /*#__PURE__*/_interopDefaultCompat(postcss);
var esbuild__default = /*#__PURE__*/_interopDefaultCompat(esbuild);
var svgr__default = /*#__PURE__*/_interopDefaultCompat(svgr);
var dts__default = /*#__PURE__*/_interopDefaultCompat(dts);
var json__default = /*#__PURE__*/_interopDefaultCompat(json);
var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);

function forwardFileImports(options) {
  const filter = rollupPluginutils.createFilter(options.include, options.exclude);
  const exportedFiles = /* @__PURE__ */ new Set();
  const generatedFor = /* @__PURE__ */ new Set();
  return {
    name: "forward-file-imports",
    async generateBundle(outputOptions, bundle, isWrite) {
      if (!isWrite) {
        return;
      }
      const dir = outputOptions.dir || path.dirname(outputOptions.file);
      if (generatedFor.has(dir)) {
        return;
      }
      for (const output of Object.values(bundle)) {
        if (output.type !== "chunk") {
          continue;
        }
        const chunk = output;
        if (!chunk.facadeModuleId) {
          continue;
        }
        generatedFor.add(dir);
        const srcRoot = path.dirname(chunk.facadeModuleId);
        await Promise.all(
          Array.from(exportedFiles).map(async (exportedFile) => {
            const outputPath = path.relative(srcRoot, exportedFile);
            const targetFile = path.resolve(dir, outputPath);
            await fs__default.default.ensureDir(path.dirname(targetFile));
            await fs__default.default.copyFile(exportedFile, targetFile);
          })
        );
        return;
      }
    },
    options(inputOptions) {
      const origExternal = inputOptions.external;
      const external = (id, importer, isResolved) => {
        if (typeof origExternal === "function" && origExternal(id, importer, isResolved)) {
          return true;
        }
        if (Array.isArray(origExternal) && origExternal.includes(id)) {
          return true;
        }
        if (!filter(id)) {
          return false;
        }
        if (!importer) {
          throw new Error(`Unknown importer of file module ${id}`);
        }
        const fullId = isResolved ? id : path.resolve(path.dirname(importer), id);
        exportedFiles.add(fullId);
        return true;
      };
      return { ...inputOptions, external };
    }
  };
}

var Output = /* @__PURE__ */ ((Output2) => {
  Output2[Output2["esm"] = 0] = "esm";
  Output2[Output2["cjs"] = 1] = "cjs";
  Output2[Output2["types"] = 2] = "types";
  return Output2;
})(Output || {});

const SCRIPT_EXTS = [".js", ".jsx", ".ts", ".tsx"];
function isFileImport(source) {
  if (source.startsWith(".")) {
    return true;
  }
  if (source.startsWith("/")) {
    return true;
  }
  if (source.match(/[a-z]:/i)) {
    return true;
  }
  return false;
}
async function makeRollupConfigs(options) {
  var _a;
  const configs = new Array();
  const targetDir = (_a = options.targetDir) != null ? _a : index.paths.targetDir;
  let targetPkg = options.packageJson;
  if (!targetPkg) {
    const packagePath = path.resolve(targetDir, "package.json");
    targetPkg = await fs__default.default.readJson(packagePath);
  }
  const onwarn = ({ code, message }) => {
    if (code === "EMPTY_BUNDLE") {
      return;
    }
    if (options.logPrefix) {
      console.log(options.logPrefix + message);
    } else {
      console.log(message);
    }
  };
  const distDir = path.resolve(targetDir, "dist");
  const entryPoints$1 = entryPoints.readEntryPoints(targetPkg);
  const scriptEntryPoints = entryPoints$1.filter(
    (e) => SCRIPT_EXTS.includes(e.ext)
  );
  if (options.outputs.has(Output.cjs) || options.outputs.has(Output.esm)) {
    const output = new Array();
    const mainFields = ["module", "main"];
    if (options.outputs.has(Output.cjs)) {
      output.push({
        dir: distDir,
        entryFileNames: `[name].cjs.js`,
        chunkFileNames: `cjs/[name]-[hash].cjs.js`,
        format: "commonjs",
        interop: "compat",
        sourcemap: true,
        exports: "named"
      });
    }
    if (options.outputs.has(Output.esm)) {
      output.push({
        dir: distDir,
        entryFileNames: `[name].esm.js`,
        chunkFileNames: `esm/[name]-[hash].esm.js`,
        format: "module",
        sourcemap: true
      });
      mainFields.unshift("browser");
    }
    configs.push({
      input: Object.fromEntries(
        scriptEntryPoints.map((e) => [e.name, path.resolve(targetDir, e.path)])
      ),
      output,
      onwarn,
      preserveEntrySignatures: "strict",
      // All module imports are always marked as external
      external: (source, importer, isResolved) => Boolean(importer && !isResolved && !isFileImport(source)),
      plugins: [
        resolve__default.default({ mainFields }),
        commonjs__default.default({
          include: /node_modules/,
          exclude: [/\/[^/]+\.(?:stories|test)\.[^/]+$/]
        }),
        postcss__default.default(),
        forwardFileImports({
          exclude: /\.icon\.svg$/,
          include: [
            /\.svg$/,
            /\.png$/,
            /\.gif$/,
            /\.jpg$/,
            /\.jpeg$/,
            /\.eot$/,
            /\.woff$/,
            /\.woff2$/,
            /\.ttf$/,
            /\.md$/
          ]
        }),
        json__default.default(),
        yaml__default.default(),
        svgr__default.default({
          include: /\.icon\.svg$/,
          template: svgrTemplate.svgrTemplate
        }),
        esbuild__default.default({
          target: "es2019",
          minify: options.minify
        })
      ]
    });
  }
  if (options.outputs.has(Output.types)) {
    const input = Object.fromEntries(
      scriptEntryPoints.map((e) => [
        e.name,
        index.paths.resolveTargetRoot(
          "dist-types",
          path.relative(index.paths.targetRoot, targetDir),
          e.path.replace(/\.(?:ts|tsx)$/, ".d.ts")
        )
      ])
    );
    for (const path$1 of Object.values(input)) {
      const declarationsExist = await fs__default.default.pathExists(path$1);
      if (!declarationsExist) {
        const declarationPath = path.relative(targetDir, path$1);
        throw new Error(
          `No declaration files found at ${declarationPath}, be sure to run ${chalk__default.default.bgRed.white(
            "yarn tsc"
          )} to generate .d.ts files before packaging`
        );
      }
    }
    configs.push({
      input,
      output: {
        dir: distDir,
        entryFileNames: `[name].d.ts`,
        chunkFileNames: `types/[name]-[hash].d.ts`,
        format: "es"
      },
      external: [
        /\.css$/,
        /\.scss$/,
        /\.sass$/,
        /\.svg$/,
        /\.eot$/,
        /\.woff$/,
        /\.woff2$/,
        /\.ttf$/
      ],
      onwarn,
      plugins: [dts__default.default()]
    });
  }
  return configs;
}

function formatErrorMessage(error) {
  var _a;
  let msg = "";
  if (error.code === "PLUGIN_ERROR") {
    if (error.plugin === "esbuild") {
      msg += `${error.message}`;
      if ((_a = error.errors) == null ? void 0 : _a.length) {
        msg += `

`;
        for (const { text, location } of error.errors) {
          const { line, column } = location;
          const path$1 = path.relative(index.paths.targetDir, error.id);
          const loc = chalk__default.default.cyan(`${path$1}:${line}:${column}`);
          if (text === 'Unexpected "<"' && error.id.endsWith(".js")) {
            msg += `${loc}: ${text}, JavaScript files with JSX should use a .jsx extension`;
          } else {
            msg += `${loc}: ${text}`;
          }
        }
      }
    } else {
      msg += `(plugin ${error.plugin}) ${error}
`;
    }
  } else {
    if (error.loc) {
      const file = `${index.paths.resolveTarget(error.loc.file || error.id)}`;
      const pos = `${error.loc.line}:${error.loc.column}`;
      msg += `${file} [${pos}]
`;
    } else if (error.id) {
      msg += `${index.paths.resolveTarget(error.id)}
`;
    }
    msg += `${error}
`;
    if (error.url) {
      msg += `${chalk__default.default.cyan(error.url)}
`;
    }
    if (error.frame) {
      msg += `${chalk__default.default.dim(error.frame)}
`;
    }
  }
  return msg;
}
async function rollupBuild(config) {
  try {
    const bundle = await rollup.rollup(config);
    if (config.output) {
      for (const output of [config.output].flat()) {
        await bundle.generate(output);
        await bundle.write(output);
      }
    }
  } catch (error) {
    throw new Error(formatErrorMessage(error));
  }
}
const buildPackage = async (options) => {
  try {
    const { resolutions } = await fs__default.default.readJson(
      index.paths.resolveTargetRoot("package.json")
    );
    if (resolutions == null ? void 0 : resolutions.esbuild) {
      console.warn(
        chalk__default.default.red(
          'Your root package.json contains a "resolutions" entry for "esbuild". This was included in older @backstage/create-app templates in order to work around build issues that have since been fixed. Please remove the entry and run `yarn install`'
        )
      );
    }
  } catch {
  }
  const rollupConfigs = await makeRollupConfigs(options);
  await fs__default.default.remove(index.paths.resolveTarget("dist"));
  const buildTasks = rollupConfigs.map(rollupBuild);
  await Promise.all(buildTasks);
};
const buildPackages = async (options) => {
  if (options.some((opt) => !opt.targetDir)) {
    throw new Error("targetDir must be set for all build options");
  }
  const rollupConfigs = await Promise.all(options.map(makeRollupConfigs));
  await Promise.all(
    options.map(({ targetDir }) => fs__default.default.remove(path.resolve(targetDir, "dist")))
  );
  const buildTasks = rollupConfigs.flat().map((opts) => () => rollupBuild(opts));
  await parallel.runParallelWorkers({
    items: buildTasks,
    worker: async (task) => task()
  });
};
function getOutputsForRole(role) {
  const outputs = /* @__PURE__ */ new Set();
  for (const output of cliNode.PackageRoles.getRoleInfo(role).output) {
    if (output === "cjs") {
      outputs.add(Output.cjs);
    }
    if (output === "esm") {
      outputs.add(Output.esm);
    }
    if (output === "types") {
      outputs.add(Output.types);
    }
  }
  return outputs;
}

const UNSAFE_PACKAGES = [
  ...Object.keys(index.dependencies),
  ...Object.keys(index.devDependencies)
];
function prefixLogFunc(prefix, out) {
  return (data) => {
    for (const line of data.toString("utf8").split(/\r?\n/)) {
      process[out].write(`${prefix} ${line}
`);
    }
  };
}
async function createDistWorkspace(packageNames, options = {}) {
  var _a, _b, _c, _d, _e, _f;
  const targetDir = (_a = options.targetDir) != null ? _a : await fs__default.default.mkdtemp(path.resolve(os.tmpdir(), "dist-workspace"));
  const packages = await cliNode.PackageGraph.listTargetPackages();
  const packageGraph = cliNode.PackageGraph.fromPackages(packages);
  const targetNames = packageGraph.collectPackageNames(packageNames, (node) => {
    if (node.packageJson.bundled) {
      return void 0;
    }
    return node.publishedLocalDependencies.keys();
  });
  const targets = Array.from(targetNames).map((name) => packageGraph.get(name));
  if (options.buildDependencies) {
    const exclude = (_b = options.buildExcludes) != null ? _b : [];
    const configPaths = (_c = options.configPaths) != null ? _c : [];
    const toBuild = new Set(
      targets.map((_) => _.name).filter((name) => !exclude.includes(name))
    );
    const standardBuilds = new Array();
    const customBuild = new Array();
    for (const pkg of packages) {
      if (!toBuild.has(pkg.packageJson.name)) {
        continue;
      }
      const role = (_d = pkg.packageJson.backstage) == null ? void 0 : _d.role;
      if (!role) {
        console.warn(
          `Building ${pkg.packageJson.name} separately because it has no role`
        );
        customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });
        continue;
      }
      const buildScript = (_e = pkg.packageJson.scripts) == null ? void 0 : _e.build;
      if (!buildScript) {
        customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });
        continue;
      }
      if (!buildScript.startsWith("backstage-cli package build")) {
        console.warn(
          `Building ${pkg.packageJson.name} separately because it has a custom build script, '${buildScript}'`
        );
        customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name });
        continue;
      }
      if (cliNode.PackageRoles.getRoleInfo(role).output.includes("bundle")) {
        console.warn(
          `Building ${pkg.packageJson.name} separately because it is a bundled package`
        );
        const args = buildScript.includes("--config") ? [] : configPaths.map((p) => ["--config", p]).flat();
        customBuild.push({ dir: pkg.dir, name: pkg.packageJson.name, args });
        continue;
      }
      const outputs = getOutputsForRole(role);
      outputs.delete(Output.types);
      if (outputs.size > 0) {
        standardBuilds.push({
          targetDir: pkg.dir,
          packageJson: pkg.packageJson,
          outputs,
          logPrefix: `${chalk__default.default.cyan(path.relative(index.paths.targetRoot, pkg.dir))}: `,
          minify: options.minify
        });
      }
    }
    await buildPackages(standardBuilds);
    if (customBuild.length > 0) {
      await parallel.runParallelWorkers({
        items: customBuild,
        worker: async ({ name, dir, args }) => {
          await run.run("yarn", ["run", "build", ...args || []], {
            cwd: dir,
            stdoutLogFunc: prefixLogFunc(`${name}: `, "stdout"),
            stderrLogFunc: prefixLogFunc(`${name}: `, "stderr")
          });
        }
      });
    }
  }
  await moveToDistWorkspace(
    targetDir,
    targets,
    Boolean(options.alwaysYarnPack)
  );
  const files = (_f = options.files) != null ? _f : ["yarn.lock", "package.json"];
  for (const file of files) {
    const src = typeof file === "string" ? file : file.src;
    const dest = typeof file === "string" ? file : file.dest;
    await fs__default.default.copy(index.paths.resolveTargetRoot(src), path.resolve(targetDir, dest));
  }
  if (options.skeleton) {
    const skeletonFiles = targets.map((target) => {
      const dir = path.relative(index.paths.targetRoot, target.dir);
      return path.join(dir, "package.json");
    }).sort();
    await tar__default.default.create(
      {
        file: path.resolve(targetDir, options.skeleton),
        cwd: targetDir,
        portable: true,
        noMtime: true,
        gzip: options.skeleton.endsWith(".gz")
      },
      skeletonFiles
    );
  }
  return targetDir;
}
const FAST_PACK_SCRIPTS = [
  void 0,
  "backstage-cli prepack",
  "backstage-cli package prepack"
];
async function moveToDistWorkspace(workspaceDir, localPackages, alwaysYarnPack) {
  const [fastPackPackages, slowPackPackages] = partition__default.default(
    localPackages,
    (pkg) => {
      var _a;
      return !alwaysYarnPack && FAST_PACK_SCRIPTS.includes((_a = pkg.packageJson.scripts) == null ? void 0 : _a.prepack);
    }
  );
  await Promise.all(
    fastPackPackages.map(async (target) => {
      console.log(`Moving ${target.name} into dist workspace`);
      const outputDir = path.relative(index.paths.targetRoot, target.dir);
      const absoluteOutputPath = path.resolve(workspaceDir, outputDir);
      await productionPack.productionPack({
        packageDir: target.dir,
        targetDir: absoluteOutputPath
      });
    })
  );
  async function pack(target, archive) {
    var _a, _b;
    console.log(`Repacking ${target.name} into dist workspace`);
    const archivePath = path.resolve(workspaceDir, archive);
    await run.run("yarn", ["pack", "--filename", archivePath], {
      cwd: target.dir
    });
    if ((_b = (_a = target.packageJson) == null ? void 0 : _a.scripts) == null ? void 0 : _b.postpack) {
      await run.run("yarn", ["postpack"], { cwd: target.dir });
    }
    const outputDir = path.relative(index.paths.targetRoot, target.dir);
    const absoluteOutputPath = path.resolve(workspaceDir, outputDir);
    await fs__default.default.ensureDir(absoluteOutputPath);
    await tar__default.default.extract({
      file: archivePath,
      cwd: absoluteOutputPath,
      strip: 1
    });
    await fs__default.default.remove(archivePath);
    if (target.packageJson.bundled) {
      const pkgJson = await fs__default.default.readJson(
        path.resolve(absoluteOutputPath, "package.json")
      );
      delete pkgJson.dependencies;
      delete pkgJson.devDependencies;
      delete pkgJson.peerDependencies;
      delete pkgJson.optionalDependencies;
      await fs__default.default.writeJson(
        path.resolve(absoluteOutputPath, "package.json"),
        pkgJson,
        {
          spaces: 2
        }
      );
    }
  }
  const [unsafePackages, safePackages] = partition__default.default(
    slowPackPackages,
    (p) => UNSAFE_PACKAGES.includes(p.name)
  );
  for (const target of unsafePackages) {
    await pack(target, `temp-package.tgz`);
  }
  const limit = pLimit__default.default(10);
  await Promise.all(
    safePackages.map(
      (target, index) => limit(() => pack(target, `temp-package-${index}.tgz`))
    )
  );
}

exports.Output = Output;
exports.buildPackage = buildPackage;
exports.buildPackages = buildPackages;
exports.createDistWorkspace = createDistWorkspace;
exports.getOutputsForRole = getOutputsForRole;
//# sourceMappingURL=createDistWorkspace-CLrZPAfL.cjs.js.map
