Skip to content

Commit

Permalink
feat: Add DID detail error (#70)
Browse files Browse the repository at this point in the history
* chore: autoformat

* feat: display fetch error

* feat: add statusText property
  • Loading branch information
bbtgnn authored Jan 30, 2024
1 parent ace4a23 commit 41413fe
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 30 deletions.
40 changes: 33 additions & 7 deletions explorer/app/details/[did]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
Expand All @@ -30,13 +41,28 @@ export default async function Page({ params }: { params: { did: string } }) {
</div>
</StickyContainer>

<div className="overflow-auto p-4">
<JSONBlock content={document} />
</div>
{document && (
<>
<div className="overflow-auto p-4">
<JSONBlock content={document} />
</div>

<div className="sticky bottom-0 flex justify-end p-4">
<CopyButton text={JSON.stringify(document, null, 2)} />
</div>
</>
)}

<div className="sticky bottom-0 flex justify-end p-4">
<CopyButton text={JSON.stringify(document, null, 2)} />
</div>
{error && (
<div className="overflow-auto p-4">
<div className="p-4 bg-red-100 border border-red-600 rounded-lg text-red-600">
<p className="font-bold">
Error | {error.status} - {error.statusText}
</p>
<p>{error.message}</p>
</div>
</div>
)}
</>
);
}
30 changes: 24 additions & 6 deletions explorer/lib/fetcher.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
40 changes: 23 additions & 17 deletions explorer/lib/resolver.ts
Original file line number Diff line number Diff line change
@@ -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<DIDResolutionResult> {
// {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<DIDResolutionResult> {
// {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<DIDResolutionResult> => {
return await resolver.resolve(didUrl)
}
return await resolver.resolve(didUrl);
};

0 comments on commit 41413fe

Please sign in to comment.