export async function compileTsp()

in tools/tsp-client/src/typespec.ts [75:177]


export async function compileTsp({
  emitterPackage,
  outputPath,
  resolvedMainFilePath,
  additionalEmitterOptions,
  saveInputs,
  trace,
}: {
  emitterPackage: string;
  outputPath: string;
  resolvedMainFilePath: string;
  additionalEmitterOptions?: string;
  saveInputs?: boolean;
  trace?: string[];
}): Promise<[boolean, string]> {
  const parsedEntrypoint = getDirectoryPath(resolvedMainFilePath);
  const { compile, NodeHost, resolveCompilerOptions, formatDiagnostic } =
    await importTsp(parsedEntrypoint);

  const outputDir = resolvePath(outputPath);
  const overrideOptions: Record<string, Record<string, string>> = {
    [emitterPackage]: {
      "emitter-output-dir": outputDir,
    },
  };
  const emitterOverrideOptions = overrideOptions[emitterPackage] ?? { [emitterPackage]: {} };
  if (saveInputs) {
    emitterOverrideOptions["save-inputs"] = "true";
  }
  if (additionalEmitterOptions) {
    additionalEmitterOptions.split(";").forEach((option) => {
      const [key, value] = option.split("=");
      if (key && value) {
        emitterOverrideOptions[key] = value;
      }
    });
  }
  const overrides: Partial<ResolveCompilerOptionsOptions["overrides"]> = {
    outputDir,
    emit: [emitterPackage],
    options: overrideOptions,
    trace: trace,
  };
  Logger.info(`Compiling tsp using ${emitterPackage}...`);
  const [options, diagnostics] = await resolveCompilerOptions(NodeHost, {
    cwd: process.cwd(),
    entrypoint: resolvedMainFilePath,
    overrides,
  });
  Logger.debug(`Compiler options: ${JSON.stringify(options)}`);

  const cliOptions = Object.entries(options.options?.[emitterPackage] ?? {})
    .map(([key, value]) => {
      if (typeof value === "object") {
        value = JSON.stringify(value);
      }
      return `--option ${key}=${value}`;
    })
    .join(" ");

  const exampleCmd = `npx tsp compile ${resolvedMainFilePath} --emit ${emitterPackage} ${cliOptions}`;

  if (diagnostics.length > 0) {
    let errorDiagnostic = false;
    // This should not happen, but if it does, we should log it.
    Logger.warn(
      "Diagnostics were reported while resolving compiler options. Use the `--debug` flag to see if there is warning diagnostic output.",
    );
    for (const diagnostic of diagnostics) {
      if (diagnostic.severity === "error") {
        Logger.error(formatDiagnostic(diagnostic));
        errorDiagnostic = true;
      } else {
        Logger.debug(formatDiagnostic(diagnostic));
      }
    }
    if (errorDiagnostic) {
      return [false, exampleCmd];
    }
  }

  const program = await compile(NodeHost, resolvedMainFilePath, options);

  if (program.diagnostics.length > 0) {
    let errorDiagnostic = false;
    Logger.warn(
      "Diagnostics were reported during compilation. Use the `--debug` flag to see if there is warning diagnostic output.",
    );
    for (const diagnostic of program.diagnostics) {
      if (diagnostic.severity === "error") {
        Logger.error(formatDiagnostic(diagnostic));
        errorDiagnostic = true;
      } else {
        Logger.debug(formatDiagnostic(diagnostic));
      }
    }
    if (errorDiagnostic) {
      return [false, exampleCmd];
    }
  }
  Logger.success("generation complete");
  return [true, exampleCmd];
}