Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Catch Seed class construction errors
Sebastian Martinez committed 4 years ago
commit 0263a5f03252f08b3da7c79b6826c7907ef1336c
parent 75ccac422e6ecbc05191e1b5e24ada9680a53bd6
9 files changed +69 -40
modified src/SeedAddress.svelte
@@ -1,8 +1,8 @@
<script lang="ts">
  import { formatSeedAddress, formatSeedId, toClipboard } from "./utils";
+
  import type { Seed } from "@app/base/seeds/Seed";

-
  export let id: string;
-
  export let host: string;
+
  export let seed: Seed;
  export let port: number;

  let seedCopied = false;
@@ -38,12 +38,12 @@
<div class="desktop">
  <div class="seed-address">
    <span class="seed-icon">🌱</span>
-
    <span><a href="/seeds/{host}" class="link">{formatSeedId(id)}@{host}</a></span>
+
    <span><a href="/seeds/{seed.host}" class="link">{formatSeedId(seed.id)}@{seed.host}</a></span>
    <span class="faded">:{port}</span>
  </div>
</div>
<div>
-
  <button class="tiny faded" disabled={seedCopied} on:click={copySeed(id, host)}>
+
  <button class="tiny faded" disabled={seedCopied} on:click={copySeed(seed.id, seed.host)}>
    {#if seedCopied}
      Copy ✓
    {:else}
modified src/base/orgs/View.svelte
@@ -249,9 +249,13 @@
            {/if}
          {/await}
          <!-- Seed Address -->
-
          {#if profile.seedId && profile.seedHost}
+
          {#if profile.seed?.valid}
            <div class="label">Seed</div>
-
            <SeedAddress id={profile.seedId} host={profile.seedHost} port={config.seed.link.port} />
+
            <SeedAddress seed={profile.seed} port={config.seed.link.port} />
+
          {:else if !profile.seed?.valid}
+
            <div class="label">Seed</div>
+
            <div class="subtle">✗ Seed configuration is invalid</div>
+
            <div class="desktop" />
          {/if}
          <!-- Name/Profile -->
          <div class="label">Profile</div>
@@ -331,7 +335,11 @@
          </Message>
        {/await}

-
        <Projects {org} {account} config={profile.seed ? config.withSeed(profile.seed) : config} />
+
        <Projects {org} {account} config={profile.config(config)} />
+
      {:catch err}
+
        <Message error>
+
          <strong>Error: </strong> {err.message}.
+
        </Message>
      {/await}
    </main>
  {:else}
modified src/base/projects/View.svelte
@@ -41,13 +41,15 @@
  }).then(async (result) => {
    const profile = result?.profile;
    const seedInstance = profile?.seed ?? result?.seed;
-
    const cfg = seedInstance ? config.withSeed(seedInstance) : config;
+
    const cfg = seedInstance && seedInstance.valid ? config.withSeed(seedInstance) : config;
    const info = await proj.getInfo(urn, cfg);
-
    projectInfo = info;
    const anchors = await getAllAnchors(config, urn, profile?.anchorsAccount ?? org);
+

    let branches = Array([info.meta.defaultBranch, info.head]) as [string, string][];
    let peers: proj.Peer[] = [];

+
    projectInfo = info;
+

    // Checks for delegates returned from seed node, as feature check of the seed node
    if (info.meta.delegates) {
      // Check for selected peer to override available branches.
modified src/base/projects/Widget.svelte
@@ -30,7 +30,7 @@
      state = { status: Status.Loaded };
      info = result;
    } catch (err: any) {
-
      console.error(err.message);
+
      console.debug(err);
      state = { status: Status.Error, error: err.message };
    }
  });
modified src/base/registrations/registrar.ts
@@ -8,19 +8,18 @@ import { Failure } from '@app/error';
import type { Config } from '@app/config';
import { unixTime } from '@app/utils';
import { assert } from '@app/error';
-
import { Seed } from '@app/base/seeds/Seed';
+
import { Seed, InvalidSeed } from '@app/base/seeds/Seed';

export interface Registration {
  profile: EnsProfile;
  resolver: EnsResolver;
}

-

export interface EnsProfile {
  name: string;
  owner?: string;
  address?: string;
-
  seed?: Seed;
+
  seed?: Seed | InvalidSeed;
  anchorsAccount?: string;
  url?: string;
  avatar?: string;
@@ -96,8 +95,14 @@ export async function getRegistration(name: string, config: Config, resolver?: E
    github,
  };

+
  // If no seed provided profile.seed ends up being undefined
  if (seedHost && seedId) {
-
    profile.seed = new Seed(seedHost, seedId, seedGit, seedApi);
+
    try {
+
      profile.seed = new Seed(seedHost, seedId, seedGit, seedApi);
+
    } catch (e: any) {
+
      console.debug(e, seedHost, seedId);
+
      profile.seed = new InvalidSeed(seedHost, seedId);
+
    }
  }

  return { resolver, profile };
@@ -123,7 +128,7 @@ export async function getAnchorsAccount(name: string, config: Config, resolver?:
  return resolver.getText('eth.radicle.anchors');
}

-
export async function getSeed(name: string, config: Config, resolver?: EnsResolver | null): Promise<Seed | null> {
+
export async function getSeed(name: string, config: Config, resolver?: EnsResolver | null): Promise<Seed | InvalidSeed | null> {
  name = name.toLowerCase();

  resolver = resolver ?? await config.provider.getResolver(name);
@@ -139,10 +144,16 @@ export async function getSeed(name: string, config: Config, resolver?: EnsResolv
  ]);

  if (! host || ! id) {
+
    console.debug("getSeed: No seed host or id provided");
    return null;
  }

-
  return new Seed(host, id, git ?? undefined, api ?? undefined);
+
  try {
+
    return new Seed(host, id, git, api);
+
  } catch (e: any) {
+
    console.debug(e, host, id);
+
    return new InvalidSeed(id, host);
+
  }
}

export function registrar(config: Config): ethers.Contract {
modified src/base/seeds/Seed.ts
@@ -5,7 +5,21 @@ import type { Project } from "@app/project";
import { isDomain } from '@app/utils';
import { assert } from '@app/error';

+
export class InvalidSeed {
+
  valid: false = false;
+

+
  host?: string;
+
  id?: string;
+

+
  constructor(host?: string, id?: string) {
+
    this.host = host;
+
    this.id = id;
+
  }
+
}
+

export class Seed {
+
  valid: true = true;
+

  host: string;
  id: string;

@@ -13,9 +27,9 @@ export class Seed {
  git?: string;
  version?: string;

-
  constructor(host: string, id: string, git?: string, api?: string) {
-
    assert(isDomain(host));
-
    assert(/^[a-z0-9]+$/.test(id));
+
  constructor(host: string, id: string, git?: string | null, api?: string | null) {
+
    assert(isDomain(host), "invalid seed host");
+
    assert(/^[a-z0-9]+$/.test(id), "invalid seed id");

    this.host = host;
    this.id = id;
@@ -49,10 +63,9 @@ export class Seed {
      Seed.getPeer(config),
    ]);

-
    return {
-
      host: config.seed.api.host,
-
      id: peer.id,
-
      version: info.version,
-
    };
+
    const seed = new Seed(config.seed.api.host, peer.id);
+
    seed.version = info.version;
+

+
    return seed;
  }
}
modified src/base/seeds/View.svelte
@@ -96,7 +96,7 @@
      <!-- Seed Address -->
      <div class="label">Address</div>
      {#if info.version === "0.2.0" && info.host}
-
        <SeedAddress id={info.id} host={info.host} port={config.seed.link.port} />
+
        <SeedAddress seed={info} port={config.seed.link.port} />
      {:else}
        <div class="seed-address subtle">N/A</div>
        <div class="desktop" />
modified src/base/users/View.svelte
@@ -175,9 +175,11 @@
        <div class="desktop" />
      {/if}
      <!-- Seed Address -->
-
      {#if profile.seedId && profile.seedHost}
-
        <div class="label">Seed</div>
-
        <SeedAddress id={profile.seedId} host={profile.seedHost} port={config.seed.link.port} />
+
      {#if profile.seed && profile.seed.valid}
+
        {#if profile.seed.id && profile.seed.host}
+
          <div class="label">Seed</div>
+
          <SeedAddress seed={profile.seed} port={config.seed.link.port} />
+
        {/if}
      {/if}
      <!-- Profile -->
      <div class="label">Profile</div>
modified src/profile.ts
@@ -4,7 +4,7 @@ import {
  isAddress, formatCAIP10Address, formatIpfsFile, resolveEnsProfile, resolveIdxProfile, parseUsername, parseEnsLabel
} from "@app/utils";
import type { Config } from "@app/config";
-
import type { Seed } from "@app/base/seeds/Seed";
+
import type { Seed, InvalidSeed } from "@app/base/seeds/Seed";

export interface IProfile {
  address: string;
@@ -70,16 +70,9 @@ export class Profile {
    else return undefined;
  }

-
  get seedHost(): string | undefined {
-
    return this.profile?.ens?.seed?.host;
-
  }
-

-
  get seedId(): string | undefined {
-
    return this.profile?.ens?.seed?.id;
-
  }
-

-
  get seed(): Seed | undefined {
-
    return this.profile?.ens?.seed;
+
  // We add null here to differentiate between a `undefined` and a invalid / null seed
+
  get seed(): Seed | InvalidSeed | null {
+
    return this.profile?.ens?.seed ?? null;
  }

  get anchorsAccount(): string | undefined {
@@ -108,7 +101,7 @@ export class Profile {
  // Return the profile-specific config. This sets various URLs in the config,
  // based on profile data.
  config(config: Config): Config {
-
    if (this.seed) {
+
    if (this.seed && this.seed.valid) {
      return config.withSeed(this.seed);
    }
    return config;