"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var docs_exports = {};
__export(docs_exports, {
  buildDocs: () => buildDocs,
  mergeDocs: () => mergeDocs
});
module.exports = __toCommonJS(docs_exports);
var import_node_path = require("node:path");
var import_typedoc = require("typedoc");
var import_file = require("../util/file.js");
var import_graph = require("./graph.js");
/**
 * @license
 * Copyright 2022-2026 Greg Lauckhart <greg@lauckhart.com>
 * SPDX-License-Identifier: Apache-2.0
 */
const PLUGINS = ["typedoc-github-theme"];
const OUTPUT_PATH = "build/docs/docs";
const THEME_OPTIONS = {
  themeColor: "#cb9820"
  // TODO - add service links
};
async function buildDocs(pkg, progress) {
  const modules = pkg.sourceModules;
  const entryPoints = Array();
  const basePath = pkg.root.path;
  for (const name in modules) {
    const path = modules[name];
    if (path.endsWith(".json")) {
      continue;
    }
    if ((0, import_file.isFile)(path)) {
      if (!entryPoints.includes(path)) {
        entryPoints.push(path);
      }
    } else {
      throw new Error(`No source found for module ${name} path ${modules[name]}`);
    }
  }
  const app = await createApplication({
    excludeExternals: true,
    entryPoints,
    tsconfig: pkg.resolve("tsconfig.json"),
    basePath,
    skipErrorChecking: true,
    // Removes a couple hundred MB of tabs so worth uncommenting at some point
    //pretty: false,
    readme: "none"
  });
  instrumentForEntrypointRepair(app, pkg);
  const analysis = new ReflectionAnalysis();
  app.converter.on(import_typedoc.Converter.EVENT_CREATE_DECLARATION, () => {
    progress.refresh();
  });
  app.converter.on(import_typedoc.Converter.EVENT_RESOLVE, () => {
    progress.refresh();
  });
  const reflection = await loadReflections(app, pkg);
  analyzeReflections(reflection, analysis);
  repairReflections(analysis);
  await app.generateJson(reflection, pkg.resolve("build/docs.json"));
}
function reflectionsPath(pkg) {
  const path = pkg.resolve("build/docs.json");
  if ((0, import_file.isFile)(path)) {
    return path;
  }
}
function instrumentForEntrypointRepair(app, pkg) {
  const baseGetEntryPoints = app.getEntryPoints.bind(app);
  const mapping = naiveToRealNamesFor(pkg);
  app.getEntryPoints = () => {
    const list = baseGetEntryPoints();
    if (list === void 0) {
      return list;
    }
    for (const ep of list) {
      const realName = mapping[ep.displayName];
      if (realName === void 0) {
        throw new Error(`Typedoc naive module name "${ep.displayName}" is unmapped`);
      }
      ep.displayName = realName;
    }
    return list;
  };
}
function naiveToRealNamesFor(pkg) {
  const modules = pkg.sourceModules;
  const mapping = {};
  const packagePrefix = `${pkg.name}/`;
  const basePath = pkg.root.path;
  for (const name in modules) {
    const path = modules[name];
    if (path.endsWith(".json")) {
      continue;
    }
    const naiveName = (0, import_node_path.relative)(basePath, path).replace(/.(?:ts|js|mjs|cjs)$/, "").replace(/\/index$/, "");
    if (name.startsWith(packagePrefix)) {
      mapping[naiveName] = name.substring(packagePrefix.length);
    } else if (name === pkg.name) {
      mapping[naiveName] = ".";
    } else {
      mapping[naiveName] = name;
    }
  }
  return mapping;
}
async function mergeDocs(pkg) {
  const entryPoints = Array();
  const root = pkg.root;
  if (root.isWorkspace) {
    const graph = await import_graph.Graph.load(root);
    if (graph === void 0) {
      throw new Error(`Internal: ${pkg.name} has workspaces but no graph`);
    }
    for (const node of graph.nodes) {
      const path = reflectionsPath(node.pkg);
      if (path) {
        entryPoints.push(path);
      }
    }
    if (!entryPoints.length) {
      throw new Error(`No reflections detected in workspace ${pkg.name}`);
    }
  } else {
    const path = reflectionsPath(pkg);
    if (path === void 0) {
      throw new Error(`No reflections present for ${pkg.name}`);
    }
    entryPoints.push(path);
  }
  const app = await createApplication({
    entryPoints,
    entryPointStrategy: "merge",
    ...THEME_OPTIONS
  });
  const reflection = await loadReflections(app, pkg);
  await app.generateDocs(reflection, pkg.resolve(OUTPUT_PATH));
}
async function createApplication(options) {
  return await import_typedoc.Application.bootstrapWithPlugins({
    plugin: PLUGINS,
    logLevel: import_typedoc.LogLevel.Warn,
    ...options
  });
}
async function loadReflections(app, pkg) {
  const reflection = await app.convert();
  if (reflection === void 0) {
    throw new Error(`Project ${pkg.path} produced no documentation`);
  }
  return reflection;
}
class ReflectionAnalysis {
  // TODO - need to populate this during analysis so we can warn; will replace typedoc-plugin-missing-exports
  unexportedReference = /* @__PURE__ */ new Set();
  mergeWithParent = /* @__PURE__ */ new Set();
  mergeInto = /* @__PURE__ */ new Map();
}
function analyzeReflections(node, analysis) {
  visit(node, (subject) => {
    const children = childrenOf(subject);
    const mergeable = {};
    const namespaces = /* @__PURE__ */ new Set();
    for (const child of children) {
      if (child.kindOf(import_typedoc.ReflectionKind.ClassOrInterface | import_typedoc.ReflectionKind.Function)) {
        mergeable[child.name] = child;
      } else if (child.kindOf(import_typedoc.ReflectionKind.Namespace)) {
        namespaces.add(child);
      }
    }
    for (const ns of namespaces) {
      const mergeInto2 = mergeable[ns.name];
      if (mergeInto2) {
        analysis.mergeInto.set(ns, mergeInto2);
      }
    }
  });
}
function repairReflections(analysis) {
  for (const toMerge of analysis.mergeWithParent) {
    if (toMerge.parent instanceof import_typedoc.DeclarationReflection) {
      mergeInto(toMerge, toMerge.parent);
    }
  }
  for (const [toMerge, into] of analysis.mergeInto.entries()) {
    mergeInto(toMerge, into);
  }
}
function moveNode(subject, into) {
  const from = subject.parent;
  if (from === into) {
    return;
  }
  if (from) {
    from.removeChild(subject);
  }
  into.addChild(subject);
  subject.parent = into;
  if (from.kindOf(import_typedoc.ReflectionKind.Namespace) && into.kindOf(import_typedoc.ReflectionKind.ClassOrInterface) && subject.kindOf(import_typedoc.ReflectionKind.SomeValue)) {
    subject.flags.setFlag(import_typedoc.ReflectionFlag.Static, true);
    if (subject.kindOf(import_typedoc.ReflectionKind.Variable)) {
      subject.kind = import_typedoc.ReflectionKind.Property;
    }
  }
}
function mergeInto(from, into) {
  const children = childrenOf(from);
  while (children.length) {
    moveNode(children[0], into);
  }
  from.parent?.removeChild(from);
}
function childrenOf(node) {
  if (node instanceof import_typedoc.ContainerReflection) {
    if (node.children === void 0) {
      node.children = [];
    }
    return node.children;
  }
  return [];
}
function visit(node, visitor) {
  visitor(node);
  for (const child of childrenOf(node)) {
    visit(child, visitor);
  }
}
//# sourceMappingURL=docs.js.map
