From 6cb46a5db3545640462dda6d1dc793260e17ca9c Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 19:38:34 -0300
Subject: [PATCH 01/19] Add defaults
---
data-vault/README.md | 14 +++++++++
data-vault/src/index.ts | 9 +++---
issuer/README.md | 22 +++++++++++---
issuer/server/index.ts | 36 +++++++---------------
issuer/server/issuer.ts | 45 ++++++++++++++++++++++++++++
issuer/server/services/backOffice.ts | 4 +--
issuer/server/setup/agent.ts | 15 ++++------
tiny-qr/README.md | 6 ++--
tiny-qr/index.js | 2 +-
9 files changed, 105 insertions(+), 48 deletions(-)
create mode 100644 issuer/server/issuer.ts
diff --git a/data-vault/README.md b/data-vault/README.md
index b8802e4..f080daa 100644
--- a/data-vault/README.md
+++ b/data-vault/README.md
@@ -63,6 +63,11 @@ After the _store_ process the holder can verify the file was uploaded accessing
```
PRIVATE_KEY= private key
ADDRESS= matching address
+ ```
+
+ Optional parameters
+
+ ```
AUTH_EXPIRATION_TIME= fixed time for auth tokens to expire in
RPC_URL= rsk testnet rpc url
PORT= to run the data vault
@@ -80,6 +85,15 @@ After the _store_ process the holder can verify the file was uploaded accessing
IPFS_PORT=5001
```
+ Defaults
+
+ ```
+ AUTH_EXPIRATION_TIME=300000
+ RPC_URL=https://did.testnet.rsk.co:4444
+ PORT=5102
+ IPFS_PORT=5001
+ ```
+
6. Fix a bug :/ - go to `node_modules/ethr-did/lib/index.js` and find `"did:ethr:"`. Prepend `"rsk:testnet"`
![fix](./img/fix.png)
diff --git a/data-vault/src/index.ts b/data-vault/src/index.ts
index db4d605..8be0a52 100644
--- a/data-vault/src/index.ts
+++ b/data-vault/src/index.ts
@@ -31,9 +31,10 @@ Debug.enable('*')
const env = {
privateKey: process.env.PRIVATE_KEY,
address: process.env.ADDRESS,
- ipfsPort: process.env.IPFS_PORT ?? '',
- authExpirationTime: process.env.AUTH_EXPIRATION_TIME ?? '',
- port: process.env.PORT
+ ipfsPort: process.env.IPFS_PORT || '5001',
+ authExpirationTime: process.env.AUTH_EXPIRATION_TIME || '300000',
+ port: process.env.PORT || '5102',
+ rpcUrl: process.env.RPC_URL || 'https://did.testnet.rsk.co:4444'
}
/* setup app */
@@ -41,7 +42,7 @@ const app = express()
app.use(cors())
/* setup did resolver */
-const providerConfig = { networks: [{ name: "rsk:testnet", registry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b", rpcUrl: 'https://did.testnet.rsk.co:4444' }] }
+const providerConfig = { networks: [{ name: "rsk:testnet", registry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b", rpcUrl: env.rpcUrl }] }
const ethrDidResolver = getResolver(providerConfig)
const didResolver = new Resolver(ethrDidResolver)
diff --git a/issuer/README.md b/issuer/README.md
index 7eca965..ebd08b0 100644
--- a/issuer/README.md
+++ b/issuer/README.md
@@ -28,26 +28,40 @@ The issuer has 2 processes running:
1. Setup: create a `.env` file with
+ ```
+ SECRET_BOX_KEY= 32 random bytes in hex representation - encryption key
+ ADMIN_PASS= a secure password for admin user - used for basic http auth
+ ```
+
+ Or choose more parameters:
+
```
DEBUG= rif-id:* for app logging - * for all logs
CREDENTIAL_REQUESTS_PORT= port to run credential requests service
SECRET_BOX_KEY= 32 random bytes in hex representation - encryption key
RPC_URL= rsk testnet rpc url - the one in the example was tested and works
DEBUG= regexp for debugging logs
- ADMIN_PASS= a secure password for admin user - used for basic http auth
```
Example
```
+ SECRET_BOX_KEY=29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c
CREDENTIAL_REQUESTS_PORT=5100
REACT_APP_BACKOFFICE_PORT=5101
- SECRET_BOX_KEY=29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c
RPC_URL=https://did.testnet.rsk.co:4444
DEBUG=rif-id:*
ADMIN_PASS=admin
```
+ Defaults
+
+ ```
+ CREDENTIAL_REQUESTS_PORT=5100
+ REACT_APP_BACKOFFICE_PORT=5101
+ RPC_URL=https://did.testnet.rsk.co:4444
+ ```
+
2. Install:
```
@@ -75,10 +89,10 @@ Also a database file will be created. `issuer.sqlite`
cd app
```
-2. Please fill the back office service port again :/, crate a `.env` file
+2. (if the default issuer back office service port was changed) Please fill the back office service port again :/, crate a `.env` file
```
- REACT_APP_BACKOFFICE_PORT=5101
+ REACT_APP_BACKOFFICE_PORT=back office service port
```
or the port you used.
diff --git a/issuer/server/index.ts b/issuer/server/index.ts
index e3fdf56..506896d 100644
--- a/issuer/server/index.ts
+++ b/issuer/server/index.ts
@@ -1,38 +1,22 @@
import dotenv from 'dotenv'
import Debug from 'debug'
-import setupDb from './setup/db'
-import setupAgent from './setup/agent'
-import setupIdentity from './setup/identity'
-
-import credentialRequestService from './services/credentialRequests'
-import backOffice from './services/backOffice'
+import { runIssuer } from './issuer'
const debug = Debug('rif-id:main')
dotenv.config()
-/* debugger from .env */
-if (process.env.DEBUG) {
- Debug.enable(process.env.DEBUG)
-}
-
debug('Setting up')
async function main () {
- const dbConnection = setupDb('./issuer.sqlite')
- const agent = setupAgent(dbConnection)
- await setupIdentity(agent)
-
- debug('Set up')
-
- debug('Starting services')
-
- credentialRequestService(process.env.CREDENTIAL_REQUESTS_PORT, agent)
- backOffice(process.env.REACT_APP_BACKOFFICE_PORT, agent)
-
- debug('Services started')
- debug('Requests at port' + process.env.CREDENTIAL_REQUESTS_PORT)
- debug('Back office at port' + process.env.REACT_APP_BACKOFFICE_PORT)
+ await runIssuer({
+ secretBoxKey: process.env.SECRET_BOX_KEY,
+ rpcUrl: process.env.RPC_URL || 'https://did.testnet.rsk.co:4444',
+ credentialRequestsPort: process.env.CREDENTIAL_REQUESTS_PORT || '5100',
+ backOfficePort: process.env.REACT_APP_BACKOFFICE_PORT || '5101',
+ debuggerOptions: process.env.DEBUG,
+ adminPass: process.env.ADMIN_PASS
+ })
}
-main().catch(e => { debug(e); process.exit(1) })
\ No newline at end of file
+main().catch(e => { debug(e); process.exit(1) })
diff --git a/issuer/server/issuer.ts b/issuer/server/issuer.ts
new file mode 100644
index 0000000..39fdc2c
--- /dev/null
+++ b/issuer/server/issuer.ts
@@ -0,0 +1,45 @@
+import dotenv from 'dotenv'
+import Debug from 'debug'
+
+import setupDb from './setup/db'
+import setupAgent from './setup/agent'
+import setupIdentity from './setup/identity'
+
+import credentialRequestService from './services/credentialRequests'
+import backOffice from './services/backOffice'
+
+import { runIssuer } from './issuer'
+
+const debug = Debug('rif-id:main')
+dotenv.config()
+
+debug('Setting up')
+
+export async function runIssuer ({
+ secretBoxKey,
+ rpcUrl,
+ credentialRequestsPort,
+ backOfficePort,
+ debuggerOptions,
+ adminPass
+}) {
+ /* debugger from .env */
+ if (debuggerOptions) {
+ Debug.enable(debuggerOptions)
+ }
+
+ const dbConnection = setupDb('./issuer.sqlite')
+ const agent = setupAgent(dbConnection, secretBoxKey, rpcUrl)
+ await setupIdentity(agent)
+
+ debug('Set up')
+
+ debug('Starting services')
+
+ credentialRequestService(credentialRequestsPort, agent)
+ backOffice(backOfficePort, agent, adminPass)
+
+ debug('Services started')
+ debug('Requests at port' + credentialRequestsPort)
+ debug('Back office at port' + backOfficePort)
+}
diff --git a/issuer/server/services/backOffice.ts b/issuer/server/services/backOffice.ts
index d5b8326..48e1e49 100644
--- a/issuer/server/services/backOffice.ts
+++ b/issuer/server/services/backOffice.ts
@@ -9,11 +9,11 @@ import CredentialRequest from '../lib/CredentialRequest'
const debug = Debug('rif-id:services:backOffice')
const trace = v => { debug(v); return v }
-export default function backOffice(port, agent) {
+export default function backOffice(port, agent, adminPass) {
const app = express()
app.use(cors())
app.use(basicAuth({
- users: { 'admin': process.env.ADMIN_PASS }
+ users: { 'admin': adminPass }
}))
const getAllRequests = () => {
diff --git a/issuer/server/setup/agent.ts b/issuer/server/setup/agent.ts
index d3e25c8..f2af0c1 100644
--- a/issuer/server/setup/agent.ts
+++ b/issuer/server/setup/agent.ts
@@ -12,10 +12,9 @@ import Debug from 'debug'
const debug = Debug('rif-id:setup:agent')
-function createIdentityProviders(dbConnection) {
- const secretBox = new SecretBox(process.env.SECRET_BOX_KEY)
+function createIdentityProviders(dbConnection, secretBoxKey ,rpcUrl) {
+ const secretBox = new SecretBox(secretBoxKey)
const keyStore = new KeyStore(dbConnection, secretBox)
- const rpcUrl = process.env.RPC_URL
const kms = new KeyManagementSystem(keyStore)
const identityStore = new IdentityStore('issuer-ethr', dbConnection)
@@ -35,9 +34,7 @@ function createServiceControllers() {
return []
}
-function createResolver() {
- const rpcUrl = process.env.RPC_URL
-
+function createResolver(rpcUrl) {
return new DafResolver({ networks: [
{ name: "rsk:testnet", registry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b", rpcUrl },
]})
@@ -60,10 +57,10 @@ function createActionHandler() {
return actionHandler
}
-export default function setupAgent(dbConnection) {
- const identityProviders = createIdentityProviders(dbConnection)
+export default function setupAgent(dbConnection, secreBoxKey, rpcUrl) {
+ const identityProviders = createIdentityProviders(dbConnection, secreBoxKey, rpcUrl)
const serviceControllers = createServiceControllers()
- const didResolver = createResolver()
+ const didResolver = createResolver(rpcUrl)
const messageHandler = createMessageHandler()
const actionHandler = createActionHandler()
diff --git a/tiny-qr/README.md b/tiny-qr/README.md
index 4502a0b..a27d85c 100644
--- a/tiny-qr/README.md
+++ b/tiny-qr/README.md
@@ -25,14 +25,16 @@ Holder Tiny QR Verifier
npm i
```
-2. Configure, create a .env file with
+2. (optional) Configure, create a .env file with
+
+ Defaults to:
```
TINY_QR_PORT=5103
TINY_QR_URL=http://localhost:5103
```
- Ensure to put DNS in Tiny QR URL if used
+ **Ensure to put DNS in Tiny QR URL if used**
3. Run
diff --git a/tiny-qr/index.js b/tiny-qr/index.js
index 02ec048..c5db8e3 100644
--- a/tiny-qr/index.js
+++ b/tiny-qr/index.js
@@ -1,4 +1,4 @@
require('dotenv').config()
const tinyQr = require('./tinyQr')
-tinyQr(process.env.TINY_QR_PORT, process.env.TINY_QR_URL)
+tinyQr(process.env.TINY_QR_PORT || 5103, process.env.TINY_QR_URL || 'http://localhost:5103')
From 4fec3ea3c019962dba4b190d29f373e39228f426 Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 19:41:09 -0300
Subject: [PATCH 02/19] Move data vault script
---
data-vault/package.json | 2 +-
data-vault/src/scripts/index.ts | 1 +
.../src/{index.ts => services/centralizedIPFSPinner.ts} | 4 ++--
3 files changed, 4 insertions(+), 3 deletions(-)
create mode 100644 data-vault/src/scripts/index.ts
rename data-vault/src/{index.ts => services/centralizedIPFSPinner.ts} (97%)
diff --git a/data-vault/package.json b/data-vault/package.json
index ec947ec..af38642 100644
--- a/data-vault/package.json
+++ b/data-vault/package.json
@@ -6,7 +6,7 @@
"scripts": {
"start:build": "tsc",
"start": "npm run start:build && node build/index.js",
- "start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/index.js\"",
+ "start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/scripts/index.js\"",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
diff --git a/data-vault/src/scripts/index.ts b/data-vault/src/scripts/index.ts
new file mode 100644
index 0000000..15ab056
--- /dev/null
+++ b/data-vault/src/scripts/index.ts
@@ -0,0 +1 @@
+import '../services/centralizedIPFSPinner'
diff --git a/data-vault/src/index.ts b/data-vault/src/services/centralizedIPFSPinner.ts
similarity index 97%
rename from data-vault/src/index.ts
rename to data-vault/src/services/centralizedIPFSPinner.ts
index 8be0a52..bfaf071 100644
--- a/data-vault/src/index.ts
+++ b/data-vault/src/services/centralizedIPFSPinner.ts
@@ -21,7 +21,7 @@ import { createVerifiableCredentialJwt } from 'did-jwt-vc'
import { verifyJWT } from 'did-jwt'
/* Data vault */
-import { DataVaultProviderIPFS, Entities } from './lib/DataVaultProviderIPFS'
+import { DataVaultProviderIPFS, Entities } from '../lib/DataVaultProviderIPFS'
/* env */
dotenv.config()
@@ -140,4 +140,4 @@ createConnection({
})
app.listen(env.port, () => debug(`Data vault started on port ${env.port}`))
-}).catch(error => console.log(error));
+});
From 717993e9c0328cadf89d074b1adafe4d6011eea8 Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 20:37:34 -0300
Subject: [PATCH 03/19] Refactor data vault
---
data-vault/package-lock.json | 4 +-
data-vault/package.json | 6 +-
data-vault/src/scripts/index.ts | 32 +-
.../src/services/centralizedIPFSPinner.ts | 226 +-
patch/ethrDID-copy.js | 2 +
staging/.gitignore | 4 +
staging/README.md | 9 +
staging/package-lock.json | 1991 +++++++++++++++++
staging/package.json | 29 +
staging/src/index.ts | 33 +
staging/tsconfig.json | 69 +
11 files changed, 2281 insertions(+), 124 deletions(-)
create mode 100644 patch/ethrDID-copy.js
create mode 100644 staging/.gitignore
create mode 100644 staging/README.md
create mode 100644 staging/package-lock.json
create mode 100644 staging/package.json
create mode 100644 staging/src/index.ts
create mode 100644 staging/tsconfig.json
diff --git a/data-vault/package-lock.json b/data-vault/package-lock.json
index a45ce1f..96110cc 100644
--- a/data-vault/package-lock.json
+++ b/data-vault/package-lock.json
@@ -1,6 +1,6 @@
{
- "name": "data-vault",
- "version": "1.0.0",
+ "name": "@rsksmart/rif-id-data-vault-service",
+ "version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/data-vault/package.json b/data-vault/package.json
index af38642..3c72a56 100644
--- a/data-vault/package.json
+++ b/data-vault/package.json
@@ -1,11 +1,11 @@
{
- "name": "data-vault",
- "version": "1.0.0",
+ "name": "@rsksmart/rif-id-data-vault-service",
+ "version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start:build": "tsc",
- "start": "npm run start:build && node build/index.js",
+ "start": "npm run start:build && node build/scripts/index.js",
"start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/scripts/index.js\"",
"test": "echo \"Error: no test specified\" && exit 1"
},
diff --git a/data-vault/src/scripts/index.ts b/data-vault/src/scripts/index.ts
index 15ab056..f1de090 100644
--- a/data-vault/src/scripts/index.ts
+++ b/data-vault/src/scripts/index.ts
@@ -1 +1,31 @@
-import '../services/centralizedIPFSPinner'
+/* env */
+import dotenv from 'dotenv'
+import Debug from 'debug'
+import express from 'express'
+import cors from 'cors'
+import { setupCentralizedIPFSPinner } from '../services/centralizedIPFSPinner'
+
+/* env */
+dotenv.config()
+Debug.enable('*')
+
+const debug = Debug('rif-id:data-vault:scripts')
+
+if (!process.env.PRIVATE_KEY) throw new Error('Setup private key')
+if (!process.env.ADDRESS) throw new Error('Setup address')
+
+const env = {
+ privateKey: process.env.PRIVATE_KEY,
+ address: process.env.ADDRESS,
+ ipfsPort: process.env.IPFS_PORT || '5001',
+ authExpirationTime: process.env.AUTH_EXPIRATION_TIME || '300000',
+ rpcUrl: process.env.RPC_URL || 'https://did.testnet.rsk.co:4444'
+}
+
+const port = process.env.PORT || '5102'
+
+/* setup app */
+const app = express()
+app.use(cors())
+
+setupCentralizedIPFSPinner(app, env).then(() => app.listen(port, () => debug(`Data vault started on port ${port}`)))
diff --git a/data-vault/src/services/centralizedIPFSPinner.ts b/data-vault/src/services/centralizedIPFSPinner.ts
index bfaf071..0229d90 100644
--- a/data-vault/src/services/centralizedIPFSPinner.ts
+++ b/data-vault/src/services/centralizedIPFSPinner.ts
@@ -1,10 +1,5 @@
-/* env */
-import dotenv from 'dotenv'
-import Debug from 'debug'
-
/* server deps */
-import express from 'express'
-import cors from 'cors'
+import { Express } from 'express'
import bodyParser from 'body-parser'
/* data base */
@@ -23,121 +18,116 @@ import { verifyJWT } from 'did-jwt'
/* Data vault */
import { DataVaultProviderIPFS, Entities } from '../lib/DataVaultProviderIPFS'
-/* env */
-dotenv.config()
-const debug = Debug('rif-id:data-vault')
-Debug.enable('*')
-
-const env = {
- privateKey: process.env.PRIVATE_KEY,
- address: process.env.ADDRESS,
- ipfsPort: process.env.IPFS_PORT || '5001',
- authExpirationTime: process.env.AUTH_EXPIRATION_TIME || '300000',
- port: process.env.PORT || '5102',
- rpcUrl: process.env.RPC_URL || 'https://did.testnet.rsk.co:4444'
+/* debugger */
+import Debug from 'debug'
+const debug = Debug('rif-id:data-vault:services:centralized-pinner')
+
+interface CentralizedIPFSPinnerEnv {
+ privateKey: string;
+ address: string;
+ ipfsPort: string;
+ authExpirationTime: string;
+ rpcUrl: string;
}
-/* setup app */
-const app = express()
-app.use(cors())
-
-/* setup did resolver */
-const providerConfig = { networks: [{ name: "rsk:testnet", registry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b", rpcUrl: env.rpcUrl }] }
-const ethrDidResolver = getResolver(providerConfig)
-const didResolver = new Resolver(ethrDidResolver)
-
-const identity = new EthrDID({
- privateKey: env.privateKey,
- address: env.address
-})
-
-/* setup auth */
-const authDictionary: any = {} // stores tokens and expiration time for given did
-
-debug(`Identity: ${identity.did}`)
-
-createConnection({
- type: 'sqlite',
- database: 'data-vault-mapper.sqlite',
- entities: Entities,
- synchronize: true,
- logging: false
-}).then(connection => {
- /* setup data vault */
- const dataVaultProvider = new DataVaultProviderIPFS(
- connection,
- { host: 'localhost', port: env.ipfsPort, protocol: 'http' }
- )
-
- app.get('/identity', function(req, res) {
- debug(`Requested identity`)
- res.status(200).send(identity.did)
- })
-
+export function setupCentralizedIPFSPinner(app: Express, env: CentralizedIPFSPinnerEnv, prefix = '') {
+ /* setup did resolver */
+ const providerConfig = { networks: [{ name: "rsk:testnet", registry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b", rpcUrl: env.rpcUrl }] }
+ const ethrDidResolver = getResolver(providerConfig)
+ const didResolver = new Resolver(ethrDidResolver)
- const authenticate = (jwt: string) => verifyJWT(jwt, {
- resolver: didResolver
- }).then(({ payload, issuer }) => {
- if (authDictionary[issuer].token !== payload.claims.find((claim: any) => claim.claimType === 'token').claimValue) throw new Error('Invalid token')
- if (authDictionary[issuer].exp < Math.floor(+new Date() / 1000)) throw new Error('Token expired')
- return { payload, issuer }
+ const identity = new EthrDID({
+ privateKey: env.privateKey,
+ address: env.address
})
- app.post('/auth', bodyParser.json(), function(req, res) {
- const { did } = req.body
- const token = randomBytes(64).toString('hex')
- debug(`${did} requested auth - token ${token}`)
-
- const sub = did
- const iss = identity.did
- const nbf = Math.round((+Date.now()) / 1000)
- const exp = Math.round((+Date.now() + parseInt(env.authExpirationTime)) / 1000)
- const credentialSubject = { token }
-
- authDictionary[did] = { token, exp }
-
- createVerifiableCredentialJwt({
- sub,
- iss,
- nbf,
- exp,
- vc: {
- '@context': ['https://www.w3.org/2018/credentials/v1'],
- type: ['VerifiableCredential'],
- credentialSubject
- }
- }, identity).then(jwt => res.status(200).send(jwt))
+ /* setup auth */
+ const authDictionary: any = {} // stores tokens and expiration time for given did
+
+ debug(`Identity: ${identity.did}`)
+
+ return createConnection({
+ type: 'sqlite',
+ database: 'data-vault-mapper.sqlite',
+ entities: Entities,
+ synchronize: true,
+ logging: false
+ }).then(connection => {
+ /* setup data vault */
+ const dataVaultProvider = new DataVaultProviderIPFS(
+ connection,
+ { host: 'localhost', port: env.ipfsPort, protocol: 'http' }
+ )
+
+ /* authentication */
+ const authenticate = (jwt: string) => verifyJWT(jwt, {
+ resolver: didResolver
+ }).then(({ payload, issuer }) => {
+ if (authDictionary[issuer].token !== payload.claims.find((claim: any) => claim.claimType === 'token').claimValue) throw new Error('Invalid token')
+ if (authDictionary[issuer].exp < Math.floor(+new Date() / 1000)) throw new Error('Token expired')
+ return { payload, issuer }
+ })
+
+ const authenticateAndFindClaim = (jwt: string) => (claimType: any) => authenticate(jwt)
+ .then(({ issuer, payload }) => ({ issuer, content: payload.claims.find((claim: any) => claim.claimType === claimType).claimValue }))
+
+ app.get(prefix + '/identity', function(req, res) {
+ debug(`Requested identity`)
+ res.status(200).send(identity.did)
+ })
+
+ app.post(prefix + '/auth', bodyParser.json(), function(req, res) {
+ const { did } = req.body
+ const token = randomBytes(64).toString('hex')
+ debug(`${did} requested auth - token ${token}`)
+
+ const sub = did
+ const iss = identity.did
+ const nbf = Math.round((+Date.now()) / 1000)
+ const exp = Math.round((+Date.now() + parseInt(env.authExpirationTime)) / 1000)
+ const credentialSubject = { token }
+
+ authDictionary[did] = { token, exp }
+
+ createVerifiableCredentialJwt({
+ sub,
+ iss,
+ nbf,
+ exp,
+ vc: {
+ '@context': ['https://www.w3.org/2018/credentials/v1'],
+ type: ['VerifiableCredential'],
+ credentialSubject
+ }
+ }, identity).then(jwt => res.status(200).send(jwt))
+ })
+
+ app.post(prefix + '/testAuth', bodyParser.json(), function(req, res) {
+ const { jwt } = req.body
+ debug(`Testing auth`)
+
+ authenticate(jwt)
+ .then(() => res.status(200).send('Authenticated'))
+ .catch(() => res.status(200).send('Not authenticated'))
+ })
+
+ /* operations */
+ app.post(prefix + '/put', bodyParser.json(), function (req, res) {
+ debug(`Put`)
+ const { jwt } = req.body
+
+ authenticateAndFindClaim(jwt)('content')
+ .then(({ issuer, content }) => dataVaultProvider.put(issuer, Buffer.from(content)))
+ .then(cid => res.status(200).send(cid))
+ })
+
+ app.post(prefix + '/get', bodyParser.json(), function (req, res) {
+ debug(`Get`)
+ const { jwt } = req.body
+
+ authenticate(jwt)
+ .then(({ issuer }) => dataVaultProvider.get(issuer))
+ .then(cids => res.status(200).send(JSON.stringify(cids)))
+ })
})
-
- app.post('/testAuth', bodyParser.json(), function(req, res) {
- const { jwt } = req.body
- debug(`Testing auth`)
-
- authenticate(jwt)
- .then(() => res.status(200).send('Authenticated'))
- .catch(() => res.status(200).send('Not authenticated'))
- })
-
- const authenticateAndFindClaim = (jwt: string) => (claimType: any) => authenticate(jwt)
- .then(({ issuer, payload }) => ({ issuer, content: payload.claims.find((claim: any) => claim.claimType === claimType).claimValue }))
-
- app.post('/put', bodyParser.json(), function (req, res) {
- debug(`Put`)
- const { jwt } = req.body
-
- authenticateAndFindClaim(jwt)('content')
- .then(({ issuer, content }) => dataVaultProvider.put(issuer, Buffer.from(content)))
- .then(cid => res.status(200).send(cid))
- })
-
- app.post('/get', bodyParser.json(), function (req, res) {
- debug(`Get`)
- const { jwt } = req.body
-
- authenticate(jwt)
- .then(({ issuer }) => dataVaultProvider.get(issuer))
- .then(cids => res.status(200).send(JSON.stringify(cids)))
- })
-
- app.listen(env.port, () => debug(`Data vault started on port ${env.port}`))
-});
+}
diff --git a/patch/ethrDID-copy.js b/patch/ethrDID-copy.js
new file mode 100644
index 0000000..b16a0c9
--- /dev/null
+++ b/patch/ethrDID-copy.js
@@ -0,0 +1,2 @@
+function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var r=e(require("ethjs-provider-http")),t=e(require("ethjs-query")),i=e(require("ethjs-contract")),n=e(require("ethr-did-resolver/contracts/ethr-did-registry.json")),o=require("did-jwt"),s=require("did-jwt/lib/Digest"),u=require("buffer"),d=require("ethr-did-resolver"),a=new(0,require("elliptic").ec)("secp256k1"),c=d.delegateTypes.Secp256k1VerificationKey2018,h=function(e){void 0===e&&(e={});var s=function(e){return void 0===e&&(e={}),e.provider?e.provider:e.web3?e.web3.currentProvider:new r(e.rpcUrl||"https://mainnet.infura.io/ethr-did")}(e),u=new t(s),a=e.registry||d.REGISTRY,c=new i(u)(n);if(this.registry=c.at(a),this.address=e.address,!this.address)throw new Error("No address is set for EthrDid");this.did="did:ethr:rsk:testnet:"+this.address,e.signer?this.signer=e.signer:e.privateKey&&(this.signer=o.SimpleSigner(e.privateKey))};h.createKeyPair=function(){var e=a.genKeyPair(),r=e.getPublic("hex"),t=e.getPrivate("hex");return{address:s.toEthereumAddress(r),privateKey:t}},h.prototype.lookupOwner=function(e){void 0===e&&(e=!0);try{return e&&this.owner?this.owner:Promise.resolve(this.registry.identityOwner(this.address)).then(function(e){return e[0]})}catch(e){return Promise.reject(e)}},h.prototype.changeOwner=function(e){try{var r=this;return Promise.resolve(r.lookupOwner()).then(function(t){return Promise.resolve(r.registry.changeOwner(r.address,e,{from:t})).then(function(t){return r.owner=e,t})})}catch(e){return Promise.reject(e)}},h.prototype.addDelegate=function(e,r){void 0===r&&(r={});try{var t=this,i=r.delegateType||c,n=r.expiresIn||86400;return Promise.resolve(t.lookupOwner()).then(function(r){return t.registry.addDelegate(t.address,i,e,n,{from:r})})}catch(e){return Promise.reject(e)}},h.prototype.revokeDelegate=function(e,r){void 0===r&&(r=c);try{var t=this;return Promise.resolve(t.lookupOwner()).then(function(i){return t.registry.revokeDelegate(t.address,r,e,{from:i})})}catch(e){return Promise.reject(e)}},h.prototype.setAttribute=function(e,r,t,i){void 0===t&&(t=86400);try{var n=this;return Promise.resolve(n.lookupOwner()).then(function(o){return n.registry.setAttribute(n.address,d.stringToBytes32(e),function(e,r){if(u.Buffer.isBuffer(r))return"0x"+r.toString("hex");var t=e.match(/^did\/(pub|auth|svc)\/(\w+)(\/(\w+))?(\/(\w+))?$/);return t&&"base64"===t[6]?"0x"+u.Buffer.from(r,"base64").toString("hex"):r.match(/^0x[0-9a-fA-F]*$/)?r:"0x"+u.Buffer.from(r).toString("hex")}(e,r),t,{from:o,gas:i})})}catch(e){return Promise.reject(e)}},h.prototype.createSigningDelegate=function(e,r){void 0===e&&(e=c),void 0===r&&(r=86400);try{var t=h.createKeyPair();return this.signer=o.SimpleSigner(t.privateKey),Promise.resolve(this.addDelegate(t.address,{delegateType:e,expiresIn:r})).then(function(e){return{kp:t,txHash:e}})}catch(e){return Promise.reject(e)}},h.prototype.signJWT=function(e,r){try{if("function"!=typeof this.signer)throw new Error("No signer configured");var t={signer:this.signer,alg:"ES256K-R",issuer:this.did};return r&&(t.expiresIn=r),o.createJWT(e,t)}catch(e){return Promise.reject(e)}},h.prototype.verifyJWT=function(e,r){void 0===r&&(r=this.did);try{return o.verifyJWT(e,{audience:r})}catch(e){return Promise.reject(e)}},module.exports=h;
+//# sourceMappingURL=index.js.map
diff --git a/staging/.gitignore b/staging/.gitignore
new file mode 100644
index 0000000..c80148d
--- /dev/null
+++ b/staging/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+.env
+build/
+*.sqlite
diff --git a/staging/README.md b/staging/README.md
new file mode 100644
index 0000000..ffabf51
--- /dev/null
+++ b/staging/README.md
@@ -0,0 +1,9 @@
+
+
+
+Staging
+
+ Put all RIF services on stage
+
+
+
diff --git a/staging/package-lock.json b/staging/package-lock.json
new file mode 100644
index 0000000..3cebca2
--- /dev/null
+++ b/staging/package-lock.json
@@ -0,0 +1,1991 @@
+{
+ "name": "staging",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@sindresorhus/is": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+ "dev": true
+ },
+ "@szmarczak/http-timer": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+ "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+ "dev": true,
+ "requires": {
+ "defer-to-connect": "^1.0.1"
+ }
+ },
+ "@types/body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
+ "requires": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+ "dev": true
+ },
+ "@types/connect": {
+ "version": "3.4.33",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
+ "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/cors": {
+ "version": "2.8.7",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.7.tgz",
+ "integrity": "sha512-sOdDRU3oRS7LBNTIqwDkPJyq0lpHYcbMTt0TrjzsXbk/e37hcLTH6eZX7CdbDeN0yJJvzw9hFBZkbtCSbk/jAQ==",
+ "requires": {
+ "@types/express": "*"
+ }
+ },
+ "@types/debug": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
+ "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ=="
+ },
+ "@types/express": {
+ "version": "4.17.7",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
+ "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
+ "requires": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "*",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "@types/express-serve-static-core": {
+ "version": "4.17.9",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz",
+ "integrity": "sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA==",
+ "requires": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "@types/mime": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
+ "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
+ },
+ "@types/node": {
+ "version": "14.0.27",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz",
+ "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g=="
+ },
+ "@types/qs": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz",
+ "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ=="
+ },
+ "@types/range-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
+ },
+ "@types/serve-static": {
+ "version": "1.13.5",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz",
+ "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==",
+ "requires": {
+ "@types/express-serve-static-core": "*",
+ "@types/mime": "*"
+ }
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "ansi-align": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
+ "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.0.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "boxen": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
+ "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^5.3.1",
+ "chalk": "^3.0.0",
+ "cli-boxes": "^2.2.0",
+ "string-width": "^4.1.0",
+ "term-size": "^2.1.0",
+ "type-fest": "^0.8.1",
+ "widest-line": "^3.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "cacheable-request": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+ "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+ "dev": true,
+ "requires": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^3.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^4.1.0",
+ "responselike": "^1.0.2"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+ "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "dev": true
+ }
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+ "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.4.0"
+ }
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "cli-boxes": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz",
+ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concurrently": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz",
+ "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "date-fns": "^2.0.1",
+ "lodash": "^4.17.15",
+ "read-pkg": "^4.0.1",
+ "rxjs": "^6.5.2",
+ "spawn-command": "^0.0.2-1",
+ "supports-color": "^6.1.0",
+ "tree-kill": "^1.2.2",
+ "yargs": "^13.3.0"
+ }
+ },
+ "configstore": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
+ "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^5.2.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^3.0.0",
+ "unique-string": "^2.0.0",
+ "write-file-atomic": "^3.0.0",
+ "xdg-basedir": "^4.0.0"
+ }
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "requires": {
+ "object-assign": "^4",
+ "vary": "^1"
+ }
+ },
+ "crypto-random-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+ "dev": true
+ },
+ "date-fns": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.15.0.tgz",
+ "integrity": "sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
+ "defer-to-connect": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "dot-prop": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
+ "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^2.0.0"
+ }
+ },
+ "dotenv": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+ "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "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"
+ }
+ },
+ "escape-goat": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
+ "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==",
+ "dev": true
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "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
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~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==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "dev": true,
+ "optional": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "global-dirs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz",
+ "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.5"
+ }
+ },
+ "got": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+ "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "^0.14.0",
+ "@szmarczak/http-timer": "^1.1.2",
+ "cacheable-request": "^6.0.0",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^4.1.0",
+ "lowercase-keys": "^1.0.1",
+ "mimic-response": "^1.0.1",
+ "p-cancelable": "^1.0.0",
+ "to-readable-stream": "^1.0.0",
+ "url-parse-lax": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-yarn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
+ "dev": true
+ },
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
+ },
+ "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-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "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-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz",
+ "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^2.0.1",
+ "is-path-inside": "^3.0.1"
+ }
+ },
+ "is-npm": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
+ "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz",
+ "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==",
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-yarn-global": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
+ "dev": true
+ },
+ "json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "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
+ },
+ "keyv": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+ "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "latest-version": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+ "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+ "dev": true,
+ "requires": {
+ "package-json": "^6.3.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+ "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+ },
+ "mime-types": {
+ "version": "2.1.27",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+ "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+ "requires": {
+ "mime-db": "1.44.0"
+ }
+ },
+ "mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "nodemon": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz",
+ "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^3.2.2",
+ "debug": "^3.2.6",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.0.4",
+ "pstree.remy": "^1.1.7",
+ "semver": "^5.7.1",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.2",
+ "update-notifier": "^4.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
+ "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "p-cancelable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "package-json": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+ "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+ "dev": true,
+ "requires": {
+ "got": "^9.6.0",
+ "registry-auth-token": "^4.0.0",
+ "registry-url": "^5.0.0",
+ "semver": "^6.2.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "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"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "proxy-addr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
+ "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.1"
+ }
+ },
+ "pstree.remy": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pupa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz",
+ "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==",
+ "dev": true,
+ "requires": {
+ "escape-goat": "^2.0.0"
+ }
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ }
+ },
+ "read-pkg": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
+ "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
+ "dev": true,
+ "requires": {
+ "normalize-package-data": "^2.3.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0"
+ }
+ },
+ "readdirp": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+ "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "registry-auth-token": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz",
+ "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "registry-url": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+ "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "dev": true,
+ "requires": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "rxjs": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
+ "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "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=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "semver-diff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+ "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~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==",
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+ "dev": true
+ },
+ "spawn-command": {
+ "version": "0.0.2-1",
+ "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
+ "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "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": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "term-size": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
+ "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==",
+ "dev": true
+ },
+ "to-readable-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+ "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dev": true,
+ "requires": {
+ "nopt": "~1.0.10"
+ }
+ },
+ "tree-kill": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+ "dev": true
+ },
+ "tslib": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "3.9.7",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
+ "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
+ "dev": true
+ },
+ "undefsafe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
+ "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
+ "dev": true,
+ "requires": {
+ "debug": "^2.2.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"
+ }
+ }
+ }
+ },
+ "unique-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+ "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^2.0.0"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "update-notifier": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz",
+ "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==",
+ "dev": true,
+ "requires": {
+ "boxen": "^4.2.0",
+ "chalk": "^3.0.0",
+ "configstore": "^5.0.1",
+ "has-yarn": "^2.1.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^2.0.0",
+ "is-installed-globally": "^0.3.1",
+ "is-npm": "^4.0.0",
+ "is-yarn-global": "^0.3.0",
+ "latest-version": "^5.0.0",
+ "pupa": "^2.0.1",
+ "semver-diff": "^3.1.1",
+ "xdg-basedir": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0"
+ }
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "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"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ }
+ }
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "xdg-basedir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
+ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+}
diff --git a/staging/package.json b/staging/package.json
new file mode 100644
index 0000000..20faf37
--- /dev/null
+++ b/staging/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "staging",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "dependencies": {
+ "@types/cors": "^2.8.7",
+ "@types/debug": "^4.1.5",
+ "@types/express": "^4.17.7",
+ "cors": "^2.8.5",
+ "debug": "^4.1.1",
+ "dotenv": "^8.2.0",
+ "express": "^4.17.1"
+ },
+ "devDependencies": {
+ "concurrently": "^5.3.0",
+ "nodemon": "^2.0.4",
+ "typescript": "^3.9.7"
+ },
+ "scripts": {
+ "build:data-vault": "cd ../data-vault && npm run start:build",
+ "build": "npm run build:data-vault && tsc",
+ "start": "npm run build && node build/index.js",
+ "start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/index.js\"",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC"
+}
diff --git a/staging/src/index.ts b/staging/src/index.ts
new file mode 100644
index 0000000..93619c4
--- /dev/null
+++ b/staging/src/index.ts
@@ -0,0 +1,33 @@
+/* env */
+import dotenv from 'dotenv'
+import Debug from 'debug'
+import express from 'express'
+import cors from 'cors'
+import { setupCentralizedIPFSPinner } from '../../data-vault/build/services/centralizedIPFSPinner'
+
+/* env */
+dotenv.config()
+Debug.enable('*')
+
+const debug = Debug('rif-id:data-vault:scripts')
+
+if (!process.env.DATA_VAULT_PRIVATE_KEY) throw new Error('Setup private key')
+if (!process.env.DATA_VAULT_ADDRESS) throw new Error('Setup address')
+
+const env = {
+ privateKey: process.env.DATA_VAULT_PRIVATE_KEY,
+ address: process.env.DATA_VAULT_ADDRESS,
+ ipfsPort: process.env.DATA_VAULT_IPFS_PORT || '5001',
+ authExpirationTime: process.env.DATA_VAULT_AUTH_EXPIRATION_TIME || '300000',
+ rpcUrl: process.env.DATA_VAULT_RPC_URL || 'https://did.testnet.rsk.co:4444'
+}
+
+const port = process.env.PORT || 3300
+
+/* setup app */
+const app = express()
+app.use(cors())
+
+setupCentralizedIPFSPinner(app, env, '/data-vault').then(() => app.listen(port, () => {
+ debug(`Data vault started on http://localhost:${port}/data-vault`)
+}))
diff --git a/staging/tsconfig.json b/staging/tsconfig.json
new file mode 100644
index 0000000..0ba8d0c
--- /dev/null
+++ b/staging/tsconfig.json
@@ -0,0 +1,69 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
+
+ /* Basic Options */
+ // "incremental": true, /* Enable incremental compilation */
+ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
+ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
+ // "lib": [], /* Specify library files to be included in the compilation. */
+ // "allowJs": true, /* Allow javascript files to be compiled. */
+ // "checkJs": true, /* Report errors in .js files. */
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+ // "declaration": true, /* Generates corresponding '.d.ts' file. */
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
+ // "sourceMap": true, /* Generates corresponding '.map' file. */
+ // "outFile": "./", /* Concatenate and emit output to single file. */
+ "outDir": "./build", /* Redirect output structure to the directory. */
+ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+ // "composite": true, /* Enable project compilation */
+ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
+ // "removeComments": true, /* Do not emit comments to output. */
+ // "noEmit": true, /* Do not emit outputs. */
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+ /* Strict Type-Checking Options */
+ "strict": true, /* Enable all strict type-checking options. */
+ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* Enable strict null checks. */
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
+
+ /* Additional Checks */
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+
+ /* Module Resolution Options */
+ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
+ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
+ // "typeRoots": [], /* List of folders to include type definitions from. */
+ // "types": [], /* Type declaration files to be included in compilation. */
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+
+ /* Source Map Options */
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+ /* Experimental Options */
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+
+ /* Advanced Options */
+ "skipLibCheck": true, /* Skip type checking of declaration files. */
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
+ }
+}
From 5f247985d98947747092757ad47d075e7d5144e9 Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 20:46:44 -0300
Subject: [PATCH 04/19] Fix data vault installation
---
data-vault/README.md | 14 +++++++-------
data-vault/package.json | 3 ++-
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/data-vault/README.md b/data-vault/README.md
index f080daa..3d13a34 100644
--- a/data-vault/README.md
+++ b/data-vault/README.md
@@ -44,6 +44,12 @@ After the _store_ process the holder can verify the file was uploaded accessing
npm i
```
+ `postinstall` is running a script to append `"rsk:testnet"` to `"did:ethr:"` methods name
+
+ To do it manually, remove `postinstall` script before running installing, then find this in `node_modules/ethr-did/lib//index.js`
+
+ ![fix](./img/fix.png)
+
2. Install IPFS CLI. Find your option: https://docs.ipfs.io/how-to/command-line-quick-start/.
3. Init IPFS
@@ -94,13 +100,7 @@ After the _store_ process the holder can verify the file was uploaded accessing
IPFS_PORT=5001
```
-6. Fix a bug :/ - go to `node_modules/ethr-did/lib/index.js` and find `"did:ethr:"`. Prepend `"rsk:testnet"`
-
- ![fix](./img/fix.png)
-
- You can also copy paste the file in `./lib/ethrDID-copy.js`
-
-7. In another terminal, start data-vault:
+6. In another terminal, start data-vault:
```
npm run start
diff --git a/data-vault/package.json b/data-vault/package.json
index 3c72a56..ac9fd0a 100644
--- a/data-vault/package.json
+++ b/data-vault/package.json
@@ -7,7 +7,8 @@
"start:build": "tsc",
"start": "npm run start:build && node build/scripts/index.js",
"start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/scripts/index.js\"",
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "postinstall": "rm ./node_modules/ethr-did/lib/index.js && cp ./patch/ethrDID-copy.js ./node_modules/ethr-did/lib/index.js"
},
"author": "",
"license": "ISC",
From a2dbab317e1cc2af77b759ea6628ba7ae12e01e9 Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 21:32:12 -0300
Subject: [PATCH 05/19] Refactor issuer services
---
data-vault/tsconfig.json | 2 +-
issuer/server/index.ts | 21 +++++++++--
issuer/server/issuer.ts | 23 +++++-------
issuer/server/services/backOffice.ts | 16 ++++-----
issuer/server/services/credentialRequests.ts | 13 +++----
issuer/tsconfig.json | 2 +-
staging/package.json | 3 +-
staging/src/index.ts | 37 +++++++++++++++-----
8 files changed, 68 insertions(+), 49 deletions(-)
diff --git a/data-vault/tsconfig.json b/data-vault/tsconfig.json
index 19b9606..5027e27 100644
--- a/data-vault/tsconfig.json
+++ b/data-vault/tsconfig.json
@@ -10,7 +10,7 @@
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
- // "declaration": true, /* Generates corresponding '.d.ts' file. */
+ "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
diff --git a/issuer/server/index.ts b/issuer/server/index.ts
index 506896d..75690fb 100644
--- a/issuer/server/index.ts
+++ b/issuer/server/index.ts
@@ -1,5 +1,7 @@
import dotenv from 'dotenv'
import Debug from 'debug'
+import express from 'express'
+import cors from 'cors'
import { runIssuer } from './issuer'
@@ -9,14 +11,27 @@ dotenv.config()
debug('Setting up')
async function main () {
+ const appCredentialRequests = express()
+ appCredentialRequests.use(cors())
+
+ const appBackOffice = express()
+ appBackOffice.use(cors())
+
await runIssuer({
secretBoxKey: process.env.SECRET_BOX_KEY,
rpcUrl: process.env.RPC_URL || 'https://did.testnet.rsk.co:4444',
- credentialRequestsPort: process.env.CREDENTIAL_REQUESTS_PORT || '5100',
- backOfficePort: process.env.REACT_APP_BACKOFFICE_PORT || '5101',
debuggerOptions: process.env.DEBUG,
- adminPass: process.env.ADMIN_PASS
+ adminPass: process.env.ADMIN_PASS,
+ apps: [appCredentialRequests, appBackOffice],
+ backOfficePrefix: '',
+ credentialRequestServicePrefix: ''
})
+
+ const credentialRequestsPort = process.env.CREDENTIAL_REQUESTS_PORT || 5100
+ const backOfficePort = process.env.CREDENTIAL_REQUESTS_PORT || 5101
+
+ appCredentialRequests.listen(credentialRequestsPort, () => debug('Request credential service started at port' + credentialRequestsPort))
+ appBackOffice.listen(backOfficePort, () => debug('Back office service started at port' + backOfficePort))
}
main().catch(e => { debug(e); process.exit(1) })
diff --git a/issuer/server/issuer.ts b/issuer/server/issuer.ts
index 39fdc2c..b36d031 100644
--- a/issuer/server/issuer.ts
+++ b/issuer/server/issuer.ts
@@ -8,8 +8,6 @@ import setupIdentity from './setup/identity'
import credentialRequestService from './services/credentialRequests'
import backOffice from './services/backOffice'
-import { runIssuer } from './issuer'
-
const debug = Debug('rif-id:main')
dotenv.config()
@@ -18,10 +16,11 @@ debug('Setting up')
export async function runIssuer ({
secretBoxKey,
rpcUrl,
- credentialRequestsPort,
- backOfficePort,
debuggerOptions,
- adminPass
+ adminPass,
+ apps,
+ credentialRequestServicePrefix,
+ backOfficePrefix
}) {
/* debugger from .env */
if (debuggerOptions) {
@@ -32,14 +31,8 @@ export async function runIssuer ({
const agent = setupAgent(dbConnection, secretBoxKey, rpcUrl)
await setupIdentity(agent)
- debug('Set up')
-
- debug('Starting services')
-
- credentialRequestService(credentialRequestsPort, agent)
- backOffice(backOfficePort, agent, adminPass)
-
- debug('Services started')
- debug('Requests at port' + credentialRequestsPort)
- debug('Back office at port' + backOfficePort)
+ debug('Setting up services')
+ credentialRequestService(apps[0], agent, credentialRequestServicePrefix)
+ backOffice(apps.length > 1 ? apps[1] : apps[0], agent, adminPass, backOfficePrefix)
+ debug('Services set up')
}
diff --git a/issuer/server/services/backOffice.ts b/issuer/server/services/backOffice.ts
index 48e1e49..04046b2 100644
--- a/issuer/server/services/backOffice.ts
+++ b/issuer/server/services/backOffice.ts
@@ -1,5 +1,3 @@
-import express from 'express'
-import cors from 'cors'
import basicAuth from 'express-basic-auth'
import bodyParser from 'body-parser'
import Debug from 'debug'
@@ -9,9 +7,7 @@ import CredentialRequest from '../lib/CredentialRequest'
const debug = Debug('rif-id:services:backOffice')
const trace = v => { debug(v); return v }
-export default function backOffice(port, agent, adminPass) {
- const app = express()
- app.use(cors())
+export default function backOffice(app, agent, adminPass, backOfficePrefix = '') {
app.use(basicAuth({
users: { 'admin': adminPass }
}))
@@ -22,11 +18,11 @@ export default function backOffice(port, agent, adminPass) {
.then(messages => messages.map(messageToRequest))
}
- app.post('/auth', function (req, res) {
+ app.post(backOfficePrefix + '/auth', function (req, res) {
res.status(200).send()
})
- app.get('/identity', function(req, res) {
+ app.get(backOfficePrefix + '/identity', function(req, res) {
debug('Identity requested')
agent.identityManager.getIdentities()
@@ -36,13 +32,13 @@ export default function backOffice(port, agent, adminPass) {
})
})
- app.get('/requests', function(req, res) {
+ app.get(backOfficePrefix + '/requests', function(req, res) {
debug(`Query requests`)
getAllRequests().then(requests => res.status(200).send(JSON.stringify(requests)))
})
- app.put('/request/:id/status', bodyParser.json(), function(req, res) {
+ app.put(backOfficePrefix + '/request/:id/status', bodyParser.json(), function(req, res) {
const { id } = req.params
const { status } = req.body
debug(`PUT status ${status} for credential request ${id}`)
@@ -63,5 +59,5 @@ export default function backOffice(port, agent, adminPass) {
})
})
- app.listen(port, () => debug(`Back office service started on port ${port}`))
+ //app.listen(port, () => debug(`Back office service started on port ${port}`))
}
diff --git a/issuer/server/services/credentialRequests.ts b/issuer/server/services/credentialRequests.ts
index 8c7c305..c2ec936 100644
--- a/issuer/server/services/credentialRequests.ts
+++ b/issuer/server/services/credentialRequests.ts
@@ -1,5 +1,3 @@
-import express from 'express'
-import cors from 'cors'
import bodyParser from 'body-parser'
import { keccak256 } from 'js-sha3'
import { messageToRequest } from '../lib/messageToRequest'
@@ -27,11 +25,8 @@ type CredentialRequestResponseStatus = 'PENDING' | 'DENIED' | 'SUCCESS'
const credentialRequestResponsePayload = (status: CredentialRequestResponseStatus, raw: string) => ({ status, payload: { raw } })
-export default function credentialRequestService(port, agent) {
- const app = express()
- app.use(cors())
-
- app.post('/requestCredential', bodyParser.text(), function(req, res) {
+export default function credentialRequestService(app, agent, credentialRequestServicePrefix = '') {
+ app.post(credentialRequestServicePrefix + '/requestCredential', bodyParser.text(), function(req, res) {
const message = JSON.parse(req.body)
debug(`Incoming credential request ${message.body}`)
@@ -57,7 +52,7 @@ export default function credentialRequestService(port, agent) {
})
})
- app.get('/receiveCredential', function(req, res) {
+ app.get(credentialRequestServicePrefix + '/receiveCredential', function(req, res) {
debug(`Incoming credential request`)
const { hash } = req.query
@@ -89,5 +84,5 @@ export default function credentialRequestService(port, agent) {
})
})
- app.listen(port, () => debug(`Credential requests service started on port ${port}`))
+ // app.listen(port, () => debug(`Credential requests service started on port ${port}`))
}
diff --git a/issuer/tsconfig.json b/issuer/tsconfig.json
index be41ece..d35fdc0 100644
--- a/issuer/tsconfig.json
+++ b/issuer/tsconfig.json
@@ -10,7 +10,7 @@
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
- // "declaration": true, /* Generates corresponding '.d.ts' file. */
+ "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
diff --git a/staging/package.json b/staging/package.json
index 20faf37..dac7344 100644
--- a/staging/package.json
+++ b/staging/package.json
@@ -19,7 +19,8 @@
},
"scripts": {
"build:data-vault": "cd ../data-vault && npm run start:build",
- "build": "npm run build:data-vault && tsc",
+ "build:issuer": "cd ../issuer && npm run back:build",
+ "build": "npm run build:data-vault && npm run build:issuer && tsc",
"start": "npm run build && node build/index.js",
"start:dev": "concurrently \"tsc --watch\" \"nodemon ./build/index.js\"",
"test": "echo \"Error: no test specified\" && exit 1"
diff --git a/staging/src/index.ts b/staging/src/index.ts
index 93619c4..a524800 100644
--- a/staging/src/index.ts
+++ b/staging/src/index.ts
@@ -4,6 +4,7 @@ import Debug from 'debug'
import express from 'express'
import cors from 'cors'
import { setupCentralizedIPFSPinner } from '../../data-vault/build/services/centralizedIPFSPinner'
+import { runIssuer } from '../../issuer/server/build/issuer'
/* env */
dotenv.config()
@@ -14,7 +15,17 @@ const debug = Debug('rif-id:data-vault:scripts')
if (!process.env.DATA_VAULT_PRIVATE_KEY) throw new Error('Setup private key')
if (!process.env.DATA_VAULT_ADDRESS) throw new Error('Setup address')
-const env = {
+if (!process.env.ISSUER_ADMIN_PASS) throw new Error('Setup issuer back office password')
+if (!process.env.ISSUER_SECRET_BOX_KEY) throw new Error('Setup issuer secret box key')
+
+
+const port = process.env.PORT || 3300
+
+/* setup app */
+const app = express()
+app.use(cors())
+
+const dataVaultOptions = {
privateKey: process.env.DATA_VAULT_PRIVATE_KEY,
address: process.env.DATA_VAULT_ADDRESS,
ipfsPort: process.env.DATA_VAULT_IPFS_PORT || '5001',
@@ -22,12 +33,20 @@ const env = {
rpcUrl: process.env.DATA_VAULT_RPC_URL || 'https://did.testnet.rsk.co:4444'
}
-const port = process.env.PORT || 3300
-
-/* setup app */
-const app = express()
-app.use(cors())
+const issuerOptions = {
+ secretBoxKey: process.env.ISSUER_SECRET_BOX_KEY,
+ rpcUrl: process.env.ISSUER_RPC_URL || 'https://did.testnet.rsk.co:4444',
+ debuggerOptions: '*',
+ adminPass: process.env.ISSUER_ADMIN_PASS,
+ apps: [app],
+ backOfficePrefix: '/issuer-back-office',
+ credentialRequestServicePrefix: '/issuer-credential-requests'
+}
-setupCentralizedIPFSPinner(app, env, '/data-vault').then(() => app.listen(port, () => {
- debug(`Data vault started on http://localhost:${port}/data-vault`)
-}))
+setupCentralizedIPFSPinner(app, dataVaultOptions, '/data-vault')
+ .then(() => runIssuer(issuerOptions))
+ .then(() => app.listen(port, () => {
+ debug(`Data vault started on http://localhost:${port}/data-vault`)
+ debug(`Back office service started on http://localhost:${port}'/issuer-back-office'`)
+ debug(`Credential request service started on http://localhost:${port}/issuer-credential-requests`)
+ }))
From 4723d09510afbea0a77f3034cb18ea768d4e46bf Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 22:06:22 -0300
Subject: [PATCH 06/19] Refactor tiny QR
---
staging/src/index.ts | 7 ++++++-
staging/tsconfig.json | 6 +++---
tiny-qr/index.js | 17 +++++++++++++++--
tiny-qr/tinyQr.js | 16 ++++------------
4 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/staging/src/index.ts b/staging/src/index.ts
index a524800..7c44a32 100644
--- a/staging/src/index.ts
+++ b/staging/src/index.ts
@@ -5,6 +5,7 @@ import express from 'express'
import cors from 'cors'
import { setupCentralizedIPFSPinner } from '../../data-vault/build/services/centralizedIPFSPinner'
import { runIssuer } from '../../issuer/server/build/issuer'
+const tinyQr = require('../../tiny-qr/tinyQr')
/* env */
dotenv.config()
@@ -35,18 +36,22 @@ const dataVaultOptions = {
const issuerOptions = {
secretBoxKey: process.env.ISSUER_SECRET_BOX_KEY,
+ adminPass: process.env.ISSUER_ADMIN_PASS,
rpcUrl: process.env.ISSUER_RPC_URL || 'https://did.testnet.rsk.co:4444',
debuggerOptions: '*',
- adminPass: process.env.ISSUER_ADMIN_PASS,
apps: [app],
backOfficePrefix: '/issuer-back-office',
credentialRequestServicePrefix: '/issuer-credential-requests'
}
+const tinyQrOptions = process.env.TINY_QR_URL
+
setupCentralizedIPFSPinner(app, dataVaultOptions, '/data-vault')
+ .then(() => tinyQr(app, tinyQrOptions, '/tiny-qr'))
.then(() => runIssuer(issuerOptions))
.then(() => app.listen(port, () => {
debug(`Data vault started on http://localhost:${port}/data-vault`)
debug(`Back office service started on http://localhost:${port}'/issuer-back-office'`)
debug(`Credential request service started on http://localhost:${port}/issuer-credential-requests`)
+ debug(`Tiny QR started on http://localhost:${port}/tiny-qr`)
}))
diff --git a/staging/tsconfig.json b/staging/tsconfig.json
index 0ba8d0c..2e41a07 100644
--- a/staging/tsconfig.json
+++ b/staging/tsconfig.json
@@ -7,7 +7,7 @@
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
- // "allowJs": true, /* Allow javascript files to be compiled. */
+ "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
@@ -25,8 +25,8 @@
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
- "strict": true, /* Enable all strict type-checking options. */
- // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
+ "strict": false, /* Enable all strict type-checking options. */
+ "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
diff --git a/tiny-qr/index.js b/tiny-qr/index.js
index c5db8e3..2648426 100644
--- a/tiny-qr/index.js
+++ b/tiny-qr/index.js
@@ -1,4 +1,17 @@
-require('dotenv').config()
+const express = require('express')
+const cors = require('cors')
+const Debug = require('debug')
const tinyQr = require('./tinyQr')
-tinyQr(process.env.TINY_QR_PORT || 5103, process.env.TINY_QR_URL || 'http://localhost:5103')
+require('dotenv').config()
+
+Debug.enable('*')
+const debug = Debug('rif-id:services:tiny-qr:script')
+
+const app = express()
+app.use(cors())
+
+tinyQr(app, process.env.TINY_QR_URL || 'http://localhost:5103', '')
+
+const port = process.env.TINY_QR_PORT || 5103
+app.listen(port, () => debug(`Tiny QR service started on port ${port}`))
diff --git a/tiny-qr/tinyQr.js b/tiny-qr/tinyQr.js
index 540a3df..73765fc 100644
--- a/tiny-qr/tinyQr.js
+++ b/tiny-qr/tinyQr.js
@@ -1,21 +1,15 @@
-const express = require('express')
-const cors = require('cors')
const bodyParser = require('body-parser')
const Debug = require('debug')
const crypto = require('crypto')
-
const debug = Debug('rif-id:services:tiny-qr')
-Debug.enable('*')
-function tinyQr(port, serviceUrl) {
- const app = express()
- app.use(cors())
+function tinyQr(app, serviceUrl, suffix = '') {
app.use(bodyParser.json())
let presentations = {};
- app.post('/presentation', async function(req, res) {
+ app.post(suffix + '/presentation', async function(req, res) {
const { jwt } = req.body
debug(`Incoming presentation JWT ${jwt}`)
@@ -28,14 +22,14 @@ function tinyQr(port, serviceUrl) {
presentations[id] = presentation;
const response = {
- url: `${serviceUrl}/jwt/${id}`,
+ url: `${serviceUrl}${suffix}/jwt/${id}`,
pwd
}
res.json(response).end()
})
- app.post('/jwt/:id', function(req, res) {
+ app.post(suffix + '/jwt/:id', function(req, res) {
const { id } = req.params
const { pwd } = req.body
@@ -49,8 +43,6 @@ function tinyQr(port, serviceUrl) {
res.status(404).end()
}
})
-
- app.listen(port, () => debug(`Tiny QR service started on port ${port}`))
}
module.exports = tinyQr;
From f7a8892c8fbd4ce9fbe8f51721b9c618df7ed7f3 Mon Sep 17 00:00:00 2001
From: Ilan Olkies
Date: Wed, 12 Aug 2020 22:15:18 -0300
Subject: [PATCH 07/19] Document
---
staging/README.md | 34 ++++++++++++++++++++++++++++++++++
staging/img/result.png | Bin 0 -> 884469 bytes
staging/src/index.ts | 2 +-
3 files changed, 35 insertions(+), 1 deletion(-)
create mode 100644 staging/img/result.png
diff --git a/staging/README.md b/staging/README.md
index ffabf51..28ec15c 100644
--- a/staging/README.md
+++ b/staging/README.md
@@ -6,4 +6,38 @@
Put all RIF services on stage
+The script in `src/index.ts` starts all the services in one single Express.js app. It routes the different services using url prefixes.
+- **Data vault** starts on http://localhost:3300/data-vault
+- **Back office service** started on http://localhost:3300'/issuer-back-office'
+- **Credential request service** starts on http://localhost:3300/issuer-credential-requests
+- **Tiny QR** starts on http://localhost:3300/tiny-qr
+
+## Setup
+
+1. First you need to install all services dependencies, go to each service folder and run
+
+ ```
+ npm install
+ ```
+
+2. Configure the services, a minimal config contains:
+
+ ```
+ DATA_VAULT_PRIVATE_KEY=
+ DATA_VAULT_ADDRESS=
+ ISSUER_ADMIN_PASS=
+ ISSUER_SECRET_BOX_KEY=
+ ```
+
+3. Run the services
+
+ ```
+ npm run start
+ ```
+
+Starting the services will first compile all the services, then compile the staging script, and finally run it with Node.js
+
+The result:
+
+![result](./img/result.png)
diff --git a/staging/img/result.png b/staging/img/result.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4a1f74136120421df2f0bab101d7e3ad99d4f5b
GIT binary patch
literal 884469
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