UNPKG

typedoc

Version:

Create api documentation for TypeScript projects.

711 lines (710 loc) 35.8 kB
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; import * as Path from "path"; import ts from "typescript"; import { Deserializer, Serializer } from "./serialization/index.js"; import { Converter } from "./converter/index.js"; import { Renderer } from "./output/renderer.js"; import { ReflectionSymbolId } from "./models/index.js"; import { AbstractComponent, FancyConsoleLogger, loadPlugins, PackageJsonReader, TSConfigReader, TypeDocReader, writeFile, } from "./utils/index.js"; import { Option, Options } from "./utils/index.js"; import { rootPackageOptions } from "./utils/options/declaration.js"; import { i18n, Logger, LogLevel, unique } from "#utils"; import { ok } from "assert"; import { EntryPointStrategy, getEntryPoints, getPackageDirectories, getWatchEntryPoints, inferEntryPoints, } from "./utils/entry-point.js"; import { nicePath, normalizePath } from "./utils/paths.js"; import { getLoadedPaths, hasBeenLoadedMultipleTimes, isDebugging } from "./utils/general.js"; import { validateExports } from "./validation/exports.js"; import { validateDocumentation } from "./validation/documentation.js"; import { validateLinks } from "./validation/links.js"; import { ApplicationEvents } from "./application-events.js"; import { deriveRootDir, findTsConfigFile, glob, readFile } from "#node-utils"; import { FileRegistry } from "./models/FileRegistry.js"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; import { createRequire } from "module"; import { Outputs } from "./output/output.js"; import { validateMergeModuleWith } from "./validation/unusedMergeModuleWith.js"; import { diagnostic, diagnostics } from "./utils/loggers.js"; import { ValidatingFileRegistry } from "./utils/ValidatingFileRegistry.js"; import { addInferredDeclarationMapPaths } from "./converter/factories/symbol-id.js"; import { Internationalization } from "./internationalization/internationalization.js"; const packageInfo = JSON.parse(readFileSync(Path.join(fileURLToPath(import.meta.url), "../../../package.json"), "utf8")); const supportedVersionMajorMinor = packageInfo.peerDependencies.typescript .split("||") .map((version) => version.replace(/^\s*|\.x\s*$/g, "")); const DETECTOR = Symbol(); export function createAppForTesting() { // @ts-expect-error private constructor const app = new Application(DETECTOR); app.files = new FileRegistry(); return app; } const DEFAULT_READERS = [ new TypeDocReader(), new PackageJsonReader(), new TSConfigReader(), ]; /** * The default TypeDoc main application class. * * This class holds the two main components of TypeDoc, the {@link Converter} and * the {@link Renderer}. When running TypeDoc, first the {@link Converter} is invoked which * generates a {@link ProjectReflection} from the passed in source files. The * {@link ProjectReflection} is a hierarchical model representation of the TypeScript * project. Afterwards the model is passed to the {@link Renderer} which uses an instance * of {@link Theme} to generate the final documentation. * * Both the {@link Converter} and the {@link Renderer} emit a series of events while processing the project. * Subscribe to these Events to control the application flow or alter the output. * * @remarks * * Access to an Application instance can be retrieved with {@link Application.bootstrap} or * {@link Application.bootstrapWithPlugins}. It can not be constructed manually. * * @group None * @summary Root level class which contains most useful behavior. */ let Application = (() => { let _classSuper = AbstractComponent; let _lang_decorators; let _lang_initializers = []; let _lang_extraInitializers = []; let _skipErrorChecking_decorators; let _skipErrorChecking_initializers = []; let _skipErrorChecking_extraInitializers = []; let _entryPointStrategy_decorators; let _entryPointStrategy_initializers = []; let _entryPointStrategy_extraInitializers = []; let _entryPoints_decorators; let _entryPoints_initializers = []; let _entryPoints_extraInitializers = []; return class Application extends _classSuper { static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _lang_decorators = [Option("lang")]; _skipErrorChecking_decorators = [Option("skipErrorChecking")]; _entryPointStrategy_decorators = [Option("entryPointStrategy")]; _entryPoints_decorators = [Option("entryPoints")]; __esDecorate(this, null, _lang_decorators, { kind: "accessor", name: "lang", static: false, private: false, access: { has: obj => "lang" in obj, get: obj => obj.lang, set: (obj, value) => { obj.lang = value; } }, metadata: _metadata }, _lang_initializers, _lang_extraInitializers); __esDecorate(this, null, _skipErrorChecking_decorators, { kind: "accessor", name: "skipErrorChecking", static: false, private: false, access: { has: obj => "skipErrorChecking" in obj, get: obj => obj.skipErrorChecking, set: (obj, value) => { obj.skipErrorChecking = value; } }, metadata: _metadata }, _skipErrorChecking_initializers, _skipErrorChecking_extraInitializers); __esDecorate(this, null, _entryPointStrategy_decorators, { kind: "accessor", name: "entryPointStrategy", static: false, private: false, access: { has: obj => "entryPointStrategy" in obj, get: obj => obj.entryPointStrategy, set: (obj, value) => { obj.entryPointStrategy = value; } }, metadata: _metadata }, _entryPointStrategy_initializers, _entryPointStrategy_extraInitializers); __esDecorate(this, null, _entryPoints_decorators, { kind: "accessor", name: "entryPoints", static: false, private: false, access: { has: obj => "entryPoints" in obj, get: obj => obj.entryPoints, set: (obj, value) => { obj.entryPoints = value; } }, metadata: _metadata }, _entryPoints_initializers, _entryPoints_extraInitializers); if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } _logger = new FancyConsoleLogger(); /** * The converter used to create the declaration reflections. */ converter; outputs = new Outputs(this); /** * The renderer used to generate the HTML documentation output. */ renderer; /** * The serializer used to generate JSON output. */ serializer = new Serializer(); /** * The deserializer used to restore previously serialized JSON output. */ deserializer = new Deserializer(this._logger); /** * The logger that should be used to output messages. */ get logger() { return this._logger; } set logger(l) { this._logger = l; this.deserializer.logger = l; } /** * Internationalization module which supports translating according to * the `lang` option. */ internationalization = new Internationalization(); options = new Options(); files = new ValidatingFileRegistry(); #lang_accessor_storage = __runInitializers(this, _lang_initializers, void 0); /** @internal */ get lang() { return this.#lang_accessor_storage; } set lang(value) { this.#lang_accessor_storage = value; } #skipErrorChecking_accessor_storage = (__runInitializers(this, _lang_extraInitializers), __runInitializers(this, _skipErrorChecking_initializers, void 0)); /** @internal */ get skipErrorChecking() { return this.#skipErrorChecking_accessor_storage; } set skipErrorChecking(value) { this.#skipErrorChecking_accessor_storage = value; } #entryPointStrategy_accessor_storage = (__runInitializers(this, _skipErrorChecking_extraInitializers), __runInitializers(this, _entryPointStrategy_initializers, void 0)); /** @internal */ get entryPointStrategy() { return this.#entryPointStrategy_accessor_storage; } set entryPointStrategy(value) { this.#entryPointStrategy_accessor_storage = value; } #entryPoints_accessor_storage = (__runInitializers(this, _entryPointStrategy_extraInitializers), __runInitializers(this, _entryPoints_initializers, void 0)); /** @internal */ get entryPoints() { return this.#entryPoints_accessor_storage; } set entryPoints(value) { this.#entryPoints_accessor_storage = value; } /** * The version number of TypeDoc. */ static VERSION = packageInfo.version; /** * Emitted after plugins have been loaded and options have been read, but before they have been frozen. * The listener will be given an instance of {@link Application}. */ static EVENT_BOOTSTRAP_END = ApplicationEvents.BOOTSTRAP_END; /** * Emitted after a project has been deserialized from JSON. * The listener will be given an instance of {@link ProjectReflection}. */ static EVENT_PROJECT_REVIVE = ApplicationEvents.REVIVE; /** * Emitted when validation is being run. * The listener will be given an instance of {@link ProjectReflection}. */ static EVENT_VALIDATE_PROJECT = ApplicationEvents.VALIDATE_PROJECT; /** * Create a new TypeDoc application instance. */ constructor(detector) { if (detector !== DETECTOR) { throw new Error("An application handle must be retrieved with Application.bootstrap or Application.bootstrapWithPlugins"); } super(null); // We own ourselves this.converter = new Converter(this); this.renderer = new Renderer(this); this.outputs.addOutput("json", async (out, project) => { const ser = this.serializer.projectToObject(project, normalizePath(process.cwd())); const space = this.options.getValue("pretty") ? "\t" : ""; await writeFile(out, JSON.stringify(ser, null, space) + "\n"); }); this.outputs.addOutput("html", async (out, project) => { await this.renderer.render(project, out); }); } /** * Initialize TypeDoc, loading plugins if applicable. */ static async bootstrapWithPlugins(options = {}, readers = DEFAULT_READERS) { const app = new Application(DETECTOR); readers.forEach((r) => app.options.addReader(r)); app.options.reset(); app.setOptions(options, /* reportErrors */ false); app.internationalization.setLocale(app.lang); await app.options.read(new Logger(), undefined, (path) => app.watchConfigFile(path)); app.internationalization.setLocale(app.lang); app.logger.level = app.options.getValue("logLevel"); await loadPlugins(app, app.options.getValue("plugin")); await app._bootstrap(options); return app; } /** * Initialize TypeDoc without loading plugins. * * @example * Initialize the application with pretty-printing output disabled. * ```ts * const app = await Application.bootstrap({ pretty: false }); * ``` * * @param options Options to set during initialization * @param readers Option readers to use to discover options from config files. */ static async bootstrap(options = {}, readers = DEFAULT_READERS) { const app = new Application(DETECTOR); readers.forEach((r) => app.options.addReader(r)); await app._bootstrap(options); return app; } async _bootstrap(options) { this.options.reset(); this.setOptions(options, /* reportErrors */ false); this.internationalization.setLocale(this.lang); await this.options.read(this.logger, undefined, (path) => this.watchConfigFile(path)); this.setOptions(options); this.internationalization.setLocale(this.lang); if (isDebugging()) { this.logger.level = LogLevel.Verbose; } else { this.logger.level = this.options.getValue("logLevel"); } for (const [lang, locales] of Object.entries(this.options.getValue("locales"))) { this.internationalization.addTranslations(lang, locales); } if (hasBeenLoadedMultipleTimes()) { this.logger.warn(i18n.loaded_multiple_times_0(getLoadedPaths().join("\n\t"))); } this.trigger(ApplicationEvents.BOOTSTRAP_END, this); if (!this.internationalization.hasTranslations(this.lang)) { // Not internationalized as by definition we don't know what to include here. this.logger.warn(`Options specified "${this.lang}" as the language to use, but TypeDoc cannot provide translations for it.`); this.logger.info(("The languages that translations are available for are:\n\t" + this.internationalization .getSupportedLanguages() .join("\n\t"))); this.logger.info("You can define/override local locales with the `locales` option, or contribute them to TypeDoc!"); } if (this.options.getValue("useHostedBaseUrlForAbsoluteLinks") && !this.options.getValue("hostedBaseUrl")) { this.logger.warn(i18n.useHostedBaseUrlForAbsoluteLinks_requires_hostedBaseUrl()); this.options.setValue("useHostedBaseUrlForAbsoluteLinks", false); } } /** @internal */ setOptions(options, reportErrors = true) { let success = true; for (const [key, val] of Object.entries(options)) { try { this.options.setValue(key, val); } catch (error) { success = false; ok(error instanceof Error); if (reportErrors) { this.logger.error(error.message); } } } return success; } /** * Return the path to the TypeScript compiler. */ getTypeScriptPath() { const req = createRequire(import.meta.url); return nicePath(Path.dirname(req.resolve("typescript"))); } getTypeScriptVersion() { return ts.version; } getEntryPoints() { if (this.options.isSet("entryPoints")) { return this.getDefinedEntryPoints(); } return inferEntryPoints(this.logger, this.options); } /** * Gets the entry points to be documented according to the current `entryPoints` and `entryPointStrategy` options. * May return undefined if entry points fail to be expanded. */ getDefinedEntryPoints() { return getEntryPoints(this.logger, this.options); } /** * Run the converter for the given set of files and return the generated reflections. * * @returns An instance of ProjectReflection on success, undefined otherwise. */ async convert() { const start = Date.now(); this.logger.verbose(`Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`); if (this.entryPointStrategy === EntryPointStrategy.Merge) { return this._merge(); } if (this.entryPointStrategy === EntryPointStrategy.Packages) { return this._convertPackages(); } if (!supportedVersionMajorMinor.some((version) => version == ts.versionMajorMinor)) { this.logger.warn(i18n.unsupported_ts_version_0(supportedVersionMajorMinor.join(", "))); } const entryPoints = this.getEntryPoints(); if (!entryPoints) { // Fatal error already reported. return; } const programs = unique(entryPoints.map((e) => e.program)); this.logger.verbose(`Converting with ${programs.length} programs ${entryPoints.length} entry points`); if (this.skipErrorChecking === false) { const errors = programs.flatMap((program) => ts.getPreEmitDiagnostics(program)); if (errors.length) { diagnostics(this.logger, errors); return; } } if (this.options.getValue("emit") === "both") { for (const program of programs) { program.emit(); } } const startConversion = Date.now(); this.logger.verbose(`Finished getting entry points in ${Date.now() - start}ms`); const project = this.converter.convert(entryPoints); this.logger.verbose(`Finished conversion in ${Date.now() - startConversion}ms`); return project; } watchers = (__runInitializers(this, _entryPoints_extraInitializers), new Map()); _watchFile; criticalFiles = new Set(); clearWatches() { this.watchers.forEach((w) => w.close()); this.watchers.clear(); } watchConfigFile(path) { this.criticalFiles.add(path); } /** * Register that the current build depends on a file, so that in watch mode * the build will be repeated. Has no effect if a watch build is not * running, or if the file has already been registered. * * @param path The file to watch. It does not need to exist, and you should * in fact register files you look for, but which do not exist, so that if * they are created the build will re-run. (e.g. if you look through a list * of 5 possibilities and find the third, you should register the first 3.) * * @param shouldRestart Should the build be completely restarted? (This is * normally only used for configuration files -- i.e. files whose contents * determine how conversion, rendering, or compiling will be done, as * opposed to files that are only read *during* the conversion or * rendering.) */ watchFile(path, shouldRestart = false) { this._watchFile?.(path, shouldRestart); } /** * Run a convert / watch process. * * @param success Callback to run after each convert, receiving the project * @returns True if the watch process should be restarted due to a * configuration change, false for an options error */ async convertAndWatch(success) { if (!this.options.getValue("preserveWatchOutput") && this.logger instanceof FancyConsoleLogger) { ts.sys.clearScreen?.(); } this.logger.verbose(`Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`); if (!supportedVersionMajorMinor.some((version) => version == ts.versionMajorMinor)) { this.logger.warn(i18n.unsupported_ts_version_0(supportedVersionMajorMinor.join(", "))); } if (Object.keys(this.options.getCompilerOptions()).length === 0) { this.logger.warn(i18n.no_compiler_options_set()); } // Doing this is considerably more complicated, we'd need to manage an array of programs, not convert until all programs // have reported in the first time... just error out for now. I'm not convinced anyone will actually notice. if (this.options.getFileNames().length === 0) { this.logger.error(i18n.solution_not_supported_in_watch_mode()); return false; } // Support for packages mode is currently unimplemented if (this.entryPointStrategy !== EntryPointStrategy.Resolve && this.entryPointStrategy !== EntryPointStrategy.Expand) { this.logger.error(i18n.strategy_not_supported_in_watch_mode()); return false; } const tsconfigFile = findTsConfigFile(this.options.getValue("tsconfig")) ?? "tsconfig.json"; // We don't want to do it the first time to preserve initial debug status messages. They'll be lost // after the user saves a file, but better than nothing... let firstStatusReport = true; const host = ts.createWatchCompilerHost(tsconfigFile, this.options.fixCompilerOptions({}), ts.sys, ts.createEmitAndSemanticDiagnosticsBuilderProgram, (d) => diagnostic(this.logger, d), (status, newLine, _options, errorCount) => { if (!firstStatusReport && errorCount === void 0 && !this.options.getValue("preserveWatchOutput") && this.logger instanceof FancyConsoleLogger) { ts.sys.clearScreen?.(); } firstStatusReport = false; this.logger.info(ts.flattenDiagnosticMessageText(status.messageText, newLine)); }); let successFinished = true; let currentProgram; let lastProgram = currentProgram; let restarting = false; this._watchFile = (path, shouldRestart = false) => { this.logger.verbose(`Watching ${nicePath(path)}, shouldRestart=${shouldRestart}`); if (this.watchers.has(path)) return; this.watchers.set(path, host.watchFile(path, (file) => { if (shouldRestart) { restartMain(file); } else if (!currentProgram) { currentProgram = lastProgram; this.logger.info(i18n.file_0_changed_rebuilding(nicePath(file))); } if (successFinished) runSuccess(); }, 2000)); }; /** resolver for the returned promise */ let exitWatch; const restartMain = (file) => { if (restarting) return; this.logger.info(i18n.file_0_changed_restarting(nicePath(file))); restarting = true; currentProgram = undefined; this.clearWatches(); tsWatcher.close(); }; const runSuccess = () => { if (restarting && successFinished) { successFinished = false; exitWatch(true); return; } if (!currentProgram) { return; } if (successFinished) { if (this.options.getValue("emit") === "both" && currentProgram !== lastProgram) { currentProgram.emit(); } // Save for possible re-run due to non-.ts file change lastProgram = currentProgram; this.logger.resetErrors(); this.logger.resetWarnings(); const entryPoints = getWatchEntryPoints(this.logger, this.options, currentProgram); if (!entryPoints) { return; } this.clearWatches(); this.criticalFiles.forEach((path) => this.watchFile(path, true)); const project = this.converter.convert(entryPoints); currentProgram = undefined; successFinished = false; void success(project).then(() => { successFinished = true; runSuccess(); }); } }; const origAfterProgramCreate = host.afterProgramCreate; host.afterProgramCreate = (program) => { if (!restarting && ts.getPreEmitDiagnostics(program.getProgram()).length === 0) { currentProgram = program.getProgram(); runSuccess(); } origAfterProgramCreate?.(program); }; const tsWatcher = ts.createWatchProgram(host); // Don't return to caller until the watch needs to restart return await new Promise((res) => { exitWatch = res; }); } validate(project) { const checks = this.options.getValue("validation"); const start = Date.now(); // No point in validating exports when merging. Warnings will have already been emitted when // creating the project jsons that this run merges together. if (checks.notExported && this.entryPointStrategy !== EntryPointStrategy.Merge) { validateExports(project, this.logger, this.options.getValue("intentionallyNotExported")); } if (checks.notDocumented) { const packagesRequiringDocumentation = this.options.isSet("packagesRequiringDocumentation") ? this.options.getValue("packagesRequiringDocumentation") : [project.packageName ?? ReflectionSymbolId.UNKNOWN_PACKAGE]; validateDocumentation(project, this.logger, this.options.getValue("requiredToBeDocumented"), this.options.getValue("intentionallyNotDocumented"), packagesRequiringDocumentation); } if (checks.invalidLink) { validateLinks(project, this.logger); } if (checks.unusedMergeModuleWith) { validateMergeModuleWith(project, this.logger); } this.trigger(Application.EVENT_VALIDATE_PROJECT, project); this.logger.verbose(`Validation took ${Date.now() - start}ms`); } /** * Render outputs selected with options for the specified project */ async generateOutputs(project) { await this.outputs.writeOutputs(project); } /** * Render HTML for the given project */ async generateDocs(project, out) { await this.outputs.writeOutput({ name: "html", path: out, }, project); } /** * Write the reflections to a json file. * * @param out The path and file name of the target file. * @returns Whether the JSON file could be written successfully. */ async generateJson(project, out) { await this.outputs.writeOutput({ name: "json", path: out, }, project); } /** * Print the version number. */ toString() { return [ "", `TypeDoc ${Application.VERSION}`, `Using TypeScript ${this.getTypeScriptVersion()} from ${this.getTypeScriptPath()}`, "", ].join("\n"); } async _convertPackages() { if (!this.options.isSet("entryPoints")) { this.logger.error(i18n.no_entry_points_for_packages()); return; } const packageDirs = getPackageDirectories(this.logger, this.options, this.options.getValue("entryPoints")); if (packageDirs.length === 0) { this.logger.error(i18n.failed_to_find_packages()); return; } const origFiles = this.files; const origOptions = this.options; const projects = []; for (const opt of Object.keys(this.options.getValue("packageOptions"))) { if (rootPackageOptions.includes(opt)) { this.logger.warn(i18n.package_option_0_should_be_specified_at_root(opt)); } } const projectsToConvert = []; // Generate a json file for each package for (const dir of packageDirs) { this.logger.verbose(`Reading project at ${nicePath(dir)}`); let opts; try { opts = origOptions.copyForPackage(dir); } catch (error) { ok(error instanceof Error); this.logger.error(error.message); this.logger.info(i18n.previous_error_occurred_when_reading_options_for_0(nicePath(dir))); continue; } await opts.read(this.logger, dir); // Invalid links should only be reported after everything has been merged. // Same goes for @mergeModuleWith, should only be validated after merging // everything together. opts.setValue("validation", { invalidLink: false, unusedMergeModuleWith: false, }); if (opts.getValue("entryPointStrategy") === EntryPointStrategy.Packages) { this.logger.error(i18n.nested_packages_unsupported_0(nicePath(dir))); continue; } addInferredDeclarationMapPaths(opts.getCompilerOptions(), opts.getFileNames()); projectsToConvert.push({ dir, options: opts }); } for (const { dir, options } of projectsToConvert) { this.logger.info(i18n.converting_project_at_0(nicePath(dir))); this.options = options; this.files = new ValidatingFileRegistry(); let project = await this.convert(); if (project) { this.validate(project); const serialized = this.serializer.projectToObject(project, normalizePath(process.cwd())); projects.push(serialized); } // When debugging memory issues, it's useful to set these // here so that a breakpoint on the continue statement below // gets the memory as it ought to be with all TS objects released. project = undefined; this.files = undefined; // global.gc!(); continue; } this.options = origOptions; this.files = origFiles; if (projects.length !== packageDirs.length) { this.logger.error(i18n.failed_to_convert_packages()); return; } this.logger.info(i18n.merging_converted_projects()); const result = this.deserializer.reviveProjects(this.options.getValue("name") || "Documentation", projects, { projectRoot: normalizePath(process.cwd()), registry: this.files, alwaysCreateEntryPointModule: this.options.getValue("alwaysCreateEntryPointModule"), }); this.converter.addProjectDocuments(result); this.trigger(ApplicationEvents.REVIVE, result); return result; } _merge() { const start = Date.now(); if (!this.options.isSet("entryPoints")) { this.logger.error(i18n.no_entry_points_to_merge()); return; } const rootDir = deriveRootDir(this.entryPoints); const entryPoints = this.entryPoints.flatMap((entry) => { const result = glob(entry, rootDir); if (result.length === 0) { // #2918 - do not pass entry through nicePath here in case it contains // windows path separators which should cause additional warnings. this.logger.warn(i18n.entrypoint_did_not_match_files_0(entry)); } else if (result.length !== 1) { this.logger.verbose(`Expanded ${entry} to:\n\t${result .map(nicePath) .join("\n\t")}`); } return result; }); const jsonProjects = entryPoints.map((path) => { try { return JSON.parse(readFile(path)); } catch { this.logger.error(i18n.failed_to_parse_json_0(nicePath(path))); return null; } }); if (this.logger.hasErrors()) return; const result = this.deserializer.reviveProjects(this.options.getValue("name"), jsonProjects, { projectRoot: normalizePath(process.cwd()), registry: this.files, alwaysCreateEntryPointModule: this.options.getValue("alwaysCreateEntryPointModule"), }); this.converter.addProjectDocuments(result); this.logger.verbose(`Reviving projects took ${Date.now() - start}ms`); this.trigger(ApplicationEvents.REVIVE, result); return result; } }; })(); export { Application };