From 41413fea9dae778d072e285c36e6363934422d2c Mon Sep 17 00:00:00 2001 From: Giovanni Abbatepaolo <30571828+bbtgnn@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:58:15 +0100 Subject: [PATCH] feat: Add DID detail error (#70) * chore: autoformat * feat: display fetch error * feat: add statusText property --- explorer/app/details/[did]/page.tsx | 40 ++++++++++++++++++++++++----- explorer/lib/fetcher.ts | 30 +++++++++++++++++----- explorer/lib/resolver.ts | 40 +++++++++++++++++------------ 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/explorer/app/details/[did]/page.tsx b/explorer/app/details/[did]/page.tsx index b2c9b7f..0e67ff8 100644 --- a/explorer/app/details/[did]/page.tsx +++ b/explorer/app/details/[did]/page.tsx @@ -7,11 +7,22 @@ import CopyButton from "@/ui/CopyButton"; import IconButton from "@/ui/IconButton"; import ArrowLeft from "@/ui/icons/ArrowLeft"; import Link from "next/link"; +import { DIDResolutionResult } from "did-resolver"; +import { FetchError } from "lib/fetcher"; // export default async function Page({ params }: { params: { did: string } }) { - const document = await resolve(decodeURIComponent(params.did)); + let document: DIDResolutionResult | undefined = undefined; + let error: FetchError | undefined = undefined; + + try { + document = await resolve(decodeURIComponent(params.did)); + } catch (e) { + if (e instanceof FetchError) error = e; + else + error = new FetchError(500, "Something went wrong :O", "Unknown error"); + } return ( <> @@ -30,13 +41,28 @@ export default async function Page({ params }: { params: { did: string } }) { -
- -
+ {document && ( + <> +
+ +
+ +
+ +
+ + )} -
- -
+ {error && ( +
+
+

+ Error | {error.status} - {error.statusText} +

+

{error.message}

+
+
+ )} ); } diff --git a/explorer/lib/fetcher.ts b/explorer/lib/fetcher.ts index 56084c5..54f5312 100644 --- a/explorer/lib/fetcher.ts +++ b/explorer/lib/fetcher.ts @@ -1,9 +1,27 @@ -const base_url = 'https://did.dyne.org'; +const base_url = "https://did.dyne.org"; export const getData = async (endpoint: string) => { - const res = await fetch(`${base_url}/${endpoint}`); - if (!res.ok) { - throw new Error(`Failed to fetch data from ${endpoint}`); - } - return res.json(); + const res = await fetch(`${base_url}/${endpoint}`); + if (!res.ok) { + throw new FetchError( + res.status, + `Failed to fetch data from ${endpoint}`, + res.statusText + ); + } + return res.json(); +}; + +export class FetchError extends Error { + status: number; + message: string; + statusText: string; + + constructor(status: number, message: string, statusText: string) { + super(message); + this.name = "FetchError"; + this.status = status; + this.message = message; + this.statusText = statusText; + } } diff --git a/explorer/lib/resolver.ts b/explorer/lib/resolver.ts index a8a4c5c..fbccff4 100644 --- a/explorer/lib/resolver.ts +++ b/explorer/lib/resolver.ts @@ -1,22 +1,28 @@ -import { DIDResolutionOptions, DIDResolutionResult, ParsedDID, Resolvable, Resolver } from "did-resolver"; +import { + DIDResolutionOptions, + DIDResolutionResult, + ParsedDID, + Resolvable, + Resolver, +} from "did-resolver"; import { getData } from "./fetcher"; const resolver = new Resolver({ - dyne: async function resolve( - did: string, - parsed: ParsedDID, - didResolver: Resolvable, - options: DIDResolutionOptions - ): Promise { - // {method: 'mymethod', id: 'abcdefg', did: 'did:mymethod:abcdefg/some/path#fragment=123', path: '/some/path', fragment: 'fragment=123'} - const didDoc = await getData(`dids/${did}`); - // If you need to lookup another did as part of resolving this did document, the primary DIDResolver object is passed in as well - // const parentDID = await didResolver.resolve(...) - // Return the DIDResolutionResult object - return didDoc - } -}) + dyne: async function resolve( + did: string, + parsed: ParsedDID, + didResolver: Resolvable, + options: DIDResolutionOptions + ): Promise { + // {method: 'mymethod', id: 'abcdefg', did: 'did:mymethod:abcdefg/some/path#fragment=123', path: '/some/path', fragment: 'fragment=123'} + const didDoc = await getData(`dids/${did}`); + // If you need to lookup another did as part of resolving this did document, the primary DIDResolver object is passed in as well + // const parentDID = await didResolver.resolve(...) + // Return the DIDResolutionResult object + return didDoc; + }, +}); export const resolve = async (didUrl: string): Promise => { - return await resolver.resolve(didUrl) -} + return await resolver.resolve(didUrl); +};