Commit 89656de4 authored by Grant's avatar Grant
Browse files

add #getVersion

parent bbc2cc5d
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
{
  "name": "@sc07/fedi-testkit",
  "version": "1.0.2",
  "version": "1.0.3",
  "exports": {
    ".": {
      "default": "./dist/index.js",
+87 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ export type Software = {

export class FediTestKit {
  private readonly api: ServiceAPI<any>;
  private _version: string | null | undefined;

  private constructor(private readonly software: Software) {
    this.api = new API[software.type](software);
@@ -26,6 +27,92 @@ export class FediTestKit {
    return instance;
  }

  /**
   * Get version of the software specified by querying the NodeInfo
   *
   * The return value is cached
   */
  async getVersion() {
    if (typeof this._version !== "undefined") return this._version;

    const getRealNodeInfo = async () => {
      const req = await fetch(
        new URL("/.well-known/nodeinfo", this.software.host)
      );
      if (!req.ok)
        throw new Error("HTTP " + req.status + " - " + req.statusText);

      const data = await req.json();

      if (!("links" in data)) throw new Error("Missing links property");
      if (!Array.isArray(data.links)) throw new Error("links property invalid");

      const findVersion = (ver: string) =>
        (data.links as any[]).find(
          (l: any): l is { href: string } =>
            "rel" in l &&
            l.rel === ver &&
            "href" in l &&
            typeof l.href === "string"
        );

      const nodeinfos = {
        "2.0": findVersion("http://nodeinfo.diaspora.software/ns/schema/2.0")
          ?.href,
        "2.1": findVersion("http://nodeinfo.diaspora.software/ns/schema/2.1")
          ?.href,
      };

      return nodeinfos["2.1"] || nodeinfos["2.0"] || null;
    };

    const getNodeInfoVersion = async (url: string) => {
      const req = await fetch(url);
      if (!req.ok)
        throw new Error("HTTP " + req.status + " - " + req.statusText);

      const data = await req.json();

      return (
        (typeof data === "object" &&
          "software" in data &&
          typeof data.software === "object" &&
          "version" in data.software &&
          typeof data.software.version === "string" &&
          (data.software.version as string)) ||
        null
      );
    };

    let realNodeInfoURL: string | null;

    try {
      realNodeInfoURL = await getRealNodeInfo();
    } catch (e) {
      this._version = null;
      console.error(e);
      throw new Error("Failed to load real nodeinfo");
    }

    if (!realNodeInfoURL) {
      this._version = null;
      return null;
    }

    let nodeinfoVersion: string | null;

    try {
      nodeinfoVersion = await getNodeInfoVersion(realNodeInfoURL);
    } catch (e) {
      this._version = null;
      console.error(e);
      throw new Error("Failed to load nodeinfo content");
    }

    this._version = nodeinfoVersion;
    return this._version;
  }

  async setup() {
    await this.api.startCollect();
  }