@interop/did-web-resolver 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@interop/did-web-resolver",
3
3
  "description": "A did:web method Decentralized Identifier (DID) resolver for the did-io library.",
4
- "version": "3.0.0",
4
+ "version": "4.0.0",
5
5
  "author": {
6
6
  "name": "Dmitri Zagidulin",
7
7
  "url": "https://github.com/dmitrizagidulin/"
@@ -14,92 +14,80 @@
14
14
  "homepage": "https://github.com/interop-alliance/did-web-driver",
15
15
  "bugs": "https://github.com/interop-alliance/did-web-driver/issues",
16
16
  "scripts": {
17
- "rollup": "rollup -c rollup.config.js",
18
- "build": "npm run clear && npm run rollup && ./build-dist.sh",
19
- "clear": "rimraf dist/ && mkdir dist",
17
+ "build": "npm run clear && tsc -d && tsc -p tsconfig.esm.json",
18
+ "clear": "rimraf dist/*",
19
+ "lint": "ts-standard --fix --project tsconfig.spec.json",
20
20
  "prepare": "npm run build",
21
21
  "rebuild": "npm run clear && npm run build",
22
- "test": "npm run standard && npm run test-node",
23
- "test-node": "cross-env NODE_ENV=test mocha -r esm --preserve-symlinks -t 10000 test/**/*.spec.js",
24
- "test-karma": "karma start test/karma.conf.js",
25
- "nyc": "cross-env NODE_ENV=test nyc npm run test-node",
26
- "standard": "standard --fix"
22
+ "test": "npm run lint && npm run test-node",
23
+ "test-node": "cross-env NODE_ENV=test TS_NODE_PROJECT=tsconfig.spec.json TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register --project tsconfig.spec.json 'test/*.ts'"
27
24
  },
28
25
  "files": [
29
26
  "dist",
30
27
  "src",
31
- "rollup.config.js",
32
- "build-dist.sh",
33
28
  "README.md",
34
29
  "LICENSE"
35
30
  ],
36
- "main": "dist/index.js",
31
+ "main": "dist/src/index.js",
37
32
  "module": "dist/esm/index.js",
38
- "exports": {
39
- ".": {
40
- "require": "./dist/index.js",
41
- "import": "./dist/esm/index.js"
42
- },
43
- "./package.json": "./package.json"
44
- },
33
+ "browser": "dist/esm/index.js",
34
+ "types": "dist/esm/index.d.ts",
45
35
  "dependencies": {
46
- "@digitalcredentials/bnid": "^2.1.1",
36
+ "@digitalbazaar/http-client": "digitalcredentials/http-client#react-native",
37
+ "@digitalcredentials/bnid": "^3.0.1",
47
38
  "@digitalcredentials/did-io": "^1.0.2",
48
- "@digitalcredentials/http-client": "^1.2.2",
49
39
  "did-context": "^3.1.1",
50
40
  "ed25519-signature-2020-context": "^1.1.0",
51
- "whatwg-url": "^11.0.0",
41
+ "whatwg-url": "^14.0.0",
52
42
  "x25519-key-agreement-2020-context": "^1.0.0"
53
43
  },
44
+ "resolutions": {
45
+ "@typescript-eslint/typescript-estree": "^6.1.6"
46
+ },
54
47
  "devDependencies": {
55
- "@babel/core": "^7.16.7",
56
- "@babel/plugin-transform-modules-commonjs": "^7.16.7",
57
- "@babel/plugin-transform-runtime": "^7.16.7",
58
- "@babel/preset-env": "^7.16.7",
59
- "@babel/runtime": "^7.16.7",
60
48
  "@digitalcredentials/ed25519-verification-key-2020": "^3.2.2",
61
49
  "@digitalcredentials/x25519-key-agreement-key-2020": "^2.0.2",
62
- "babel-loader": "^8.2.3",
63
- "chai": "^4.3.4",
50
+ "@types/chai": "^4.3.5",
51
+ "@types/mocha": "^10.0.1",
52
+ "@types/node": "^20.4.6",
53
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
54
+ "@typescript-eslint/parser": "^5.0.0",
55
+ "chai": "^4.3.7",
64
56
  "cross-env": "^7.0.3",
65
57
  "crypto-ld": "^6.0.0",
66
- "dirty-chai": "^2.0.1",
67
- "esm": "^3.2.25",
68
- "karma": "^6.3.9",
69
- "karma-babel-preprocessor": "^8.0.1",
70
- "karma-chai": "^0.1.0",
71
- "karma-chrome-launcher": "^3.1.0",
72
- "karma-mocha": "^2.0.1",
73
- "karma-mocha-reporter": "^2.2.5",
74
- "karma-sourcemap-loader": "^0.3.8",
75
- "karma-webpack": "^5.0.0",
76
- "mocha": "^8.4.0",
77
- "nyc": "^15.1.0",
78
- "rimraf": "^3.0.2",
79
- "rollup": "^2.62.0",
80
- "sinon": "^12.0.1",
81
- "standard": "^16.0.4",
82
- "webpack": "^5.65.0"
58
+ "eslint": "^8.46.0",
59
+ "mocha": "^10.2.0",
60
+ "rimraf": "^5.0.1",
61
+ "ts-node": "^10.9.1",
62
+ "ts-standard": "^12.0.2",
63
+ "typescript": "5.2.2"
64
+ },
65
+ "publishConfig": {
66
+ "access": "public"
83
67
  },
84
- "nyc": {
85
- "reporter": [
86
- "html",
87
- "text-summary"
68
+ "mocha": {
69
+ "require": "ts-node/register",
70
+ "extension": [
71
+ "ts"
88
72
  ],
89
- "cache": true
73
+ "spec": "test/**/*.ts"
90
74
  },
91
- "standard": {
75
+ "ts-standard": {
76
+ "ignore": [
77
+ "dist"
78
+ ],
92
79
  "globals": [
93
- "after",
94
- "afterEach",
95
- "before",
96
- "beforeEach",
97
- "describe",
98
80
  "it",
99
- "require"
81
+ "describe",
82
+ "beforeEach"
100
83
  ]
101
84
  },
102
85
  "engines": {
103
- "node": ">=12.0"
86
+ "node": ">=18.0"
87
+ },
88
+ "standard": {
89
+ "globals": [
90
+ "it"
91
+ ]
104
92
  }
105
93
  }
@@ -1,8 +1,9 @@
1
- import { httpClient } from '@digitalcredentials/http-client'
1
+ /* eslint-disable @typescript-eslint/strict-boolean-expressions */
2
+ import { httpClient } from '@digitalbazaar/http-client'
2
3
  import * as didIo from '@digitalcredentials/did-io'
3
- import ed25519Context from 'ed25519-signature-2020-context'
4
- import x25519Context from 'x25519-key-agreement-2020-context'
5
- import didContext from 'did-context'
4
+ import * as ed25519Context from 'ed25519-signature-2020-context'
5
+ import * as x25519Context from 'x25519-key-agreement-2020-context'
6
+ import * as didContext from 'did-context'
6
7
  import { decodeSecretKeySeed } from '@digitalcredentials/bnid'
7
8
  import { URL } from 'whatwg-url'
8
9
 
@@ -16,7 +17,7 @@ const DEFAULT_KEY_MAP = {
16
17
  keyAgreement: 'X25519KeyAgreementKey2020'
17
18
  }
18
19
 
19
- export function didFromUrl ({ url } = {}) {
20
+ export function didFromUrl ({ url }: { url?: string } = {}): string {
20
21
  if (!url) {
21
22
  throw new TypeError('Cannot convert url to did, missing url.')
22
23
  }
@@ -31,29 +32,37 @@ export function didFromUrl ({ url } = {}) {
31
32
  throw new TypeError(`Invalid url: "${url}".`)
32
33
  }
33
34
 
34
- const { host, pathname } = parsedUrl
35
-
35
+ let { host, pathname } = parsedUrl
36
36
  let pathComponent = ''
37
- if (pathname && pathname !== '/' && pathname !== '/.well-known/did.json') {
37
+
38
+ const didJsonSuffix = '/did.json'
39
+ const wellKnownSuffix = '/.well-known'
40
+
41
+ if (pathname?.endsWith(didJsonSuffix)) {
42
+ pathname = pathname.substring(0, pathname.length - didJsonSuffix.length)
43
+ }
44
+
45
+ if (pathname?.endsWith(wellKnownSuffix)) {
46
+ pathname = pathname.substring(0, pathname.length - wellKnownSuffix.length)
47
+ }
48
+
49
+ if (pathname && pathname !== '/') {
38
50
  pathComponent = pathname.split('/').map(encodeURIComponent).join(':')
39
51
  }
40
52
 
41
53
  return 'did:web:' + encodeURIComponent(host) + pathComponent
42
54
  }
43
55
 
44
- export function urlFromDid ({ did } = {}) {
45
- if (!did) {
46
- throw new TypeError('Cannot convert did to url, missing did.')
47
- }
48
- if (!did.startsWith('did:web:')) {
49
- throw new TypeError(`DID Method not supported: "${did}".`)
56
+ export function urlFromDid ({ did }: { did: string | undefined }): string {
57
+ if (!did?.startsWith('did:web:')) {
58
+ throw new TypeError(`DID Method not supported: "${did ?? ''}".`)
50
59
  }
51
60
 
52
61
  const [didUrl, hashFragment] = did.split('#')
53
62
  // eslint-disable-next-line no-unused-vars
54
63
  // const [didResource, query] = didUrl.split('?')
55
64
 
56
- // eslint-disable-next-line no-unused-vars
65
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
66
  const [_did, _web, urlNoProtocol, ...pathFragments] = didUrl.split(':')
58
67
 
59
68
  if (urlNoProtocol.includes('/')) {
@@ -108,8 +117,11 @@ export function urlFromDid ({ did } = {}) {
108
117
  * DID Document initialized with keys, as well as the map of the corresponding
109
118
  * key pairs (by key id).
110
119
  */
111
- export async function initKeys ({ didDocument, cryptoLd, keyMap } = {}) {
112
- const doc = { ...didDocument }
120
+ export async function initKeys (
121
+ { didDocument, cryptoLd, keyMap }:
122
+ { didDocument?: object, cryptoLd?: any, keyMap?: any } = {}
123
+ ): Promise<{ didDocument: object, keyPairs: Map<string, any> }> {
124
+ const doc: any = { ...didDocument }
113
125
  if (!doc.id) {
114
126
  throw new TypeError(
115
127
  'DID Document "id" property is required to initialize keys.')
@@ -144,13 +156,19 @@ export async function initKeys ({ didDocument, cryptoLd, keyMap } = {}) {
144
156
  }
145
157
 
146
158
  export class DidWebResolver {
159
+ public cryptoLd: any
160
+ public keyMap: object
161
+ public method: string
162
+ public logger: any
163
+
147
164
  /**
148
165
  * @param cryptoLd {CryptoLD}
149
166
  * @param keyMap {object}
150
167
  * @param [logger] {object} Logger object (with .log, .error, .warn,
151
168
  * etc methods).
152
169
  */
153
- constructor ({ cryptoLd, keyMap = DEFAULT_KEY_MAP, logger = console } = {}) {
170
+ constructor ({ cryptoLd, keyMap = DEFAULT_KEY_MAP, logger = console }:
171
+ { cryptoLd?: any, keyMap?: object, logger?: any } = {}) {
154
172
  this.method = 'web' // did:web:... (used for didIo resolver harness)
155
173
  this.cryptoLd = cryptoLd
156
174
  this.keyMap = keyMap
@@ -171,18 +189,23 @@ export class DidWebResolver {
171
189
  * Either an `id` or a `url` is required:
172
190
  * @param [id] {string} - A did:web DID. If absent, will be converted from url
173
191
  * @param [url] {string}
192
+ * @param [seed] {string|Uint8Array}
174
193
  *
175
194
  * @param [keyMap] {object} A hashmap of key types by purpose.
176
195
  *
196
+ * @param cryptoLd
177
197
  * @parma [cryptoLd] {object} CryptoLD instance with support for supported
178
198
  * crypto suites installed.
179
199
  *
180
- * @returns {Promise<{didDocument: object, keyPairs: Map,
200
+ * @returns {Promise<{didDocument: object, keyPairs: object,
181
201
  * methodFor: Function}>} Resolves with the generated DID Document, along
182
202
  * with the corresponding key pairs used to generate it (for storage in a
183
203
  * KMS).
184
204
  */
185
- async generate ({ id, url, seed, keyMap, cryptoLd = this.cryptoLd } = {}) {
205
+ async generate (
206
+ { id, url, seed, keyMap, cryptoLd = this.cryptoLd }:
207
+ { id?: string, url?: string, seed?: string | Uint8Array, keyMap?: any, cryptoLd?: any } = {}):
208
+ Promise<{ didDocument: any, keyPairs: object, methodFor: Function }> {
186
209
  if (!id && !url) {
187
210
  throw new TypeError('A "url" or an "id" parameter is required.')
188
211
  }
@@ -192,7 +215,7 @@ export class DidWebResolver {
192
215
  )
193
216
  }
194
217
 
195
- const did = id || didFromUrl({ url })
218
+ const did = id ?? didFromUrl({ url })
196
219
 
197
220
  if (seed) {
198
221
  const keyPair = await _keyPairFromSecretSeed({
@@ -213,13 +236,13 @@ export class DidWebResolver {
213
236
  id: did
214
237
  }
215
238
 
216
- const result = await initKeys({ didDocument, cryptoLd, keyMap })
239
+ const result: any = await initKeys({ didDocument, cryptoLd, keyMap })
217
240
  const keyPairs = result.keyPairs
218
241
  didDocument = result.didDocument
219
242
 
220
243
  // Convenience function that returns the public/private key pair instance
221
244
  // for a given purpose (authentication, assertionMethod, keyAgreement, etc).
222
- const methodFor = ({ purpose }) => {
245
+ const methodFor = ({ purpose }: { purpose: string }): any => {
223
246
  const { id: methodId } = didIo.findVerificationMethod({
224
247
  doc: didDocument, purpose
225
248
  })
@@ -247,8 +270,8 @@ export class DidWebResolver {
247
270
  *
248
271
  * @returns {Promise<object>} Plain parsed JSON object of the DID Document.
249
272
  */
250
- async get ({ did, url, agent, logger = this.logger }) {
251
- const didUrl = url || urlFromDid({ did })
273
+ async get ({ did, url, agent, logger = this.logger }: { did?: string | undefined, url?: string | undefined, agent?: any, logger?: any }): Promise<object> {
274
+ const didUrl = url ?? urlFromDid({ did })
252
275
  if (!didUrl) {
253
276
  throw new TypeError('A DID or a URL is required.')
254
277
  }
@@ -260,11 +283,12 @@ export class DidWebResolver {
260
283
  logger.info(`Fetching "${urlAuthority}" via http client.`)
261
284
  const result = await httpClient.get(urlAuthority, { agent })
262
285
  didDocument = result.data
263
- } catch (e) {
286
+ } catch (e: any) {
264
287
  // status is HTTP status code
265
288
  // data is JSON error from the server if available
266
289
  const { data, status } = e
267
- logger.error(`Http ${status} error:`, data)
290
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
291
+ logger.error(`Http ${status ?? ''} error:`, data)
268
292
  throw e
269
293
  }
270
294
  if (didDocument && keyIdFragment) {
@@ -308,14 +332,7 @@ export class DidWebResolver {
308
332
  * @returns {object} Returns the public key object (obtained from the DID
309
333
  * Document), without a `@context`.
310
334
  */
311
- publicMethodFor ({ didDocument, purpose } = {}) {
312
- if (!didDocument) {
313
- throw new TypeError('The "didDocument" parameter is required.')
314
- }
315
- if (!purpose) {
316
- throw new TypeError('The "purpose" parameter is required.')
317
- }
318
-
335
+ publicMethodFor ({ didDocument, purpose }: { didDocument: any, purpose: string }): any {
319
336
  const method = didIo.findVerificationMethod({ doc: didDocument, purpose })
320
337
  if (!method) {
321
338
  throw new Error(`No verification method found for purpose "${purpose}"`)
@@ -332,7 +349,7 @@ export class DidWebResolver {
332
349
  *
333
350
  * @return {Promise<LDKeyPair>}
334
351
  */
335
- async function _keyPairFromSecretSeed ({ seed, controller, cryptoLd } = {}) {
352
+ async function _keyPairFromSecretSeed ({ seed, controller, cryptoLd }: { seed: string | Uint8Array, controller?: string, cryptoLd?: any }): Promise<any> {
336
353
  let seedBytes
337
354
  if (typeof seed === 'string') {
338
355
  // Currently only supports base58 multibase / identity multihash encoding.
@@ -0,0 +1,11 @@
1
+ declare module '@digitalbazaar/http-client'
2
+ declare module '@digitalcredentials/did-io'
3
+ declare module 'ed25519-signature-2020-context'
4
+ declare module 'x25519-key-agreement-2020-context'
5
+ declare module 'did-context'
6
+ declare module '@digitalcredentials/bnid'
7
+ declare module '@digitalcredentials/ed25519-verification-key-2020'
8
+ declare module '@digitalcredentials/x25519-key-agreement-key-2020'
9
+ declare module 'crypto-ld'
10
+ declare module 'whatwg-url'
11
+ declare module 'dirty-chai'
@@ -1,7 +1,7 @@
1
1
 
2
- import { DidWebResolver, didFromUrl, urlFromDid } from './DidWebResolver.js'
2
+ import { DidWebResolver, didFromUrl, urlFromDid } from './DidWebResolver'
3
3
 
4
- const driver = options => {
4
+ const driver = (options: { cryptoLd?: any, keyMap?: object | undefined, logger?: any } | undefined): DidWebResolver => {
5
5
  return new DidWebResolver(options)
6
6
  }
7
7
 
package/build-dist.sh DELETED
@@ -1,14 +0,0 @@
1
- mkdir ./dist/esm
2
- cat >dist/esm/index.js <<!EOF
3
- import cjsModule from '../index.js';
4
- export const driver = cjsModule.driver;
5
- export const DidWebResolver = cjsModule.DidWebResolver;
6
- export const didFromUrl = cjsModule.didFromUrl;
7
- export const urlFromDid = cjsModule.urlFromDid;
8
- !EOF
9
-
10
- cat >dist/esm/package.json <<!EOF
11
- {
12
- "type": "module"
13
- }
14
- !EOF