constructor()

in src/api/catalog-search/catalog-search.ts [105:172]


  constructor(catalogData: CatalogPackage[], stats: PackageStats) {
    const catalogMap = catalogData
      // Packages with the "construct-hub/hide-from-search" keyword are shadow-banned from search results
      .filter(
        (pkg) => !pkg.keywords?.includes("construct-hub/hide-from-search")
      )
      .reduce((map, pkg) => {
        const { author, name, version } = pkg;
        const id = [name, version].join("@");
        const downloads = stats.packages[name]?.downloads?.npm ?? 0;
        let [scope, packageName] = name.split("/");

        if (!packageName) {
          packageName = scope;
        }

        let authorName: string | undefined;
        let authorEmail: string | undefined;

        if (typeof author === "string") {
          authorName = author;
        } else {
          if (author?.name) {
            authorName = author.name;
          }

          if (author?.email) {
            authorEmail = author.email;
          }
        }

        const keywords = renderAllKeywords(pkg);

        map.set(id, {
          ...pkg,
          authorName,
          authorEmail,
          keywords,
          downloads,
          id,
          packageName,
          scope,
          tagNames: keywords.map(lunr.tokenizer).flat(),
        });

        return map;
      }, new Map<string, ExtendedCatalogPackage>());

    this.map = this.sort(catalogMap, CatalogSearchSort.PublishDateDesc);

    this.constructFrameworks = this.detectConstructFrameworks();
    this.keywords = this.detectKeywords();

    this.index = lunr(function () {
      this.tokenizer.separator = /[\s\-/@]+/;
      this.ref("id");

      for (const key in INDEX_FIELDS) {
        const field = INDEX_FIELDS[key as keyof typeof INDEX_FIELDS];
        this.field(field.name, { boost: field.boost });
      }

      [...catalogMap.values()].forEach((pkg) => {
        const downloadBoost = Math.log(Math.max(pkg.downloads, 1));
        this.add(pkg, { boost: downloadBoost });
      });
    });
  }