From 495c47d441c9c85ff9d3569325a1e3bff05e1356 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 09:32:28 +0100 Subject: [PATCH 01/12] Added generate ssid test --- src/index.spec.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/index.spec.js b/src/index.spec.js index 1b7c0b8..78b721b 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,11 +1,29 @@ import { expect } from "chai"; import * as discipl from '../src/index.js'; -describe("index test", () => { - describe("getConnector function", () => { - it("should be able to get the memory connector", async () => { - const connector = await discipl.getConnector("memory"); - expect(connector.getName(), "memory") +describe("desciple-core-api", () => { + describe("The disciple core API", () => { + it("should be able to get the memory connector asynchronously", async () => { + const connector = await discipl.getConnector("memory") + expect(connector.getName()).to.equal("memory") + + expect(connector.getName(), "when loaded for the second time").to.equal("memory") + }) + + it("should be able to retrieve a new ssid asynchronously", async () => { + let ssid = await discipl.newSsid('memory') + + it("which should contain a large random public key, private key and connector object", () => { + expect(ssid.pubkey).to.be.a('string') + expect(ssid.pubkey.length).to.equal(88) + expect(ssid.privkey).to.be.a('string') + expect(ssid.privkey.length).to.equal(88) + expect(ssid.pubkey).to.not.equal(ssid.privkey) + expect(ssid.did).to.equal('did:discipl:memory:' + ssid.pubkey) + expect(ssid.connector.getName()).to.equal('memory') + }) }) }) }) + + From 2091418cbb7ab99d7b7d321f7b94dbc3e6ced887 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 09:59:57 +0100 Subject: [PATCH 02/12] Add claim test --- src/index.spec.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/index.spec.js b/src/index.spec.js index 78b721b..4d7c4f1 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -13,15 +13,22 @@ describe("desciple-core-api", () => { it("should be able to retrieve a new ssid asynchronously", async () => { let ssid = await discipl.newSsid('memory') - it("which should contain a large random public key, private key and connector object", () => { - expect(ssid.pubkey).to.be.a('string') - expect(ssid.pubkey.length).to.equal(88) - expect(ssid.privkey).to.be.a('string') - expect(ssid.privkey.length).to.equal(88) - expect(ssid.pubkey).to.not.equal(ssid.privkey) - expect(ssid.did).to.equal('did:discipl:memory:' + ssid.pubkey) - expect(ssid.connector.getName()).to.equal('memory') - }) + expect(ssid.pubkey).to.be.a('string') + expect(ssid.pubkey.length).to.equal(88) + expect(ssid.privkey).to.be.a('string') + expect(ssid.privkey.length).to.equal(88) + expect(ssid.pubkey).to.not.equal(ssid.privkey) + expect(ssid.did).to.equal('did:discipl:memory:' + ssid.pubkey) + expect(ssid.connector.getName()).to.equal('memory') + }) + + + it("should be able to add a first claim to some new channel through a claim() method", async () => { + let ssid = await discipl.newSsid('memory') + let claimlink = await discipl.claim(tmpSsid, {'need':'beer'}) + + expect(claimlink).to.be.a('string') + expect(claimlink.length).to.equal(108) }) }) }) From 6edc5e8a9b552f7cda5c5afeef0444e69f846922 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 14:50:28 +0100 Subject: [PATCH 03/12] Adding stubbed tests and registerConnector method --- package-lock.json | 110 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- src/index.js | 13 +++++- src/index.spec.js | 72 +++++++++++++++++++++++++++--- 4 files changed, 189 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e5af8e..dc3a05c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -762,6 +762,35 @@ "to-fast-properties": "^2.0.0" } }, + "@sinonjs/commons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", + "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", + "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", + "dev": true, + "requires": { + "@sinonjs/samsam": "^2 || ^3" + } + }, + "@sinonjs/samsam": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.0.2.tgz", + "integrity": "sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash.get": "^4.4.2" + } + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -771,6 +800,12 @@ "color-convert": "^1.9.0" } }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -1093,6 +1128,12 @@ "loose-envify": "^1.0.0" } }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "js-levenshtein": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", @@ -1120,6 +1161,12 @@ "minimist": "^1.2.0" } }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -1136,6 +1183,18 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lolex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.0.0.tgz", + "integrity": "sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ==", + "dev": true + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -1221,6 +1280,27 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nise": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", + "integrity": "sha512-kGASVhuL4tlAV0tvA34yJYZIVihrUt/5bDwpp4tTluigxUr2bBlJeDXmivb6NuEdFkqvdv/Ybb9dm16PSKUhtw==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.1.0", + "just-extend": "^4.0.2", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" + }, + "dependencies": { + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + } + } + }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -1305,6 +1385,15 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -1423,6 +1512,21 @@ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "sinon": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.2.2.tgz", + "integrity": "sha512-WLagdMHiEsrRmee3jr6IIDntOF4kbI6N2pfbi8wkv50qaUQcBglkzkjtoOEbeJ2vf1EsrHhLI+5Ny8//WHdMoA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.2.0", + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/samsam": "^3.0.2", + "diff": "^3.5.0", + "lolex": "^3.0.0", + "nise": "^1.4.7", + "supports-color": "^5.5.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1456,6 +1560,12 @@ "has-flag": "^3.0.0" } }, + "text-encoding": { + "version": "0.6.4", + "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/package.json b/package.json index 80ccff8..f34d57e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "babel-plugin-dynamic-import-node": "^2.2.0", "chai": "^4.2.0", "discipl-core-memory": "git+https://github.com/discipl/discipl-core-memory.git", - "mocha": "^5.2.0" + "mocha": "^5.2.0", + "sinon": "^7.2.2" } } diff --git a/src/index.js b/src/index.js index 7ada41f..196a17c 100644 --- a/src/index.js +++ b/src/index.js @@ -20,7 +20,7 @@ const initializeConnector = async (connector) => { if(!Object.keys(disciplCoreConnectors).includes(connector)) { import(CONNECTOR_MODULE_PREFIX+connector).then(module => { let connectorModuleClass = module.default - disciplCoreConnectors[connector] = new connectorModuleClass() + registerConnector(connector, new connectorModuleClass()) }) } } @@ -33,6 +33,16 @@ const getConnector = async (connector) => { return disciplCoreConnectors[connector] } +/** + * Registers a connector explicitly. + * + * @param name of the connector. Packages containing a connector follow the naming convention CONNECTOR_MODULE_PREFIX + name + * @param connector instantiated object representing the connector + */ +const registerConnector = (name, connector) => { + disciplCoreConnectors[name] = connector; +} + /** * extracts connector name and reference from a link string and returns it as a json object in the form of: {connector, reference} */ @@ -268,6 +278,7 @@ const revoke = async (ssid, link) => { export { getConnector, + registerConnector, newSsid, claim, attest, diff --git a/src/index.spec.js b/src/index.spec.js index 4d7c4f1..d0e6197 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,18 +1,21 @@ -import { expect } from "chai"; +import { expect, use } from "chai"; import * as discipl from '../src/index.js'; +import sinon from 'sinon'; + describe("desciple-core-api", () => { - describe("The disciple core API", () => { - it("should be able to get the memory connector asynchronously", async () => { + describe("The disciple core API with memory connector", () => { + + it("should be able to get the connector asynchronously", async () => { const connector = await discipl.getConnector("memory") expect(connector.getName()).to.equal("memory") - + expect(connector.getName(), "when loaded for the second time").to.equal("memory") }) it("should be able to retrieve a new ssid asynchronously", async () => { let ssid = await discipl.newSsid('memory') - + expect(ssid.pubkey).to.be.a('string') expect(ssid.pubkey.length).to.equal(88) expect(ssid.privkey).to.be.a('string') @@ -22,15 +25,70 @@ describe("desciple-core-api", () => { expect(ssid.connector.getName()).to.equal('memory') }) - it("should be able to add a first claim to some new channel through a claim() method", async () => { let ssid = await discipl.newSsid('memory') - let claimlink = await discipl.claim(tmpSsid, {'need':'beer'}) + let claimlink = await discipl.claim(ssid, {'need': 'beer'}) expect(claimlink).to.be.a('string') expect(claimlink.length).to.equal(108) }) + }, + describe("The disciple core API with mocked connector", () => { + + it("should be able to retrieve a new mocked ssid asynchronously", async () => { + let newSsidStub = sinon.stub().returns({pubkey: "".padStart(88,"1"), privkey: "".padStart(88,"2")}) + let getNameStub = sinon.stub().returns("mock") + let stubConnector = {newSsid: newSsidStub, getName: getNameStub}; + + + await discipl.registerConnector('mock', stubConnector) + let ssid = await discipl.newSsid('mock') + + expect(newSsidStub.calledOnce).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) + + expect(ssid.pubkey).to.equal("".padStart(88,"1")) + expect(ssid.privkey).to.equal("".padStart(88, "2")) + expect(ssid.did).to.equal('did:discipl:mock:' + "".padStart(88,"1")) + expect(ssid.connector.getName()).to.equal('mock') + }) + + it("should be able to add a claim to some new channel through a claim() method through a mocked connector", async () => { + let ssid = {did: 'did:discipl:mock:111'} + let claimStub = sinon.stub().returns("claimRef"); + let getNameStub = sinon.stub().returns("mock") + let stubConnector = {claim: claimStub, getName: getNameStub}; + + + await discipl.registerConnector('mock', stubConnector) + let claimlink = await discipl.claim(ssid, {'need':'beer'}) + + expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) + expect(getNameStub.calledOnce).to.be.equal(true) + + + expect(claimlink).to.equal('link:discipl:mock:claimRef') + }) + + it("should be able to add a claim to some new channel through a claim() method with an object as reference", async () => { + let ssid = {did: 'did:discipl:mock:111'} + let claimStub = sinon.stub().returns({someKey:"infoNeededByConnector"}); + let getNameStub = sinon.stub().returns("mock") + let stubConnector = {claim: claimStub, getName: getNameStub}; + + + await discipl.registerConnector('mock', stubConnector) + let claimlink = await discipl.claim(ssid, {'need':'beer'}) + + expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) + expect(getNameStub.calledOnce).to.be.equal(true) + + expect(claimlink).to.equal('link:discipl:mock:jdkIBFi8PojrrOV/Z9qtuS+8hDyUUMUkono9Rof4ZxlA6OIQjOWcHeSWGD73fn2I') + }) + + }) + ) }) From 25d0b51239e4a9799892ff019e31a2755dc86ff1 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 15:48:45 +0100 Subject: [PATCH 04/12] Add npm test back in to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 090940a..b9cf79f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,5 +5,6 @@ addons: sonarcloud: organization: "discipl" # the key of the org you chose at step #3 script: + - npm test # other script steps might be done before running the actual analysis - sonar-scanner From dffebf4b699f043ca44a5a03e8a4765bdb559f97 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 15:55:28 +0100 Subject: [PATCH 05/12] Make sonar scanner conditional on non-pr --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b9cf79f..e4aa5bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,4 @@ addons: script: - npm test # other script steps might be done before running the actual analysis - - sonar-scanner + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sonar-scanner; fi' From 6452111ea2c2871304236d39b40eea72e1ad431b Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Wed, 19 Dec 2018 16:23:16 +0100 Subject: [PATCH 06/12] Adding claim retrival tests --- src/index.spec.js | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/index.spec.js b/src/index.spec.js index d0e6197..19930da 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,4 +1,4 @@ -import { expect, use } from "chai"; +import { expect } from "chai"; import * as discipl from '../src/index.js'; import sinon from 'sinon'; @@ -32,9 +32,19 @@ describe("desciple-core-api", () => { expect(claimlink).to.be.a('string') expect(claimlink.length).to.equal(108) }) + + it("should be able to get a claim added through claim, with link to previous", async () => { + let ssid = await discipl.newSsid('memory') + let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + + let claim = await discipl.get(claimlink2) + expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) + expect(claim.previous).to.equal(claimlink1) + + }) }, describe("The disciple core API with mocked connector", () => { - it("should be able to retrieve a new mocked ssid asynchronously", async () => { let newSsidStub = sinon.stub().returns({pubkey: "".padStart(88,"1"), privkey: "".padStart(88,"2")}) let getNameStub = sinon.stub().returns("mock") @@ -64,7 +74,7 @@ describe("desciple-core-api", () => { let claimlink = await discipl.claim(ssid, {'need':'beer'}) expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) - expect(getNameStub.calledOnce).to.be.equal(true) + expect(getNameStub.calledOnce).to.equal(true) expect(claimlink).to.equal('link:discipl:mock:claimRef') @@ -81,12 +91,30 @@ describe("desciple-core-api", () => { let claimlink = await discipl.claim(ssid, {'need':'beer'}) expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) - expect(getNameStub.calledOnce).to.be.equal(true) + expect(getNameStub.calledOnce).to.equal(true) expect(claimlink).to.equal('link:discipl:mock:jdkIBFi8PojrrOV/Z9qtuS+8hDyUUMUkono9Rof4ZxlA6OIQjOWcHeSWGD73fn2I') }) + it("should be able to get a claim added through claims", async () => { + let claimlink = 'link:discipl:mock:claimRef' + let prevClaimlink = 'link:discipl:mock:previous' + let getStub = sinon.stub().returns({'data':{'need': 'wine'}, 'previous': 'previous'}) + let getNameStub = sinon.stub().returns("mock") + + let stubConnector = {get: getStub, getName: getNameStub} + await discipl.registerConnector('mock', stubConnector) + + let claim = await discipl.get(claimlink) + + expect(getStub.calledOnceWith("claimRef", null)).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) + + expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) + expect(claim.previous).to.equal(prevClaimlink) + + }) }) ) }) From cdabee6ba15d4fe6e37136cfe99d2704f5e05bcd Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 09:43:53 +0100 Subject: [PATCH 07/12] Attestation tests --- src/index.spec.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/index.spec.js b/src/index.spec.js index 19930da..c27a9d7 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -38,10 +38,27 @@ describe("desciple-core-api", () => { let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + let claim = await discipl.get(claimlink2) + + + let attestorSsid = await discipl.newSsid('memory') + + let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); + + let attestation = await discipl.get(attestationLink) + + expect(attestation.data.agree).to.equal(claimlink2) + expect(attestation.previous).to.equal(null) + }) + + it("should be able to attest to a second claim in a chain", async () => { + let ssid = await discipl.newSsid('memory') + let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + let claim = await discipl.get(claimlink2) expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) expect(claim.previous).to.equal(claimlink1) - }) }, describe("The disciple core API with mocked connector", () => { @@ -113,7 +130,23 @@ describe("desciple-core-api", () => { expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) expect(claim.previous).to.equal(prevClaimlink) + }) + + it("should be able to attest a claim", async() => { + let ssid = {did: 'did:discipl:mock:111'} + let claimlink = 'link:discipl:mock:claimRef' + + let claimStub = sinon.stub().returns("attestationRef") + let getNameStub = sinon.stub().returns("mock") + let stubConnector = {claim: claimStub, getName: getNameStub} + + await discipl.registerConnector('mock', stubConnector) + + let attestationLink = await discipl.attest(ssid, 'agree', claimlink); + expect(getNameStub.calledOnce).to.equal(true) + expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'agree':claimlink})).to.equal(true) + expect(attestationLink).to.equal('link:discipl:mock:attestationRef') }) }) ) From bece3b05ee460da0275ce9248095a33ae33e1299 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 12:09:03 +0100 Subject: [PATCH 08/12] Attestation revocation tests --- src/index.spec.js | 110 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 4 deletions(-) diff --git a/src/index.spec.js b/src/index.spec.js index c27a9d7..0578c45 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -39,7 +39,14 @@ describe("desciple-core-api", () => { let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) let claim = await discipl.get(claimlink2) + expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) + expect(claim.previous).to.equal(claimlink1) + }) + it("should be able to attest to a second claim in a chain", async () => { + let ssid = await discipl.newSsid('memory') + let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) let attestorSsid = await discipl.newSsid('memory') @@ -51,14 +58,18 @@ describe("desciple-core-api", () => { expect(attestation.previous).to.equal(null) }) - it("should be able to attest to a second claim in a chain", async () => { + it("should be able to verify an attestation", async () => { let ssid = await discipl.newSsid('memory') let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) - let claim = await discipl.get(claimlink2) - expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) - expect(claim.previous).to.equal(claimlink1) + let attestorSsid = await discipl.newSsid('memory') + + let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); + + let verifiedAttestor = await discipl.verify('agree', claimlink2, [ssid, null, {'did':'did:discipl:memory:1234'}, attestorSsid]) + + expect(verifiedAttestor).to.equal(attestorSsid) }) }, describe("The disciple core API with mocked connector", () => { @@ -148,6 +159,97 @@ describe("desciple-core-api", () => { expect(attestationLink).to.equal('link:discipl:mock:attestationRef') }) + + it("should be able to verify an attestation", async() => { + let ssid = {did: 'did:discipl:mock:111'} + let attestorSsid = {did: 'did:discipl:mock:attestor'} + let claimlink = 'link:discipl:mock:claimRef' + let attestationlink = 'link:discipl:mock:attestationRef' + + let verifyStub = sinon.stub() + + verifyStub.onCall(0).returns('attestationRef') + verifyStub.onCall(1).returns(null) + verifyStub.onCall(2).returns(null) + + let getNameStub = sinon.stub().returns("mock") + + let getSsidOfClaimStub = sinon.stub().returns({pubkey: "111"}) + + let stubConnector = {verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub} + + await discipl.registerConnector('mock', stubConnector) + + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + + expect(verifyStub.calledThrice).to.equal(true) + expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) + expect(verifyStub.args[1]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) + expect(verifyStub.args[2]).to.deep.equal([{did: ssid.did, connector: stubConnector, pubkey: '111'}, {revoke: claimlink}]) + expect(getNameStub.calledTwice).to.equal(true) + expect(getSsidOfClaimStub.calledOnce).to.equal(true) + expect(getSsidOfClaimStub.args[0]).to.deep.equal(['claimRef']) + expect(verifiedAttestor.did).to.equal(attestorSsid.did) + }) + + it("should not be able to verify an attestation, if there is no matching claim", async() => { + let attestorSsid = {did: 'did:discipl:mock:attestor'} + let claimlink = 'link:discipl:mock:claimRef' + + let verifyStub = sinon.stub().returns(null) + + let stubConnector = {verify: verifyStub} + + await discipl.registerConnector('mock', stubConnector) + + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + + expect(verifyStub.calledOnce).to.equal(true) + expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) + + expect(verifiedAttestor).to.equal(null) + }) + + it("should not be able to verify an attestation, if the attestation is revoked", async() => { + let ssid = {did: 'did:discipl:mock:111'} + let attestorSsid = {did: 'did:discipl:mock:attestor'} + let claimlink = 'link:discipl:mock:claimRef' + let attestationlink = 'link:discipl:mock:attestationRef' + let attestationrevocationlink = 'link:discipl:mock:attestationRevocationRef' + + let verifyStub = sinon.stub() + + verifyStub.onCall(0).returns('attestationRef') + verifyStub.onCall(1).returns('attestationRevocationRef') + verifyStub.onCall(2).returns(null) + verifyStub.onCall(3).returns(null) + + let getSsidOfClaimStub = sinon.stub().returns({pubkey: "attestor"}) + + let getNameStub = sinon.stub().returns("mock") + + + let stubConnector = {verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub} + + await discipl.registerConnector('mock', stubConnector) + + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + + expect(verifyStub.callCount).to.equal(4) + expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) + expect(verifyStub.args[1]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) + expect(verifyStub.args[2]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationrevocationlink}]) + expect(verifyStub.args[3]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) + + expect(getSsidOfClaimStub.calledOnce).to.equal(true) + expect(getSsidOfClaimStub.args[0]).to.deep.equal(['attestationRef']) + + expect(getNameStub.callCount).to.equal(3) + + expect(verifiedAttestor).to.equal(null) + }) + + }) ) }) From 921f4ea496b1884bbc9242d1c408d7edf5788067 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 13:23:19 +0100 Subject: [PATCH 09/12] Adding export integration test --- src/index.js | 11 +++++------ src/index.spec.js | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index 196a17c..5d7dc7a 100644 --- a/src/index.js +++ b/src/index.js @@ -18,10 +18,9 @@ var disciplCoreConnectors = [] */ const initializeConnector = async (connector) => { if(!Object.keys(disciplCoreConnectors).includes(connector)) { - import(CONNECTOR_MODULE_PREFIX+connector).then(module => { - let connectorModuleClass = module.default - registerConnector(connector, new connectorModuleClass()) - }) + let module = await import(CONNECTOR_MODULE_PREFIX+connector); + let connectorModuleClass = module.default + registerConnector(connector, new connectorModuleClass()) } } @@ -243,13 +242,13 @@ const exportLD = async (SsidDidOrLink, maxdepth = 3, ssid = null, visitedStack = let res = await get(currentLink, ssid) if(res != null) { - data = res.data + let data = res.data if(res.previous && (SsidDidOrLink.indexOf(DID_PREFIX) == 0)) { console.log('Get previous of channel'+res.previous) exportData[currentSsid.did] = await exportLD(res.previous, maxdepth, ssid, visitedStack) } exportData[currentSsid.did][currentLink] = {} - for(elem in data) { + for(let elem in data) { exportData[currentSsid.did][currentLink][elem] = {} let value = data[elem] try { diff --git a/src/index.spec.js b/src/index.spec.js index 0578c45..d18836e 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,4 +1,4 @@ -import { expect } from "chai"; +import {expect} from "chai"; import * as discipl from '../src/index.js'; import sinon from 'sinon'; @@ -71,6 +71,20 @@ describe("desciple-core-api", () => { expect(verifiedAttestor).to.equal(attestorSsid) }) + + it("should be able to export linked verifiable claim channels", async () => { + let ssid = await discipl.newSsid('memory') + let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + + let attestorSsid = await discipl.newSsid('memory') + + let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); + let exportedData = await discipl.exportLD(attestorSsid) + + + expect(exportedData[attestorSsid.did][attestationLink]['agree'][ssid.did][claimlink2]).to.deep.equal({'need': 'wine'}) + }) }, describe("The disciple core API with mocked connector", () => { it("should be able to retrieve a new mocked ssid asynchronously", async () => { From 6db6e958e738f63c222591a8be05d28631757cc2 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 13:24:56 +0100 Subject: [PATCH 10/12] Removing unused variables --- src/index.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.spec.js b/src/index.spec.js index d18836e..e391d5d 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -45,7 +45,7 @@ describe("desciple-core-api", () => { it("should be able to attest to a second claim in a chain", async () => { let ssid = await discipl.newSsid('memory') - let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + await discipl.claim(ssid, {'need': 'beer'}) let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) let attestorSsid = await discipl.newSsid('memory') @@ -60,12 +60,12 @@ describe("desciple-core-api", () => { it("should be able to verify an attestation", async () => { let ssid = await discipl.newSsid('memory') - let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + await discipl.claim(ssid, {'need': 'beer'}) let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) let attestorSsid = await discipl.newSsid('memory') - let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); + await discipl.attest(attestorSsid, 'agree', claimlink2); let verifiedAttestor = await discipl.verify('agree', claimlink2, [ssid, null, {'did':'did:discipl:memory:1234'}, attestorSsid]) @@ -74,7 +74,7 @@ describe("desciple-core-api", () => { it("should be able to export linked verifiable claim channels", async () => { let ssid = await discipl.newSsid('memory') - let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) + await discipl.claim(ssid, {'need': 'beer'}) let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) let attestorSsid = await discipl.newSsid('memory') From c70d470030806eb64bcaac498ef9d50c9dd96286 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 13:31:31 +0100 Subject: [PATCH 11/12] Comments for most convoluted parts --- src/index.spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/index.spec.js b/src/index.spec.js index e391d5d..cc2c404 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -69,6 +69,7 @@ describe("desciple-core-api", () => { let verifiedAttestor = await discipl.verify('agree', claimlink2, [ssid, null, {'did':'did:discipl:memory:1234'}, attestorSsid]) + // The first ssid that is valid and proves the attestation should be returned expect(verifiedAttestor).to.equal(attestorSsid) }) @@ -183,6 +184,7 @@ describe("desciple-core-api", () => { let verifyStub = sinon.stub() verifyStub.onCall(0).returns('attestationRef') + // No revocations will be found verifyStub.onCall(1).returns(null) verifyStub.onCall(2).returns(null) @@ -234,7 +236,9 @@ describe("desciple-core-api", () => { let verifyStub = sinon.stub() verifyStub.onCall(0).returns('attestationRef') + // A revocation of the attestation will be found verifyStub.onCall(1).returns('attestationRevocationRef') + // No revocations of the revocation of the attestation will be found verifyStub.onCall(2).returns(null) verifyStub.onCall(3).returns(null) From f12b5affc630e931e991fd2eaf0b8e6e6d97e1f3 Mon Sep 17 00:00:00 2001 From: Pim Otte Date: Thu, 20 Dec 2018 14:01:11 +0100 Subject: [PATCH 12/12] Adding standard linter --- .travis.yml | 1 + package-lock.json | 1398 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 9 +- src/index.js | 96 ++-- src/index.spec.js | 395 +++++++------ 5 files changed, 1641 insertions(+), 258 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4aa5bd..dc7c232 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ addons: sonarcloud: organization: "discipl" # the key of the org you chose at step #3 script: + - npm run lint - npm test # other script steps might be done before running the actual analysis - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sonar-scanner; fi' diff --git a/package-lock.json b/package-lock.json index dc3a05c..739ed95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -791,6 +791,48 @@ "lodash.get": "^4.4.2" } }, + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, + "ajv": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", + "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -800,18 +842,116 @@ "color-convert": "^1.9.0" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-from": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", + "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, "babel-plugin-dynamic-import-node": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz", @@ -860,6 +1000,27 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, "caniuse-lite": { "version": "1.0.30000921", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz", @@ -891,12 +1052,39 @@ "supports-color": "^5.3.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -930,6 +1118,12 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -945,6 +1139,19 @@ "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==", "dev": true }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "crypto-js": { "version": "3.1.9-1", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", @@ -958,6 +1165,12 @@ "ms": "2.0.0" } }, + "debug-log": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -967,6 +1180,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -976,6 +1195,28 @@ "object-keys": "^1.0.12" } }, + "deglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + } + } + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -997,24 +1238,399 @@ "discipl-core-baseconnector": "git+https://github.com/discipl/discipl-core-baseconnector.git#8dffe28e1bc886058c8f1e42698c5cb027fa2c2d" } }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "electron-to-chromium": { "version": "1.3.94", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.94.tgz", "integrity": "sha512-miQqXALb6eBD3OetCtg3UM5XTLMwHISux0l6mh14iiV5SE+qvftgOCXT9Vvp53fWaCLET4sfA/SmIMYHXkaNmw==", "dev": true }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz", + "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==", + "dev": true, + "requires": { + "ajv": "^6.5.0", + "babel-code-frame": "^6.26.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.2", + "imurmurhash": "^0.1.4", + "inquirer": "^5.2.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.11.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + } + }, + "eslint-config-standard": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz", + "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + } + } + }, + "eslint-plugin-es": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", + "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==", + "dev": true, + "requires": { + "eslint-plugin-es": "^1.3.1", + "eslint-utils": "^1.3.1", + "ignore": "^4.0.2", + "minimatch": "^3.0.4", + "resolve": "^1.8.1", + "semver": "^5.5.0" + } + }, + "eslint-plugin-promise": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", + "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.0.1", + "prop-types": "^15.6.2" + } + }, + "eslint-plugin-standard": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "external-editor": { + "version": "2.2.0", + "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, "find-cache-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", @@ -1026,6 +1642,12 @@ "pkg-dir": "^2.0.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -1035,6 +1657,18 @@ "locate-path": "^2.0.0" } }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1047,12 +1681,24 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -1073,12 +1719,36 @@ "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", "dev": true }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1103,6 +1773,33 @@ "integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs=", "dev": true }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1119,6 +1816,27 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "inquirer": { + "version": "5.2.0", + "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -1128,12 +1846,81 @@ "loose-envify": "^1.0.0" } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "js-levenshtein": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", @@ -1146,10 +1933,38 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "json5": { @@ -1161,12 +1976,51 @@ "minimist": "^1.2.0" } }, + "jsx-ast-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", + "dev": true, + "requires": { + "array-includes": "^3.0.3" + } + }, "just-extend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -1213,6 +2067,12 @@ "pify": "^3.0.0" } }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1280,6 +2140,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "nise": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", @@ -1316,6 +2194,24 @@ "semver": "^5.3.0" } }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, "object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", @@ -1343,6 +2239,35 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -1367,6 +2292,15 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -1379,6 +2313,18 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -1394,6 +2340,23 @@ "isarray": "0.0.1" } }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -1406,6 +2369,21 @@ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.0.tgz", @@ -1415,6 +2393,51 @@ "node-modules-regexp": "^1.0.0" } }, + "pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -1424,12 +2447,67 @@ "find-up": "^2.1.0" } }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -1454,6 +2532,12 @@ "private": "^0.1.6" } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "regexpu-core": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", @@ -1491,6 +2575,16 @@ } } }, + "require-uncached": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, "resolve": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", @@ -1500,18 +2594,94 @@ "path-parse": "^1.0.6" } }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, "sinon": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.2.2.tgz", @@ -1527,6 +2697,15 @@ "supports-color": "^5.5.0" } }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1551,6 +2730,112 @@ } } }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "standard": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/standard/-/standard-12.0.1.tgz", + "integrity": "sha512-UqdHjh87OG2gUrNCSM4QRLF5n9h3TFPwrCNyVlkqu31Hej0L/rc8hzKqVvkb2W3x0WMq7PzZdkLfEcBhVOR6lg==", + "dev": true, + "requires": { + "eslint": "~5.4.0", + "eslint-config-standard": "12.0.0", + "eslint-config-standard-jsx": "6.0.2", + "eslint-plugin-import": "~2.14.0", + "eslint-plugin-node": "~7.0.1", + "eslint-plugin-promise": "~4.0.0", + "eslint-plugin-react": "~7.11.1", + "eslint-plugin-standard": "~4.0.0", + "standard-engine": "~9.0.0" + } + }, + "standard-engine": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-9.0.0.tgz", + "integrity": "sha512-ZfNfCWZ2Xq67VNvKMPiVMKHnMdvxYzvZkf1AH8/cw2NLDBm5LRsxMqvEJpsjLI/dUosZ3Z1d6JlHDp5rAvvk2w==", + "dev": true, + "requires": { + "deglob": "^2.1.0", + "get-stdin": "^6.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1560,12 +2845,53 @@ "has-flag": "^3.0.0" } }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "table": { + "version": "4.0.3", + "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, "text-encoding": { "version": "0.6.4", "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -1578,6 +2904,15 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -1612,11 +2947,66 @@ "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", "dev": true }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true } } } diff --git a/package.json b/package.json index f34d57e..5c40c47 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ "author": "Bas Kaptijn", "license": "GPL-3.0", "scripts": { - "test": "./node_modules/.bin/mocha --require @babel/register ./src/**/*.spec.js" + "test": "./node_modules/.bin/mocha --require @babel/register ./src/**/*.spec.js", + "lint": "./node_modules/standard/bin/cmd.js --parser babel-eslint", + "lint-fix": "./node_modules/standard/bin/cmd.js --parser babel-eslint --fix" + }, "dependencies": { "crypto-js": "3.1.9-1", @@ -17,10 +20,12 @@ "@babel/core": "^7.2.2", "@babel/preset-env": "^7.2.0", "@babel/register": "^7.0.0", + "babel-eslint": "^10.0.1", "babel-plugin-dynamic-import-node": "^2.2.0", "chai": "^4.2.0", "discipl-core-memory": "git+https://github.com/discipl/discipl-core-memory.git", "mocha": "^5.2.0", - "sinon": "^7.2.2" + "sinon": "^7.2.2", + "standard": "^12.0.1" } } diff --git a/src/index.js b/src/index.js index 5d7dc7a..4e006dd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,9 @@ -import crypto from 'crypto-js'; +import crypto from 'crypto-js' const DID_DELIMITER = ':' const MAX_DEPTH_REACHED = 'MAX_DEPTH_REACHED' -const LINK_PREFIX = 'link'+DID_DELIMITER+'discipl'+DID_DELIMITER -const DID_PREFIX = 'did'+DID_DELIMITER+'discipl'+DID_DELIMITER +const LINK_PREFIX = 'link' + DID_DELIMITER + 'discipl' + DID_DELIMITER +const DID_PREFIX = 'did' + DID_DELIMITER + 'discipl' + DID_DELIMITER const REVOKE_PREDICATE = 'revoke' const CONNECTOR_MODULE_PREFIX = 'discipl-core-' @@ -17,10 +17,10 @@ var disciplCoreConnectors = [] * requires and holds in memory the given discipl connector (if not done before) */ const initializeConnector = async (connector) => { - if(!Object.keys(disciplCoreConnectors).includes(connector)) { - let module = await import(CONNECTOR_MODULE_PREFIX+connector); - let connectorModuleClass = module.default - registerConnector(connector, new connectorModuleClass()) + if (!Object.keys(disciplCoreConnectors).includes(connector)) { + let module = await import(CONNECTOR_MODULE_PREFIX + connector) + let ConnectorModuleClass = module.default + registerConnector(connector, new ConnectorModuleClass()) } } @@ -39,7 +39,7 @@ const getConnector = async (connector) => { * @param connector instantiated object representing the connector */ const registerConnector = (name, connector) => { - disciplCoreConnectors[name] = connector; + disciplCoreConnectors[name] = connector } /** @@ -49,19 +49,19 @@ const splitLink = (link) => { let splitted = link.split(DID_DELIMITER) let connector = splitted[2] let reference = splitted[3] - return {'connector':connector, 'reference':reference} + return { 'connector': connector, 'reference': reference } } /** * returns a link string for the given claim in the channel of the given ssid. claim can be a string in which case it needs to be a connector specific reference string, or it is a object holding claim(s) of which the hash of the stringified version is used as reference */ const getLink = (ssid, claim) => { - if(claim) { + if (claim) { let connector = ssid.connector.getName() - if(typeof claim == 'string') { - return LINK_PREFIX+connector+DID_DELIMITER+claim + if (typeof claim === 'string') { + return LINK_PREFIX + connector + DID_DELIMITER + claim } else { - return LINK_PREFIX+connector+DID_DELIMITER+getHash(ssid, claim) + return LINK_PREFIX + connector + DID_DELIMITER + getHash(ssid, claim) } } return null @@ -72,10 +72,10 @@ const getLink = (ssid, claim) => { */ const isValidLink = async (link) => { try { - let {connector, reference} = splitLink(link) + let connector = splitLink(link).connector await getConnector(connector) return true - } catch(e) { + } catch (e) { return false } } @@ -84,10 +84,10 @@ const isValidLink = async (link) => { * Retrieves an Ssid object for the claim referenced in the given link. Note that the Ssid object will not contain the private key for obvious reasons */ const getSsidOfLinkedClaim = async (link) => { - let {connector, reference} = splitLink(link) + let { connector, reference } = splitLink(link) let conn = await getConnector(connector) let ssid = await conn.getSsidOfClaim(reference) - return {'did':DID_PREFIX+conn.getName()+DID_DELIMITER+ssid.pubkey} + return { 'did': DID_PREFIX + conn.getName() + DID_DELIMITER + ssid.pubkey } } /** @@ -111,7 +111,7 @@ const newSsid = async (connector) => { let conn = await getConnector(connector) let ssid = await conn.newSsid() ssid['connector'] = conn - ssid['did'] = DID_PREFIX+conn.getName()+DID_DELIMITER+ssid.pubkey + ssid['did'] = DID_PREFIX + conn.getName() + DID_DELIMITER + ssid.pubkey return ssid } @@ -142,29 +142,27 @@ const attest = async (ssid, predicate, link) => { */ const verify = async (predicate, link, ssids, all = false) => { let result = [] - for(let i in ssids) { + for (let i in ssids) { let ssid = ssids[i] - if(!(ssid)) continue + if (!(ssid)) continue await expandSsid(ssid) let attestation = {} attestation[predicate] = link let reference = await ssid.connector.verify(ssid, attestation) - if(reference) { - if(await verify(REVOKE_PREDICATE, getLink(ssid, reference), [ssid]) == null) { - if(await verify(REVOKE_PREDICATE, link, [await getSsidOfLinkedClaim(link)]) == null) { - if(all) { + if (reference) { + if (await verify(REVOKE_PREDICATE, getLink(ssid, reference), [ssid]) == null) { + if (await verify(REVOKE_PREDICATE, link, [await getSsidOfLinkedClaim(link)]) == null) { + if (all) { result.push(ssid) - } - else { + } else { return ssid } } } } } - if(result.length == 0) - return null; - return result; + if (result.length === 0) { return null } + return result } /** @@ -174,10 +172,10 @@ const verify = async (predicate, link, ssids, all = false) => { * @return {json} - {data, linkToPrevious} */ const get = async (link, ssid = null) => { - let {connector, reference} = splitLink(link) + let { connector, reference } = splitLink(link) let conn = await getConnector(connector) let result = await conn.get(reference, ssid) - result.previous = getLink({'connector':conn}, result.previous) + result.previous = getLink({ 'connector': conn }, result.previous) return result } @@ -196,23 +194,23 @@ const subscribe = async (ssid) => { const detectSsidLinkFromDidSsidOrLink = async (value) => { let currentLink = null let currentSsid = null - if(typeof value == 'string') { - if(await isValidLink(value)) { + if (typeof value === 'string') { + if (await isValidLink(value)) { currentLink = value currentSsid = await getSsidOfLinkedClaim(currentLink) - } else if(value.indexOf(DID_PREFIX) == 0) { - currentSsid = await expandSsid({'did':value}) + } else if (value.indexOf(DID_PREFIX) === 0) { + currentSsid = await expandSsid({ 'did': value }) currentLink = getLink(currentSsid, await currentSsid.connector.getLatestClaim(currentSsid)) } else { return null } - } else if(Object.keys(value).includes('did')) { + } else if (Object.keys(value).includes('did')) { currentSsid = await expandSsid(value) currentLink = getLink(currentSsid, await currentSsid.connector.getLatestClaim(currentSsid)) } else { return null } - return {'ssid':currentSsid, 'link':currentLink} + return { 'ssid': currentSsid, 'link': currentLink } } /** @@ -226,14 +224,14 @@ const exportLD = async (SsidDidOrLink, maxdepth = 3, ssid = null, visitedStack = let exportData = {} let ssidlink = await detectSsidLinkFromDidSsidOrLink(SsidDidOrLink) - if(ssidlink == null) { + if (ssidlink == null) { return SsidDidOrLink } let currentLink = ssidlink.link let currentSsid = ssidlink.ssid - if(visitedStack.length >= maxdepth) { - return {SsidDidOrLink:MAX_DEPTH_REACHED} + if (visitedStack.length >= maxdepth) { + return { SsidDidOrLink: MAX_DEPTH_REACHED } } else { visitedStack.push(currentLink) } @@ -241,29 +239,29 @@ const exportLD = async (SsidDidOrLink, maxdepth = 3, ssid = null, visitedStack = exportData[currentSsid.did] = {} let res = await get(currentLink, ssid) - if(res != null) { + if (res != null) { let data = res.data - if(res.previous && (SsidDidOrLink.indexOf(DID_PREFIX) == 0)) { - console.log('Get previous of channel'+res.previous) + if (res.previous && (SsidDidOrLink.indexOf(DID_PREFIX) === 0)) { + console.log('Get previous of channel' + res.previous) exportData[currentSsid.did] = await exportLD(res.previous, maxdepth, ssid, visitedStack) } exportData[currentSsid.did][currentLink] = {} - for(let elem in data) { + for (let elem in data) { exportData[currentSsid.did][currentLink][elem] = {} let value = data[elem] try { - console.log('Getting export for..'+value) + console.log('Getting export for..' + value) exportData[currentSsid.did][currentLink][elem] = await exportLD(value, maxdepth, ssid, visitedStack) - console.log('Got'+exportData[currentSsid.did][currentLink][elem]) - } catch(err) { - exportData[currentSsid.did][currentLink][elem][value]={'export-error':err} + console.log('Got' + exportData[currentSsid.did][currentLink][elem]) + } catch (err) { + exportData[currentSsid.did][currentLink][elem][value] = { 'export-error': err } } } } else { exportData[currentSsid.did][currentLink] = 'NOT_FOUND' } - return exportData; + return exportData } /** diff --git a/src/index.spec.js b/src/index.spec.js index cc2c404..dc4bbbe 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,275 +1,264 @@ -import {expect} from "chai"; -import * as discipl from '../src/index.js'; +/* eslint-env mocha */ +import { expect } from 'chai' +import * as discipl from '../src/index.js' -import sinon from 'sinon'; +import sinon from 'sinon' -describe("desciple-core-api", () => { - describe("The disciple core API with memory connector", () => { +describe('desciple-core-api', () => { + describe('The disciple core API with memory connector', () => { + it('should be able to get the connector asynchronously', async () => { + const connector = await discipl.getConnector('memory') + expect(connector.getName()).to.equal('memory') - it("should be able to get the connector asynchronously", async () => { - const connector = await discipl.getConnector("memory") - expect(connector.getName()).to.equal("memory") - - expect(connector.getName(), "when loaded for the second time").to.equal("memory") - }) - - it("should be able to retrieve a new ssid asynchronously", async () => { - let ssid = await discipl.newSsid('memory') - - expect(ssid.pubkey).to.be.a('string') - expect(ssid.pubkey.length).to.equal(88) - expect(ssid.privkey).to.be.a('string') - expect(ssid.privkey.length).to.equal(88) - expect(ssid.pubkey).to.not.equal(ssid.privkey) - expect(ssid.did).to.equal('did:discipl:memory:' + ssid.pubkey) - expect(ssid.connector.getName()).to.equal('memory') - }) - - it("should be able to add a first claim to some new channel through a claim() method", async () => { - let ssid = await discipl.newSsid('memory') - let claimlink = await discipl.claim(ssid, {'need': 'beer'}) - - expect(claimlink).to.be.a('string') - expect(claimlink.length).to.equal(108) - }) - - it("should be able to get a claim added through claim, with link to previous", async () => { - let ssid = await discipl.newSsid('memory') - let claimlink1 = await discipl.claim(ssid, {'need': 'beer'}) - let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) - - let claim = await discipl.get(claimlink2) - expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) - expect(claim.previous).to.equal(claimlink1) - }) - - it("should be able to attest to a second claim in a chain", async () => { - let ssid = await discipl.newSsid('memory') - await discipl.claim(ssid, {'need': 'beer'}) - let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) - - let attestorSsid = await discipl.newSsid('memory') - - let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); - - let attestation = await discipl.get(attestationLink) - - expect(attestation.data.agree).to.equal(claimlink2) - expect(attestation.previous).to.equal(null) - }) + expect(connector.getName(), 'when loaded for the second time').to.equal('memory') + }) - it("should be able to verify an attestation", async () => { - let ssid = await discipl.newSsid('memory') - await discipl.claim(ssid, {'need': 'beer'}) - let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + it('should be able to retrieve a new ssid asynchronously', async () => { + let ssid = await discipl.newSsid('memory') - let attestorSsid = await discipl.newSsid('memory') + expect(ssid.pubkey).to.be.a('string') + expect(ssid.pubkey.length).to.equal(88) + expect(ssid.privkey).to.be.a('string') + expect(ssid.privkey.length).to.equal(88) + expect(ssid.pubkey).to.not.equal(ssid.privkey) + expect(ssid.did).to.equal('did:discipl:memory:' + ssid.pubkey) + expect(ssid.connector.getName()).to.equal('memory') + }) - await discipl.attest(attestorSsid, 'agree', claimlink2); + it('should be able to add a first claim to some new channel through a claim() method', async () => { + let ssid = await discipl.newSsid('memory') + let claimlink = await discipl.claim(ssid, { 'need': 'beer' }) - let verifiedAttestor = await discipl.verify('agree', claimlink2, [ssid, null, {'did':'did:discipl:memory:1234'}, attestorSsid]) + expect(claimlink).to.be.a('string') + expect(claimlink.length).to.equal(108) + }) - // The first ssid that is valid and proves the attestation should be returned - expect(verifiedAttestor).to.equal(attestorSsid) - }) + it('should be able to get a claim added through claim, with link to previous', async () => { + let ssid = await discipl.newSsid('memory') + let claimlink1 = await discipl.claim(ssid, { 'need': 'beer' }) + let claimlink2 = await discipl.claim(ssid, { 'need': 'wine' }) - it("should be able to export linked verifiable claim channels", async () => { - let ssid = await discipl.newSsid('memory') - await discipl.claim(ssid, {'need': 'beer'}) - let claimlink2 = await discipl.claim(ssid, {'need': 'wine'}) + let claim = await discipl.get(claimlink2) + expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({ 'need': 'wine' })) + expect(claim.previous).to.equal(claimlink1) + }) - let attestorSsid = await discipl.newSsid('memory') + it('should be able to attest to a second claim in a chain', async () => { + let ssid = await discipl.newSsid('memory') + await discipl.claim(ssid, { 'need': 'beer' }) + let claimlink2 = await discipl.claim(ssid, { 'need': 'wine' }) - let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2); - let exportedData = await discipl.exportLD(attestorSsid) + let attestorSsid = await discipl.newSsid('memory') + let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2) - expect(exportedData[attestorSsid.did][attestationLink]['agree'][ssid.did][claimlink2]).to.deep.equal({'need': 'wine'}) - }) - }, - describe("The disciple core API with mocked connector", () => { - it("should be able to retrieve a new mocked ssid asynchronously", async () => { - let newSsidStub = sinon.stub().returns({pubkey: "".padStart(88,"1"), privkey: "".padStart(88,"2")}) - let getNameStub = sinon.stub().returns("mock") - let stubConnector = {newSsid: newSsidStub, getName: getNameStub}; + let attestation = await discipl.get(attestationLink) + expect(attestation.data.agree).to.equal(claimlink2) + expect(attestation.previous).to.equal(null) + }) - await discipl.registerConnector('mock', stubConnector) - let ssid = await discipl.newSsid('mock') + it('should be able to verify an attestation', async () => { + let ssid = await discipl.newSsid('memory') + await discipl.claim(ssid, { 'need': 'beer' }) + let claimlink2 = await discipl.claim(ssid, { 'need': 'wine' }) - expect(newSsidStub.calledOnce).to.equal(true) - expect(getNameStub.calledOnce).to.equal(true) + let attestorSsid = await discipl.newSsid('memory') - expect(ssid.pubkey).to.equal("".padStart(88,"1")) - expect(ssid.privkey).to.equal("".padStart(88, "2")) - expect(ssid.did).to.equal('did:discipl:mock:' + "".padStart(88,"1")) - expect(ssid.connector.getName()).to.equal('mock') - }) + await discipl.attest(attestorSsid, 'agree', claimlink2) - it("should be able to add a claim to some new channel through a claim() method through a mocked connector", async () => { - let ssid = {did: 'did:discipl:mock:111'} - let claimStub = sinon.stub().returns("claimRef"); - let getNameStub = sinon.stub().returns("mock") - let stubConnector = {claim: claimStub, getName: getNameStub}; + let verifiedAttestor = await discipl.verify('agree', claimlink2, [ssid, null, { 'did': 'did:discipl:memory:1234' }, attestorSsid]) + // The first ssid that is valid and proves the attestation should be returned + expect(verifiedAttestor).to.equal(attestorSsid) + }) - await discipl.registerConnector('mock', stubConnector) - let claimlink = await discipl.claim(ssid, {'need':'beer'}) + it('should be able to export linked verifiable claim channels', async () => { + let ssid = await discipl.newSsid('memory') + await discipl.claim(ssid, { 'need': 'beer' }) + let claimlink2 = await discipl.claim(ssid, { 'need': 'wine' }) - expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) - expect(getNameStub.calledOnce).to.equal(true) + let attestorSsid = await discipl.newSsid('memory') + let attestationLink = await discipl.attest(attestorSsid, 'agree', claimlink2) + let exportedData = await discipl.exportLD(attestorSsid) - expect(claimlink).to.equal('link:discipl:mock:claimRef') - }) + expect(exportedData[attestorSsid.did][attestationLink]['agree'][ssid.did][claimlink2]).to.deep.equal({ 'need': 'wine' }) + }) + }, + describe('The disciple core API with mocked connector', () => { + it('should be able to retrieve a new mocked ssid asynchronously', async () => { + let newSsidStub = sinon.stub().returns({ pubkey: ''.padStart(88, '1'), privkey: ''.padStart(88, '2') }) + let getNameStub = sinon.stub().returns('mock') + let stubConnector = { newSsid: newSsidStub, getName: getNameStub } + + await discipl.registerConnector('mock', stubConnector) + let ssid = await discipl.newSsid('mock') + + expect(newSsidStub.calledOnce).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) + + expect(ssid.pubkey).to.equal(''.padStart(88, '1')) + expect(ssid.privkey).to.equal(''.padStart(88, '2')) + expect(ssid.did).to.equal('did:discipl:mock:' + ''.padStart(88, '1')) + expect(ssid.connector.getName()).to.equal('mock') + }) - it("should be able to add a claim to some new channel through a claim() method with an object as reference", async () => { - let ssid = {did: 'did:discipl:mock:111'} - let claimStub = sinon.stub().returns({someKey:"infoNeededByConnector"}); - let getNameStub = sinon.stub().returns("mock") - let stubConnector = {claim: claimStub, getName: getNameStub}; + it('should be able to add a claim to some new channel through a claim() method through a mocked connector', async () => { + let ssid = { did: 'did:discipl:mock:111' } + let claimStub = sinon.stub().returns('claimRef') + let getNameStub = sinon.stub().returns('mock') + let stubConnector = { claim: claimStub, getName: getNameStub } + await discipl.registerConnector('mock', stubConnector) + let claimlink = await discipl.claim(ssid, { 'need': 'beer' }) - await discipl.registerConnector('mock', stubConnector) - let claimlink = await discipl.claim(ssid, {'need':'beer'}) + expect(claimStub.calledOnceWith({ did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111' }, { 'need': 'beer' })).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) - expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'need':'beer'})).to.equal(true) - expect(getNameStub.calledOnce).to.equal(true) + expect(claimlink).to.equal('link:discipl:mock:claimRef') + }) - expect(claimlink).to.equal('link:discipl:mock:jdkIBFi8PojrrOV/Z9qtuS+8hDyUUMUkono9Rof4ZxlA6OIQjOWcHeSWGD73fn2I') - }) + it('should be able to add a claim to some new channel through a claim() method with an object as reference', async () => { + let ssid = { did: 'did:discipl:mock:111' } + let claimStub = sinon.stub().returns({ someKey: 'infoNeededByConnector' }) + let getNameStub = sinon.stub().returns('mock') + let stubConnector = { claim: claimStub, getName: getNameStub } - it("should be able to get a claim added through claims", async () => { - let claimlink = 'link:discipl:mock:claimRef' - let prevClaimlink = 'link:discipl:mock:previous' + await discipl.registerConnector('mock', stubConnector) + let claimlink = await discipl.claim(ssid, { 'need': 'beer' }) - let getStub = sinon.stub().returns({'data':{'need': 'wine'}, 'previous': 'previous'}) - let getNameStub = sinon.stub().returns("mock") + expect(claimStub.calledOnceWith({ did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111' }, { 'need': 'beer' })).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) - let stubConnector = {get: getStub, getName: getNameStub} - await discipl.registerConnector('mock', stubConnector) + expect(claimlink).to.equal('link:discipl:mock:jdkIBFi8PojrrOV/Z9qtuS+8hDyUUMUkono9Rof4ZxlA6OIQjOWcHeSWGD73fn2I') + }) - let claim = await discipl.get(claimlink) + it('should be able to get a claim added through claims', async () => { + let claimlink = 'link:discipl:mock:claimRef' + let prevClaimlink = 'link:discipl:mock:previous' - expect(getStub.calledOnceWith("claimRef", null)).to.equal(true) - expect(getNameStub.calledOnce).to.equal(true) + let getStub = sinon.stub().returns({ 'data': { 'need': 'wine' }, 'previous': 'previous' }) + let getNameStub = sinon.stub().returns('mock') - expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({'need':'wine'})) - expect(claim.previous).to.equal(prevClaimlink) - }) + let stubConnector = { get: getStub, getName: getNameStub } + await discipl.registerConnector('mock', stubConnector) - it("should be able to attest a claim", async() => { - let ssid = {did: 'did:discipl:mock:111'} - let claimlink = 'link:discipl:mock:claimRef' + let claim = await discipl.get(claimlink) - let claimStub = sinon.stub().returns("attestationRef") - let getNameStub = sinon.stub().returns("mock") - let stubConnector = {claim: claimStub, getName: getNameStub} + expect(getStub.calledOnceWith('claimRef', null)).to.equal(true) + expect(getNameStub.calledOnce).to.equal(true) - await discipl.registerConnector('mock', stubConnector) + expect(JSON.stringify(claim.data)).to.equal(JSON.stringify({ 'need': 'wine' })) + expect(claim.previous).to.equal(prevClaimlink) + }) - let attestationLink = await discipl.attest(ssid, 'agree', claimlink); - expect(getNameStub.calledOnce).to.equal(true) - expect(claimStub.calledOnceWith({did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111'}, {'agree':claimlink})).to.equal(true) + it('should be able to attest a claim', async () => { + let ssid = { did: 'did:discipl:mock:111' } + let claimlink = 'link:discipl:mock:claimRef' - expect(attestationLink).to.equal('link:discipl:mock:attestationRef') - }) + let claimStub = sinon.stub().returns('attestationRef') + let getNameStub = sinon.stub().returns('mock') + let stubConnector = { claim: claimStub, getName: getNameStub } - it("should be able to verify an attestation", async() => { - let ssid = {did: 'did:discipl:mock:111'} - let attestorSsid = {did: 'did:discipl:mock:attestor'} - let claimlink = 'link:discipl:mock:claimRef' - let attestationlink = 'link:discipl:mock:attestationRef' + await discipl.registerConnector('mock', stubConnector) - let verifyStub = sinon.stub() + let attestationLink = await discipl.attest(ssid, 'agree', claimlink) + expect(getNameStub.calledOnce).to.equal(true) + expect(claimStub.calledOnceWith({ did: 'did:discipl:mock:111', connector: stubConnector, pubkey: '111' }, { 'agree': claimlink })).to.equal(true) - verifyStub.onCall(0).returns('attestationRef') - // No revocations will be found - verifyStub.onCall(1).returns(null) - verifyStub.onCall(2).returns(null) + expect(attestationLink).to.equal('link:discipl:mock:attestationRef') + }) - let getNameStub = sinon.stub().returns("mock") + it('should be able to verify an attestation', async () => { + let ssid = { did: 'did:discipl:mock:111' } + let attestorSsid = { did: 'did:discipl:mock:attestor' } + let claimlink = 'link:discipl:mock:claimRef' + let attestationlink = 'link:discipl:mock:attestationRef' - let getSsidOfClaimStub = sinon.stub().returns({pubkey: "111"}) + let verifyStub = sinon.stub() - let stubConnector = {verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub} + verifyStub.onCall(0).returns('attestationRef') + // No revocations will be found + verifyStub.onCall(1).returns(null) + verifyStub.onCall(2).returns(null) - await discipl.registerConnector('mock', stubConnector) + let getNameStub = sinon.stub().returns('mock') - let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + let getSsidOfClaimStub = sinon.stub().returns({ pubkey: '111' }) - expect(verifyStub.calledThrice).to.equal(true) - expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) - expect(verifyStub.args[1]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) - expect(verifyStub.args[2]).to.deep.equal([{did: ssid.did, connector: stubConnector, pubkey: '111'}, {revoke: claimlink}]) - expect(getNameStub.calledTwice).to.equal(true) - expect(getSsidOfClaimStub.calledOnce).to.equal(true) - expect(getSsidOfClaimStub.args[0]).to.deep.equal(['claimRef']) - expect(verifiedAttestor.did).to.equal(attestorSsid.did) - }) + let stubConnector = { verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub } - it("should not be able to verify an attestation, if there is no matching claim", async() => { - let attestorSsid = {did: 'did:discipl:mock:attestor'} - let claimlink = 'link:discipl:mock:claimRef' + await discipl.registerConnector('mock', stubConnector) - let verifyStub = sinon.stub().returns(null) + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) - let stubConnector = {verify: verifyStub} + expect(verifyStub.calledThrice).to.equal(true) + expect(verifyStub.args[0]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { agree: claimlink }]) + expect(verifyStub.args[1]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { revoke: attestationlink }]) + expect(verifyStub.args[2]).to.deep.equal([{ did: ssid.did, connector: stubConnector, pubkey: '111' }, { revoke: claimlink }]) + expect(getNameStub.calledTwice).to.equal(true) + expect(getSsidOfClaimStub.calledOnce).to.equal(true) + expect(getSsidOfClaimStub.args[0]).to.deep.equal(['claimRef']) + expect(verifiedAttestor.did).to.equal(attestorSsid.did) + }) - await discipl.registerConnector('mock', stubConnector) + it('should not be able to verify an attestation, if there is no matching claim', async () => { + let attestorSsid = { did: 'did:discipl:mock:attestor' } + let claimlink = 'link:discipl:mock:claimRef' - let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + let verifyStub = sinon.stub().returns(null) - expect(verifyStub.calledOnce).to.equal(true) - expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) + let stubConnector = { verify: verifyStub } - expect(verifiedAttestor).to.equal(null) - }) + await discipl.registerConnector('mock', stubConnector) - it("should not be able to verify an attestation, if the attestation is revoked", async() => { - let ssid = {did: 'did:discipl:mock:111'} - let attestorSsid = {did: 'did:discipl:mock:attestor'} - let claimlink = 'link:discipl:mock:claimRef' - let attestationlink = 'link:discipl:mock:attestationRef' - let attestationrevocationlink = 'link:discipl:mock:attestationRevocationRef' + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) - let verifyStub = sinon.stub() + expect(verifyStub.calledOnce).to.equal(true) + expect(verifyStub.args[0]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { agree: claimlink }]) - verifyStub.onCall(0).returns('attestationRef') - // A revocation of the attestation will be found - verifyStub.onCall(1).returns('attestationRevocationRef') - // No revocations of the revocation of the attestation will be found - verifyStub.onCall(2).returns(null) - verifyStub.onCall(3).returns(null) + expect(verifiedAttestor).to.equal(null) + }) - let getSsidOfClaimStub = sinon.stub().returns({pubkey: "attestor"}) + it('should not be able to verify an attestation, if the attestation is revoked', async () => { + let attestorSsid = { did: 'did:discipl:mock:attestor' } + let claimlink = 'link:discipl:mock:claimRef' + let attestationlink = 'link:discipl:mock:attestationRef' + let attestationrevocationlink = 'link:discipl:mock:attestationRevocationRef' - let getNameStub = sinon.stub().returns("mock") + let verifyStub = sinon.stub() + verifyStub.onCall(0).returns('attestationRef') + // A revocation of the attestation will be found + verifyStub.onCall(1).returns('attestationRevocationRef') + // No revocations of the revocation of the attestation will be found + verifyStub.onCall(2).returns(null) + verifyStub.onCall(3).returns(null) - let stubConnector = {verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub} + let getSsidOfClaimStub = sinon.stub().returns({ pubkey: 'attestor' }) - await discipl.registerConnector('mock', stubConnector) + let getNameStub = sinon.stub().returns('mock') - let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) + let stubConnector = { verify: verifyStub, getName: getNameStub, getSsidOfClaim: getSsidOfClaimStub } - expect(verifyStub.callCount).to.equal(4) - expect(verifyStub.args[0]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {agree: claimlink}]) - expect(verifyStub.args[1]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) - expect(verifyStub.args[2]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationrevocationlink}]) - expect(verifyStub.args[3]).to.deep.equal([{did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor'}, {revoke: attestationlink}]) + await discipl.registerConnector('mock', stubConnector) - expect(getSsidOfClaimStub.calledOnce).to.equal(true) - expect(getSsidOfClaimStub.args[0]).to.deep.equal(['attestationRef']) + let verifiedAttestor = await discipl.verify('agree', claimlink, [attestorSsid]) - expect(getNameStub.callCount).to.equal(3) + expect(verifyStub.callCount).to.equal(4) + expect(verifyStub.args[0]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { agree: claimlink }]) + expect(verifyStub.args[1]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { revoke: attestationlink }]) + expect(verifyStub.args[2]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { revoke: attestationrevocationlink }]) + expect(verifyStub.args[3]).to.deep.equal([{ did: 'did:discipl:mock:attestor', connector: stubConnector, pubkey: 'attestor' }, { revoke: attestationlink }]) - expect(verifiedAttestor).to.equal(null) - }) + expect(getSsidOfClaimStub.calledOnce).to.equal(true) + expect(getSsidOfClaimStub.args[0]).to.deep.equal(['attestationRef']) + expect(getNameStub.callCount).to.equal(3) + expect(verifiedAttestor).to.equal(null) }) - ) + }) + ) }) - -