From 657ac52970b5057e180cf1c803f22d2ba99f8fc3 Mon Sep 17 00:00:00 2001 From: "David I. Lehn" Date: Tue, 30 Jul 2024 23:27:16 -0400 Subject: [PATCH] Add `addDocuments` API. --- CHANGELOG.md | 6 +++ README.md | 16 +++++- lib/JsonLdDocumentLoader.js | 26 ++++++++-- test/10-test.spec.js | 99 +++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5f7604..ebafb8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # jsonld-document-loader +## 2.2.0 - 2024-xx-xx + +### Added +- `addDocuments({documents})` to add many URL to document mappings from an + iterable object. + ## 2.1.0 - 2024-06-05 ### Changed diff --git a/README.md b/README.md index f69457a..dffbe93 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ import {JsonLdDocumentLoader} from 'jsonld-document-loader'; const loader = new JsonLdDocumentLoader(); ``` -### `addStatic()` +### `addStatic(url, document)` The `addStatic()` method allows developers to load fixed static contexts and documents, to ensure known versions and contents, without going out to the @@ -88,6 +88,20 @@ const documentLoader = jdl.build(); // Pass to jsonld, jsonld-signatures, vc-js and similar libraries ``` +### `addDocuments({documents})` + +Uses `addStatic()` to add many documents from an iterable object that returns +values of the form `[url, document]`. Can be used directly with a Map +associating URLs to documents. + +```js +import {contexts as credContexts} from 'credentials-context'; + +const jdl = new JsonLdDocumentLoader(); + +jdl.addDocuments({documents: credContexts}); +``` + ### `setDidResolver()` To add support for resolving DIDs and DID-related key ids: diff --git a/lib/JsonLdDocumentLoader.js b/lib/JsonLdDocumentLoader.js index 9a5edb6..e67ce52 100644 --- a/lib/JsonLdDocumentLoader.js +++ b/lib/JsonLdDocumentLoader.js @@ -13,9 +13,8 @@ export class JsonLdDocumentLoader { * * The document will be cloned. * - * @param {string} url - The URL of a document, - * etc. - * @param {object} document -The document. + * @param {string} url - The URL of a document. + * @param {object} document - The document. */ addStatic(url, document) { if(!_isString(url)) { @@ -27,6 +26,25 @@ export class JsonLdDocumentLoader { this.documents.set(url, structuredClone(document)); } + /** + * Adds many URL to document mappings to the loader. + * + * The documents will be cloned. + * + * @param {object} options - The options to use. + * @param {object} options.documents - An object that implements the iterable + * protocol returning [url, document] pairs. + */ + addDocuments({documents} = {}) { + if(documents === null || documents === undefined || + typeof documents[Symbol.iterator] !== 'function') { + throw new TypeError('"documents" must be iterable.'); + } + for(const [url, document] of documents) { + this.addStatic(url, document); + } + } + /** * Adds a custom protocol handler to the loader. * @@ -34,7 +52,7 @@ export class JsonLdDocumentLoader { * // Using did-io's CachedResolver instance as a did: protocol handler * jld.addProtocolHandler({protocol: 'did', handler: cachedResolver}); * - * @param {object} options -The options to use. + * @param {object} options - The options to use. * @param {string} options.protocol - Protocol id, such as 'did', 'https', * etc. * @param {{get: Function}} options.handler - Protocol handler object, diff --git a/test/10-test.spec.js b/test/10-test.spec.js index 15a8769..7f4558d 100644 --- a/test/10-test.spec.js +++ b/test/10-test.spec.js @@ -128,8 +128,107 @@ describe('jsonld-document-loader', () => { expectedDoc, 'Expected document from documentLoader to equal unmutated document.'); }); + it('allows overwrites', () => { + const jldl = new JsonLdDocumentLoader(); + const documentUrl = 'https://example.com/foo.jsonld'; + let error; + try { + jldl.addStatic(documentUrl, sampleDoc); + jldl.addStatic(documentUrl, sampleDoc); + } catch(e) { + error = e; + } + should.not.exist(error); + }); }); // end addStatic API + describe('addDocuments API', () => { + it('throws TypeError with no documents', () => { + const jldl = new JsonLdDocumentLoader(); + let error; + try { + jldl.addDocuments(); + } catch(e) { + error = e; + } + should.exist(error); + error.should.be.instanceOf(TypeError); + }); + it('throws TypeError with null documents', () => { + const jldl = new JsonLdDocumentLoader(); + let error; + try { + jldl.addDocuments({documents: null}); + } catch(e) { + error = e; + } + should.exist(error); + error.should.be.instanceOf(TypeError); + }); + it('throws TypeError with undefined documents', () => { + const jldl = new JsonLdDocumentLoader(); + let error; + try { + jldl.addDocuments({documents: undefined}); + } catch(e) { + error = e; + } + should.exist(error); + error.should.be.instanceOf(TypeError); + }); + it('throws TypeError with non-iterable', () => { + const jldl = new JsonLdDocumentLoader(); + let error; + try { + jldl.addDocuments({documents: {}}); + } catch(e) { + error = e; + } + should.exist(error); + error.should.be.instanceOf(TypeError); + }); + it('add multiple documents', async () => { + const jldl = new JsonLdDocumentLoader(); + const documentUrl1 = 'https://example.com/foo1.jsonld'; + const documentUrl2 = 'https://example.com/foo2.jsonld'; + const documents = new Map([ + [documentUrl1, sampleDoc], + [documentUrl2, sampleDoc] + ]); + let error; + try { + jldl.addDocuments({documents}); + const documentLoader = jldl.build(); + const result1 = await documentLoader(documentUrl1); + should.exist(result1); + should.exist(result1.documentUrl); + should.exist(result1.document); + const result2 = await documentLoader(documentUrl2); + should.exist(result2); + should.exist(result2.documentUrl); + should.exist(result2.document); + } catch(e) { + error = e; + } + should.not.exist(error); + }); + it('allows overwrites', () => { + const jldl = new JsonLdDocumentLoader(); + const documentUrl1 = 'https://example.com/foo1.jsonld'; + const documents = [ + [documentUrl1, sampleDoc], + [documentUrl1, sampleDoc] + ]; + let error; + try { + jldl.addDocuments({documents}); + } catch(e) { + error = e; + } + should.not.exist(error); + }); + }); // end addDocuments API + describe('documentLoader API', () => { it('throws error when url is not a string', async () => { const jldl = new JsonLdDocumentLoader();