Skip to content

Commit df3ac75

Browse files
author
Wes Biggs
committed
Switch to using @digitalbazaar/did-io
Upgrade dependencies
1 parent 9fdb90e commit df3ac75

File tree

6 files changed

+1853
-1408
lines changed

6 files changed

+1853
-1408
lines changed

README.md

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
11
# Overview
22

33
This package implements a generic resolver for the `dsnp` DID method (that is, DIDs of the form `did:dsnp:123456`, where `123456` is a [DSNP User Id](https://spec.dsnp.org/DSNP/Identifiers.html#dsnp-user-id) in decimal format).
4-
This resolver should be used with one or more plugins for specific DSNP systems (see below).
4+
This resolver must be used with one or more plugins for specific DSNP systems (see below).
55

66
# Usage
77

8-
This package follows the conventions described in the [`did-resolver`](https://github.com/decentralized-identity/did-resolver) package and exposes a `getResolver()` function which returns a mapping from the `dsnp` DID method to a resolver function.
9-
Pass an array of plugins to the `getResolver()` method.
8+
This package follows the conventions described in the [`@digitalbazaar/did-io`](https://github.com/digitalbazaar/did-io) package and exposes a `driver()` function which returns an object with a `get(options)` method.
9+
Pass an array of DSNPResolver objects to the `driver()` method.
1010

1111
## Usage for DSNP DID method only
1212

1313
```
14-
import { Resolver } from "did-resolver";
15-
import dsnpResolver from "@dsnp/did-resolver";
14+
import { CachedResolver } from "@digitalbazaar/did-io";
15+
import didDsnp from "@dsnp/did-resolver";
1616
import { FooResolver} from "dsnp-did-resolver-plugin-foo"; // See below for known plugins
1717
// ... additional dsnp-did-resolver plugins if needed
1818
19-
const resolver = new Resolver(dsnpResolver.getResolver(
20-
[ new FooResolver() ]
21-
));
19+
const resolver = new CachedResolver();
20+
resolver.use(didDsnp.driver([ new FooResolver() ]));
21+
2222
const myDid = "did:dsnp:123456";
23-
const result = await resolver.resolve(myDid);
23+
const result = await resolver.get({ did: myDid });
2424
console.log(JSON.stringify(result, null, 2));
2525
```
2626

2727
## Usage with other DID method resolvers
2828

29-
The Resolver constructor can combine resolvers for multiple DID methods as described in the `did-resolver` [documentation](https://github.com/decentralized-identity/did-resolver#readme).
30-
For example, if you also want to be able to resolve `did:ethr:*` DIDs, you would import and include the `ethr` resolver and pass its destructured resolver alongside the DSNP one to the constructor as follows:
29+
The CachedResolver can combine drivers for multiple DID methods as described in the `did-io` [documentation](https://github.com/digitalbazaar/did-io#readme).
30+
For example, if you also want to be able to resolve `did:web:*` DIDs, you can use the `did-method-web` driver alongside the DSNP driver.
3131

3232
```
33-
import ethrResolver from "ethr-did-resolver";
34-
// ... additional did-resolver packages;
33+
import { CachedResolver } from "@digitalbazaar/did-io";
34+
import didWeb from "@digitalbazaar/did-method-web";
35+
import didDsnp from "@dsnp/did-resolver";
36+
37+
const resolver = new CachedResolver();
38+
resolver.use(didWeb.driver());
39+
resolver.use(didDsnp.driver([ new FooResolver() ]));
3540
36-
const resolver = new Resolver({
37-
...dsnpResolver.getResolver([plugin]),
38-
...ethrResolver.getResolver()
39-
});
4041
// usage is same as in previous example
4142
```
4243

@@ -52,22 +53,20 @@ Plugins should implement the `DSNPResolver` interface, which includes a `resolve
5253

5354
```
5455
export interface DSNPResolver {
55-
resolve(dsnpUserId: bigint): Promise<DIDDocument | null>;
56+
resolve(dsnpUserId: bigint): Promise<object | null>;
5657
}
5758
```
5859

59-
The `DIDDocument` type is defined in the `did-resolver` package.
60-
6160
The `resolve()` function should return `null` if the DSNP User Id cannot be resolved to a DID document for any reason.
6261
Plugins should avoid throwing errors except in dire circumstances, as errors from one plugin will cause any further plugins that have been registered to *not* be called.
6362

64-
`DSNPResolver` instances are passed to the `getResolver()` function.
63+
`DSNPResolver` instances can be passed to the `CachedResolver` `use()` function.
6564

6665
## Known plugins
6766

6867
| System | Plugin package
6968
|---|---|
70-
| Frequency | [`@dsnp/did-resolver-plugin-frequency`](https://github.com/AmplicaLabs/dsnp-did-resolver-plugin-frequency) |
69+
| Frequency | [`@dsnp/did-resolver-plugin-frequency`](https://github.com/ProjectLibertyLabs/dsnp-did-resolver-plugin-frequency) |
7170

7271
Please submit a pull request with any additional plugins.
7372

index.test.ts

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
import {
2-
DIDDocument,
3-
DIDResolutionResult,
4-
ParsedDID,
5-
Resolvable,
6-
DIDResolutionOptions,
7-
} from "did-resolver";
81
import { expect, jest, test } from "@jest/globals";
9-
import { DSNPResolver, getResolver } from "./index.js";
2+
import { driver } from "./index.js";
3+
import { CachedResolver } from "@digitalbazaar/did-io";
104

11-
const someDocument: DIDDocument = {
5+
import type { DSNPResolver } from "./index.js";
6+
7+
const someDocument: object = {
128
id: "",
139
};
1410

1511
class Plugin1 implements DSNPResolver {
16-
async resolve(dsnpUserId: bigint): Promise<DIDDocument | null> {
12+
async resolve(dsnpUserId: bigint) {
1713
if (dsnpUserId === 123456n) {
1814
return someDocument;
1915
} else {
@@ -23,7 +19,7 @@ class Plugin1 implements DSNPResolver {
2319
}
2420

2521
class Plugin2 implements DSNPResolver {
26-
async resolve(dsnpUserId: bigint): Promise<DIDDocument | null> {
22+
async resolve(dsnpUserId: bigint) {
2723
if (dsnpUserId === 234567n) {
2824
return someDocument;
2925
} else {
@@ -32,103 +28,56 @@ class Plugin2 implements DSNPResolver {
3228
}
3329
}
3430

35-
function errorResult(error: string): DIDResolutionResult {
36-
return {
37-
didDocument: null,
38-
didDocumentMetadata: {},
39-
didResolutionMetadata: { error },
40-
};
41-
}
42-
43-
type GetResolverOutput = {
44-
[method: string]: (
45-
did: string,
46-
parsed: ParsedDID,
47-
resolver: Resolvable,
48-
options: DIDResolutionOptions,
49-
) => Promise<DIDResolutionResult>;
50-
};
51-
52-
const dummyResolvable: Resolvable = {
53-
resolve: async (
54-
didUrl: string,
55-
options?: DIDResolutionOptions,
56-
): Promise<DIDResolutionResult> => {
57-
return errorResult("dummy resolvable");
58-
},
59-
};
60-
6131
describe("dsnp-did-resolver", () => {
62-
let resolver: GetResolverOutput;
32+
let resolver: {
33+
method: string;
34+
get: (options: { did: string }) => Promise<object>;
35+
};
6336

6437
beforeAll(() => {
65-
resolver = getResolver([new Plugin1(), new Plugin2()]);
38+
resolver = driver([new Plugin1(), new Plugin2()]);
6639
});
6740

6841
async function doResolve(id: string) {
6942
const did = `did:dsnp:${id}`;
70-
return await resolver.dsnp(
71-
did,
72-
{
73-
did,
74-
didUrl: did,
75-
method: "dsnp",
76-
id,
77-
},
78-
dummyResolvable,
79-
{},
80-
);
43+
return await resolver.get({ did });
8144
}
8245

8346
it("claims to resolve 'dsnp' DID method", () => {
84-
expect(resolver.dsnp).not.toBeNull();
47+
expect(resolver.method).toEqual("dsnp");
8548
});
8649

8750
it("rejects non-DSNP DIDs", async () => {
8851
const did = "did:xyz:123";
89-
const output = await resolver.dsnp(
90-
did,
91-
{ did, didUrl: did, method: "xyz", id: "123" },
92-
dummyResolvable,
93-
{},
94-
);
95-
expect(output).toEqual(errorResult("unsupportedDidMethod"));
52+
const output = await expect(resolver.get({ did })).rejects.toThrow();
9653
});
9754

9855
it("rejects invalid DSNP User Ids", async () => {
99-
let output;
100-
output = await doResolve("");
101-
expect(output).toEqual(errorResult("invalidDid"));
102-
output = await doResolve("abc");
103-
expect(output).toEqual(errorResult("notFound"));
104-
output = await doResolve("123.456");
105-
expect(output).toEqual(errorResult("notFound"));
106-
output = await doResolve("-123456");
107-
expect(output).toEqual(errorResult("notFound"));
108-
output = await doResolve(BigInt(2n ** 64n).toString());
109-
expect(output).toEqual(errorResult("notFound"));
56+
await expect(doResolve("")).rejects.toThrow();
57+
await expect(doResolve("abc")).rejects.toThrow();
58+
await expect(doResolve("123.456")).rejects.toThrow();
59+
await expect(doResolve("-123456")).rejects.toThrow();
60+
await expect(doResolve(BigInt(2n ** 64n).toString())).rejects.toThrow();
11061
});
11162

11263
it("returns expected output for a resolved DID from first plugin", async () => {
11364
const output = await doResolve("123456");
114-
expect(output).toEqual({
115-
didResolutionMetadata: { contentType: "application/did+ld+json" },
116-
didDocument: someDocument,
117-
didDocumentMetadata: {},
118-
});
65+
expect(output).toEqual(someDocument);
11966
});
12067

12168
it("returns expected output for a resolved DID from second plugin", async () => {
12269
const output = await doResolve("234567");
123-
expect(output).toEqual({
124-
didResolutionMetadata: { contentType: "application/did+ld+json" },
125-
didDocument: someDocument,
126-
didDocumentMetadata: {},
127-
});
70+
expect(output).toEqual(someDocument);
71+
});
72+
73+
it("throws for a valid but unresolved DID", async () => {
74+
await expect(doResolve("654321")).rejects.toThrow();
12875
});
12976

130-
it("returns 'notFound' output for a valid but unresolved DID", async () => {
131-
const output = await doResolve("654321");
132-
expect(output).toEqual(errorResult("notFound"));
77+
it("works with did-io framework", async () => {
78+
const didResolver = new CachedResolver();
79+
didResolver.use(resolver);
80+
const output = await didResolver.get({ did: "did:dsnp:123456" });
81+
expect(output).toEqual(someDocument);
13382
});
13483
});

index.ts

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,52 @@
1-
import {
2-
Resolver,
3-
ParsedDID,
4-
Resolvable,
5-
DIDResolutionOptions,
6-
DIDResolutionResult,
7-
DIDDocument,
8-
} from "did-resolver";
9-
101
export interface DSNPResolver {
11-
resolve(dsnpUserId: bigint): Promise<DIDDocument | null>;
2+
resolve(dsnpUserId: bigint): Promise<object | null>;
123
}
134

14-
const notFoundResult: DIDResolutionResult = {
15-
didDocument: null,
16-
didDocumentMetadata: {},
17-
didResolutionMetadata: { error: "notFound" },
18-
};
19-
20-
export function getResolver(dsnpResolvers: DSNPResolver[]) {
21-
async function resolve(
22-
did: string,
23-
parsed: ParsedDID,
24-
resolver: Resolvable,
25-
options: DIDResolutionOptions,
26-
): Promise<DIDResolutionResult> {
27-
if (parsed.id === "") {
28-
return {
29-
didDocument: null,
30-
didDocumentMetadata: {},
31-
didResolutionMetadata: { error: "invalidDid" },
32-
};
5+
export function driver(dsnpResolvers: DSNPResolver[]) {
6+
async function get(options: { did: string }): Promise<object> {
7+
const did = options.did;
8+
if (!did || !did.startsWith("did:dsnp:")) {
9+
throw new Error("Not a valid DSNP DID");
3310
}
34-
if (parsed.method !== "dsnp") {
35-
return {
36-
didDocument: null,
37-
didDocumentMetadata: {},
38-
didResolutionMetadata: { error: "unsupportedDidMethod" },
39-
};
11+
const id = did.substring("did:dsnp:".length);
12+
if (id === "") {
13+
throw new Error("Missing DSNP User Id");
4014
}
15+
4116
let dsnpUserId: bigint = 0n;
4217
try {
43-
dsnpUserId = BigInt(parsed.id);
18+
dsnpUserId = BigInt(id);
4419
} catch (e) {
45-
return notFoundResult;
20+
throw new Error("Could not parse DSNP User Id");
4621
}
4722
if (dsnpUserId < 0n || dsnpUserId >= 2n ** 64n) {
48-
return notFoundResult;
23+
throw new Error("DSNP User Id not in valid range");
4924
}
5025

5126
for (const dsnpResolver of dsnpResolvers) {
5227
try {
5328
const output = await dsnpResolver.resolve(dsnpUserId);
54-
if (output)
55-
return {
56-
didResolutionMetadata: { contentType: "application/did+ld+json" },
57-
didDocument: output,
58-
didDocumentMetadata: {},
59-
};
29+
if (output) return output;
6030
} catch (cause) {
6131
throw new Error(`Error resolving DSNP User Id ${dsnpUserId}`, {
6232
cause,
6333
});
6434
}
6535
}
6636

67-
return notFoundResult;
37+
throw new Error("DSNP User Id not found");
6838
}
6939

70-
return { dsnp: resolve };
40+
if (!dsnpResolvers || dsnpResolvers.length === 0)
41+
throw new Error("Must provide at least one DSNPResolver");
42+
43+
return {
44+
method: "dsnp",
45+
get,
46+
generate: () => {
47+
throw new Error("generate() is not implemented");
48+
},
49+
};
7150
}
51+
52+
export default { driver };

js.d.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1 @@
1-
declare module "@digitalbazaar/vc" {
2-
export function defaultDocumentLoader(url: string): any;
3-
export function issue(
4-
params: any,
5-
): import("./types/openapi.d.ts").Components.Schemas.VerifiableCredentialWithEd25519Proof;
6-
export function verifyCredential(options: any): any;
7-
}
8-
9-
declare module "@digitalbazaar/ed25519-verification-key-2020" {
10-
export interface Ed25519VerificationKey2020 {}
11-
}
12-
13-
declare module "@digitalbazaar/ed25519-signature-2020" {
14-
export class Ed25519Signature2020 {
15-
constructor(o: any);
16-
verificationMethod: string;
17-
}
18-
export const suiteContext: any;
19-
}
20-
21-
declare module "jsonld-signatures" {
22-
export function extendContextLoader(extension: (string) => any);
23-
}
1+
declare module "@digitalbazaar/did-io";

0 commit comments

Comments
 (0)