diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index c4e17a1b9e023d17fe97dd6aa309e6ab0cfe09fe..0000000000000000000000000000000000000000 --- a/Dockerfile +++ /dev/null @@ -1,52 +0,0 @@ -# Avoid the use of floating tags like: latest, boron, argon and carbon -ARG VERSION=10.16.3 -FROM node:$VERSION - -LABEL autor="C3SL - Centro de Computação CientÃfica e Software Livre" - - -# Node was not designed to run as PID 1 (process in docker run with PID 1). -# Its recommended to use the flag --init or use tine to start node process -# in docker - -# Add Tini -ENV TINI_VERSION="v0.16.1" WORKSPACE="/home/node/app/" -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini - -# Install app dependencies -# A wildcard is used to ensure both package.json AND package-lock.json are copied -# where available (npm@5+) - -COPY package*.json $WORKSPACE -COPY yarn.lock $WORKSPACE -RUN \ - chmod +x /tini &&\ - chown -R node:node $WORKSPACE - -USER node -WORKDIR $WORKSPACE - -RUN yarn install --frozen-lockfile --silent --non-interactive - -# Bundle app source -# COPY copy files as root so chown must be used -USER root -COPY . . -RUN find . -user root | xargs chown node:node -USER node - -VOLUME ["/home/node/app/config"] - -EXPOSE 3000 - -HEALTHCHECK CMD curl -f http://localhost:3000/v1/metrics || exit 1 - -# Instead of using npm start to start the container, directly put the command -# that npm start executes. -# First off this reduces the number of processes running inside of your container -# Secondly it causes exit signals such as SIGTERM and SIGINT to be received by -# the Node.js process instead of npm swallowing them. - - -ENTRYPOINT ["/tini", "--"] -CMD ["node", "index" ] diff --git a/config/ci_test.yaml.example b/config/ci_test.yaml.example index 4736b4d296b6b675991c16a4bbf85de2edc9af71..2b810d85afcaae12cc5929427dc6a94410d06a0f 100644 --- a/config/ci_test.yaml.example +++ b/config/ci_test.yaml.example @@ -1,87 +1,231 @@ # gitignore ignores files.yaml in this folder # however a config file for tests in CI is required # so this example file in fact is the CI test file -tags: - links: - - config/market_tags.yaml.example - obj: - - - name: "noDescription" - description: "Related with seller" -views: - links: - - config/market_views.yaml.example - obj: - - - alias: "view:Seller" - data: "test/postgres/fixtures/seller.json" +connection: + database: 'blendb_fixture' + user: 'runner' + password: '' + host: 'postgres' + port: 5432 + max: 10 + idleTimeoutMillis: 30000 +struct: + create: true + insert: true +schema: + views: + - + alias: "View 0" + data: "test/postgres/fixtures/view0.json" + origin: true + dimensions: + - "dim:0" + - "dim:7" + metrics: + - "met:0" + - "met:1" + - "met:2" + - "met:10" + - + alias: "View 1" + data: "test/postgres/fixtures/view1.json" + origin: true + dimensions: + - "dim:1" + - "dim:8" + metrics: + - "met:3" + - "met:4" + - + alias: "View 2" + data: "test/postgres/fixtures/view2.json" origin: true - aliasAsName: true dimensions: - - "dim:seller:name" - - "dim:seller:sex" - - "dim:seller:cpf" - - "dim:seller:id" - - "dim:seller:status" + - "dim:2" metrics: - - "met:seller:avg:age" - - "met:seller:max:age" - - "met:seller:min:age" - - "met:seller:count:age" -metrics: - links: - - config/market_metrics.yaml.example - obj: - - - name: "met:seller:avg:age" - dataType: "float" + - "met:5" + - "met:6" + - "met:11" + - + alias: "View 3" + data: "test/postgres/fixtures/view3.json" + origin: true + dimensions: + - "dim:2" + - "dim:3" + - "dim:4" + - + alias: "View 4" + data: "test/postgres/fixtures/view4.json" + origin: true + dimensions: + - "dim:2" + - "dim:7" + - "dim:8" + - + alias: "View 5" + data: "test/postgres/fixtures/view5.json" + origin: true + dimensions: + - "dim:3" + metrics: + - "met:7" + - + alias: "View 6" + data: "test/postgres/fixtures/view6.json" + origin: true + dimensions: + - "dim:4" + metrics: + - "met:8" + - + alias: "View 7" + data: "test/postgres/fixtures/view7.json" + origin: true + dimensions: + - "dim:4" + - "dim:5" + - "dim:6" + - + alias: "View 8" + data: "test/postgres/fixtures/view8.json" + origin: true + dimensions: + - "dim:5" + - "dim:6" + metrics: + - "met:9" + - + alias: "view 9" + data: "test/postgres/fixtures/view9.json" + origin: false + dimensions: + - "dim:2" + metrics: + - "met:5" + - "met:6" + - "met:7" + clauses: + - "dim:2!=1" + metrics: + - + name: "met:0" + dataType: "integer" + aggregation: "sum" + description: "No meaning, just used for test" + - + name: "met:1" + dataType: "integer" aggregation: "avg" - description: "The seller average age" - tags: - - "seller" - - "age" -dimensions: - links: - - config/market_dimensions.yaml.example - obj: - - - name: "dim:seller:name" + description: "No meaning, just used for test" + - + name: "met:2" + dataType: "integer" + aggregation: "avg" + description: "No meaning, just used for test" + - + name: "met:3" + dataType: "integer" + aggregation: "sum" + description: "No meaning, just used for test" + - + name: "met:4" + dataType: "integer" + aggregation: "sum" + description: "No meaning, just used for test" + - + name: "met:5" + dataType: "integer" + aggregation: "avg" + description: "No meaning, just used for test" + - + name: "met:6" + dataType: "integer" + aggregation: "count" + description: "No meaning, just used for test" + - + name: "met:7" + dataType: "integer" + aggregation: "count" + description: "No meaning, just used for test" + - + name: "met:8" + dataType: "integer" + aggregation: "sum" + description: "No meaning, just used for test" + - + name: "met:9" + dataType: "integer" + aggregation: "count" + description: "No meaning, just used for test" + - + name: "met:10" + dataType: "integer" + aggregation: "max" + description: "No meaning, just used for test" + - + name: "met:11" + dataType: "integer" + aggregation: "min" + description: "No meaning, just used for test" + dimensions: + - + name: "dim:0" + dataType: "date" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:1" + dataType: "date" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:2" + dataType: "integer" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:3" + dataType: "string" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:4" dataType: "string" - description: "Name of the seller from market" - tags: - - "seller" -enumTypes: - links: - - config/market_enum.yaml.example - obj: - - [] -sources: - links: - - config/market_sources.yaml.example - - config/source_test_only.yaml.example - obj: - - - name: "Seller" - description: "Market worker" - fields: - - - name: "name" - description: "Seller name" - dataType: "string" - - - name: "age" - description: "Seller age" - dataType: "integer" - - - name: "sex" - description: "Seller sex" - enumType: "enumsex" - dataType: "enumtype" - - - name: "CPF" - description: "Seller CPF" - dataType: "string" - - - name: "id" - description: "Seller id" - dataType: "integer" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:5" + dataType: "boolean" + description: "A dimension of Blendb. Has 2 possible values." + - + name: "dim:6" + dataType: "integer" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:7" + dataType: "integer" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:8" + dataType: "integer" + description: "A dimension of Blendb. Has 5 possible values." + - + name: "dim:9" + dataType: "integer" + parent: "dim:0" + relation: "day" + description: "A dimension of Blendb. Has 30 possible values." + - + name: "dim:10" + dataType: "integer" + parent: "dim:0" + relation: "month" + description: "A dimension of Blendb. Has 12 possible values." + - + name: "dim:11" + dataType: "integer" + parent: "dim:0" + relation: "year" + description: "A dimension of Blendb. Has 1 possible value." + - + name: "dim:12" + dataType: "integer" + parent: "dim:0" + relation: "dayofweek" + description: "A dimension of Blendb. Has 7 possible values." diff --git a/config/config.env.example b/config/config.env.example deleted file mode 100644 index fcec8a5fe171bee6f2fb9a65f0628ea7cf896a53..0000000000000000000000000000000000000000 --- a/config/config.env.example +++ /dev/null @@ -1,11 +0,0 @@ -BLENDB_SCHEMA_FILE=config/config.yaml.example -PORT=3000 -BLENDB_LOG_FILE=/var/log/blendb.log -BLENDB_LOG_LEVEL=debug -BLENDB_N_DB=1 -BLENDB_DB0_USER=blendb -BLENDB_DB0_NAME=blendb-test -BLENDB_DB0_PASSWORD=secret -BLENDB_DB0_HOST=localhost -BLENDB_DB0_PORT=5432 -BLENDB_DB0_ADAPTER=postgres diff --git a/config/config.yaml.example b/config/config.yaml.example index 4736b4d296b6b675991c16a4bbf85de2edc9af71..f97ea97db5adb4daf21d7011aa78bbaa50e61803 100644 --- a/config/config.yaml.example +++ b/config/config.yaml.example @@ -1,87 +1,15 @@ -# gitignore ignores files.yaml in this folder -# however a config file for tests in CI is required -# so this example file in fact is the CI test file -tags: - links: - - config/market_tags.yaml.example - obj: - - - name: "noDescription" - description: "Related with seller" -views: - links: - - config/market_views.yaml.example - obj: - - - alias: "view:Seller" - data: "test/postgres/fixtures/seller.json" - origin: true - aliasAsName: true - dimensions: - - "dim:seller:name" - - "dim:seller:sex" - - "dim:seller:cpf" - - "dim:seller:id" - - "dim:seller:status" - metrics: - - "met:seller:avg:age" - - "met:seller:max:age" - - "met:seller:min:age" - - "met:seller:count:age" -metrics: - links: - - config/market_metrics.yaml.example - obj: - - - name: "met:seller:avg:age" - dataType: "float" - aggregation: "avg" - description: "The seller average age" - tags: - - "seller" - - "age" -dimensions: - links: - - config/market_dimensions.yaml.example - obj: - - - name: "dim:seller:name" - dataType: "string" - description: "Name of the seller from market" - tags: - - "seller" -enumTypes: - links: - - config/market_enum.yaml.example - obj: - - [] -sources: - links: - - config/market_sources.yaml.example - - config/source_test_only.yaml.example - obj: - - - name: "Seller" - description: "Market worker" - fields: - - - name: "name" - description: "Seller name" - dataType: "string" - - - name: "age" - description: "Seller age" - dataType: "integer" - - - name: "sex" - description: "Seller sex" - enumType: "enumsex" - dataType: "enumtype" - - - name: "CPF" - description: "Seller CPF" - dataType: "string" - - - name: "id" - description: "Seller id" - dataType: "integer" +connection: + user: 'blendb' + database: 'blendb-test' + password: 'secret' + host: 'localhost' + port: 5432 + max: 10 + idleTimeoutMillis: 30000 +struct: + create: false + insert: false +schema: + views: + metrics: + dimensions: diff --git a/config/market_dimensions.yaml.example b/config/market_dimensions.yaml.example deleted file mode 100644 index 3e85343d4e613235bbfd9fc5e7d853b727e54b6d..0000000000000000000000000000000000000000 --- a/config/market_dimensions.yaml.example +++ /dev/null @@ -1,81 +0,0 @@ -- - name: "dim:seller:sex" - dataType: "enumtype" - enumType: "enumsex" - description: "Sexual orientation of the seller from market" -- - name: "dim:seller:cpf" - dataType: "string" - description: "CPF of the seller from market" -- - name: "dim:seller:status" - dataType: "enumtype" - enumType: "workingStatus" - description: "The status of the seller from market" -- - name: "dim:product:name" - dataType: "string" - description: "Name of the product from market" -- - name: "dim:product:validity" - dataType: "date" - description: "Validity of the product from market" -- - name: "dim:client:name" - dataType: "string" - description: "Name of the client from market" -- - name: "dim:client:cpf" - dataType: "string" - description: "CPF of the client from market" -- - name: "dim:sell:registered" - dataType: "boolean" - description: "Check if the client is registered" -- - name: "dim:seller:id" - dataType: "integer" - description: "id of the seller from market" -- - name: "dim:client:id" - dataType: "integer" - description: "id of the client from market" -- - name: "dim:sell:datein" - dataType: "date" - description: "Date of the sell was realized" -- - name: "dim:buyout:datein" - dataType: "date" - description: "Date of the buyout was realized" -- - name: "dim:product:id" - dataType: "integer" - description: "id of the product from market" -- - name: "dim:provider:name" - dataType: "string" - description: "Name of the provider from market" -- - name: "dim:provider:id" - dataType: "string" - description: "id of the provider from market" -- - name: "dim:buyout:day" - dataType: "integer" - parent: "dim:buyout:datein" - relation: "day" - description: "Date of the buyout was realized" -- - name: "dim:buyout:month" - dataType: "integer" - parent: "dim:buyout:datein" - relation: "month" - description: "Date of the buyout was realized" -- - name: "dim:buyout:year" - dataType: "integer" - parent: "dim:buyout:datein" - relation: year - description: "Date of the buyout was realized" - diff --git a/config/market_enum.yaml.example b/config/market_enum.yaml.example deleted file mode 100644 index 496f1b9447f1f1ab3ad03033196924133b3674fd..0000000000000000000000000000000000000000 --- a/config/market_enum.yaml.example +++ /dev/null @@ -1,16 +0,0 @@ -- - name: "enumsex" - values: - - "male" - - "female" - - "nonbinary" - - "undecided" -- - name: "workingStatus" - values: - - "active" - - "inactive" - - "vacation" - - "sick leave" - - "maternity leave" - - "stand by" diff --git a/config/market_main.yaml.example b/config/market_main.yaml.example deleted file mode 100644 index 32db12921d05daee820913e0587e4093999ed2b4..0000000000000000000000000000000000000000 --- a/config/market_main.yaml.example +++ /dev/null @@ -1,70 +0,0 @@ -views: - links: - - config/market_views.yaml.example - obj: - - - alias: "view:Seller" - data: "test/postgres/fixtures/seller.json" - origin: true - dimensions: - - "dim:seller:name" - - "dim:seller:sex" - - "dim:seller:cpf" - - "dim:seller:id" - - "dim:seller:status" - metrics: - - "met:seller:avg:age" - - "met:seller:max:age" - - "met:seller:min:age" - - "met:seller:count:age" -metrics: - links: - - config/market_metrics.yaml.example - obj: - - - name: "met:seller:avg:age" - dataType: "float" - aggregation: "avg" - description: "The seller average age" -dimensions: - links: - - config/market_dimensions.yaml.example - obj: - - - name: "dim:seller:name" - dataType: "string" - description: "Name of the seller from market" -enumTypes: - links: - - config/market_enum.yaml.example - obj: - - [] -sources: - links: - - config/market_sources.yaml.example - obj: - - - name: "Seller" - description: "Market worker" - fields: - - - name: "name" - description: "Seller name" - dataType: "string" - - - name: "age" - description: "Seller age" - dataType: "integer" - - - name: "sex" - description: "Seller sex" - enumType: "enumsex" - dataType: "enumtype" - - - name: "CPF" - description: "Seller CPF" - dataType: "string" - - - name: "id" - description: "Seller id" - dataType: "integer" diff --git a/config/market_metrics.yaml.example b/config/market_metrics.yaml.example deleted file mode 100644 index 320defff801b451ed3f20e1e60afaecf4ab0733b..0000000000000000000000000000000000000000 --- a/config/market_metrics.yaml.example +++ /dev/null @@ -1,106 +0,0 @@ -- - name: "met:seller:max:age" - dataType: "integer" - aggregation: "max" - description: "The seller highest age" - tags: - - "seller" - - "age" - - "max" -- - name: "met:seller:min:age" - dataType: "integer" - aggregation: "min" - description: "The seller lowest age" - tags: - - "seller" - - "age" -- - name: "met:seller:count:age" - dataType: "integer" - aggregation: "count" - description: "The number of seller's" - tags: - - "seller" - - "age" -- - name: "met:product:avg:pricein" - dataType: "float" - aggregation: "avg" - description: "The average product pricein" - tags: - - "product" -- - name: "met:product:max:pricein" - dataType: "float" - aggregation: "max" - description: "The highest product pricein" - tags: - - "product" - - "max" -- - name: "met:product:min:pricein" - dataType: "float" - aggregation: "min" - description: "The lowest product pricein" - tags: - - "product" -- - name: "met:product:avg:priceout" - dataType: "float" - aggregation: "avg" - description: "The average product priceout" - tags: - - "product" -- - name: "met:product:max:priceout" - dataType: "float" - aggregation: "max" - description: "The highest product priceout" - tags: - - "product" - - "max" -- - name: "met:product:min:priceout" - dataType: "float" - aggregation: "min" - description: "The lowest product priceout" - tags: - - "product" -- - name: "met:sell:sum:quantity" - dataType: "integer" - aggregation: "sum" - description: "The sum of sales quantity" -- - name: "met:sell:avg:quantity" - dataType: "float" - aggregation: "avg" - description: "The average of sales quantity" -- - name: "met:sell:count:quantity" - dataType: "integer" - aggregation: "count" - description: "The total number of sales" -- - name: "met:buyout:avg:quantity" - dataType: "float" - aggregation: "avg" - description: "The average of quantity bought" - tags: - - "buyout" -- - name: "met:buyout:max:quantity" - dataType: "integer" - aggregation: "max" - description: "The highest quantity bought" - tags: - - "buyout" - - "max" -- - name: "met:buyout:min:quantity" - dataType: "integer" - aggregation: "min" - description: "The lowest quantity bought" - tags: - - "buyout" diff --git a/config/market_sources.yaml.example b/config/market_sources.yaml.example deleted file mode 100644 index 96583bf7fb29c6c9993babee755692cc64465626..0000000000000000000000000000000000000000 --- a/config/market_sources.yaml.example +++ /dev/null @@ -1,112 +0,0 @@ -- - name: "Product" - description: "Market product" - fields: - - - name: "name" - description: "Product name" - dataType: "string" - - - name: "pricein" - description: "Product purchase price" - dataType: "float" - - - name: "priceout" - description: "Product price" - dataType: "float" - - - name: "validity" - description: "Product validity" - dataType: "date" - - - name: "id" - description: "Product id" - dataType: "integer" -- - name: "Client" - description: "Market client" - fields: - - - name: "name" - description: "Client name" - dataType: "string" - - - name: "CPF" - description: "Client CPF" - dataType: "string" - - - name: "id" - description: "Client id" - dataType: "integer" -- - name: "Sell" - description: "Market sale" - fields: - - - name: "Registered" - description: "Check if client is registered" - dataType: "boolean" - - - name: "Product.id" - description: "id from product" - dataType: "integer" - - - name: "Client.id" - description: "id from seller" - dataType: "integer" - - - name: "Seller.id" - description: "id from seller" - dataType: "integer" - - - name: "Quantity" - description: "How many is being bought" - dataType: "integer" - - - name: "Datein" - description: "Date of buy from Provider" - dataType: "date" -- - name: "Buyout" - description: "Market buyout" - fields: - - - name: "datein" - description: "date of entry" - dataType: "date" - - - name: "quantity" - description: "how many products has been bought" - dataType: "integer" - - - name: "Provider.id" - description: "Provider id" - dataType: "integer" - - - name: "Product.id" - description: "Product id" - dataType: "integer" -- - name: "Provider" - description: "Market provider" - fields: - - - name: "name" - description: "Provider product name" - dataType: "string" - - - name: "id" - description: "Provider id" - dataType: "integer" -- - name: "Distribute" - description: "Relation between Provider and Product" - fields: - - - name: "Provider.id" - description: "Provider id" - dataType: "integer" - - - name: "Product.id" - description: "Product id" - dataType: "integer" diff --git a/config/market_tags.yaml.example b/config/market_tags.yaml.example deleted file mode 100644 index 48fc078e6f943eae315c00a2990de7ad745fe65e..0000000000000000000000000000000000000000 --- a/config/market_tags.yaml.example +++ /dev/null @@ -1,21 +0,0 @@ -- - name: "seller" - description: "Related with seller" -- - name: "age" - description: "Related with age" -- - name: "product" - description: "Related with product" -- - name: "client" - description: "Related with client" -- - name: "buyout" - description: "Related with buyout" -- - name: "provider" - description: "Related with provider" -- - name: "max" - description: "Aggregation Max" diff --git a/config/market_views.yaml.example b/config/market_views.yaml.example deleted file mode 100644 index c5b681d117a51addace4ddb71a9c0da06224e072..0000000000000000000000000000000000000000 --- a/config/market_views.yaml.example +++ /dev/null @@ -1,90 +0,0 @@ -- - alias: "view:Product" - data: "test/postgres/fixtures/product.json" - origin: true - aliasAsName: true - dimensions: - - "dim:product:name" - - "dim:product:validity" - - "dim:product:id" - metrics: - - "met:product:avg:pricein" - - "met:product:max:pricein" - - "met:product:min:pricein" - - "met:product:avg:priceout" - - "met:product:max:priceout" - - "met:product:min:priceout" -- - alias: "view:Client" - data: "test/postgres/fixtures/client.json" - origin: true - aliasAsName: true - dimensions: - - "dim:client:name" - - "dim:client:cpf" - - "dim:client:id" -- - alias: "view:Sell" - data: "test/postgres/fixtures/sell.json" - origin: true - aliasAsName: true - dimensions: - - "dim:sell:registered" - - "dim:product:id" - - "dim:seller:id" - - "dim:client:id" - - "dim:sell:datein" - metrics: - - "met:sell:sum:quantity" - - "met:sell:avg:quantity" - - "met:sell:count:quantity" -- - alias: "view:Buyout" - data: "test/postgres/fixtures/buyout.json" - origin: true - aliasAsName: true - dimensions: - - "dim:buyout:datein" - - "dim:provider:id" - - "dim:product:id" - metrics: - - "met:buyout:avg:quantity" - - "met:buyout:max:quantity" - - "met:buyout:min:quantity" -- - alias: "view:Provider" - data: "test/postgres/fixtures/provider.json" - origin: true - aliasAsName: true - dimensions: - - "dim:provider:name" - - "dim:provider:id" -- - alias: "view:Distribute" - data: "test/postgres/fixtures/distribute.json" - origin: true - aliasAsName: true - dimensions: - - "dim:provider:id" - - "dim:product:id" -- - alias: "view:ActiveSeller" - data: "test/postgres/fixtures/activeseller.json" - origin: true - aliasAsName: true - dimensions: - - "dim:seller:name" - - "dim:seller:status" - metrics: - - "met:seller:max:age" - clauses: - - "dim:seller:status==active" -- - alias: "view:SellerStatus" - data: "test/postgres/fixtures/sellerstatus.json" - origin: false - aliasAsName: true - metrics: - - "met:seller:count:age" - dimensions: - - "dim:seller:status" diff --git a/config/source_test_only.yaml.example b/config/source_test_only.yaml.example deleted file mode 100644 index 02a89e58853841fe3dad433609578f34e5ea33da..0000000000000000000000000000000000000000 --- a/config/source_test_only.yaml.example +++ /dev/null @@ -1,8 +0,0 @@ -- - name: "test" - description: - fields: - - - name: "noDescriptionString" - description: - dataType: "string" diff --git a/config/test.env.example b/config/test.env.example deleted file mode 100644 index 6c2daa608b56c7b956b68811543f5c9e0dddaebd..0000000000000000000000000000000000000000 --- a/config/test.env.example +++ /dev/null @@ -1,17 +0,0 @@ -PORT=3000 -BLENDB_N_DB=2 -BLENDB_LOG_FILE=/var/log/blendb.log -BLENDB_LOG_LEVEL=debug -BLENDB_DB0_USER=runner -BLENDB_DB0_NAME=blendb_fixture -BLENDB_DB0_PASSWORD= -BLENDB_DB0_HOST=postgres -BLENDB_DB0_PORT=5432 -BLENDB_DB0_ADAPTER=postgres -BLENDB_DB1_USER=monetdb -BLENDB_DB1_NAME=blendb_fixture -BLENDB_DB1_PASSWORD=monetdb -BLENDB_DB1_HOST=monet -BLENDB_DB1_PORT=50000 -BLENDB_DB1_ADAPTER=monet -BLENDB_SCHEMA_FILE=config/ci_test.yaml.example diff --git a/scripts/schema.ts b/database/createSchema.ts similarity index 58% rename from scripts/schema.ts rename to database/createSchema.ts index baef54d368f50b9234dc3384ef78957d3c073031..86b1507cc4864e35870f6b9d3a6b7dcbbae8ac04 100755 --- a/scripts/schema.ts +++ b/database/createSchema.ts @@ -23,7 +23,6 @@ import { Engine } from "../src/core/engine"; import { PostgresAdapter } from "../src/adapter/postgres"; import { ConfigParser } from "../src/util/configParser"; -import { QueryOpts, Query } from "../src/common/query"; import * as path from "path"; import * as fs from "fs"; @@ -38,12 +37,14 @@ const configFile = process.argv[2]; const schemaFile = process.argv[3]; const config = ConfigParser.parse(configFile); const referencePath = path.dirname(configFile); - -const engine = new Engine(config); -const adapter = new PostgresAdapter(config.connections[0]); +const engine = new Engine(); +const adapter = new PostgresAdapter(config.connection); let schema = ""; +config.metrics.forEach ((met) => engine.addMetric(met)); +config.dimensions.forEach ((dim) => engine.addDimension(dim)); + for (let i = 0; i < config.buildViews.length; ++i) { const view = config.buildViews[i].view; const filePath = config.buildViews[i].file; @@ -51,20 +52,8 @@ for (let i = 0; i < config.buildViews.length; ++i) { if (view.origin) { // Cria uma tabela let output = "-- View: " + alias + "\n"; - if (process.env.BLENDB_ADAPTER === "postgres") { - output += "DROP VIEW IF EXISTS " + view.name + " CASCADE;\n"; - output += "CREATE OR REPLACE VIEW " + view.name + " AS\n"; - } - - else if (process.env.BLENDB_ADAPTER === "monet") { - output += "DROP VIEW " + view.name + " CASCADE;\n"; - output += "CREATE VIEW " + view.name + " AS\n"; - } - - else { - console.log("The adapter value:", process.env.BLENDB_ADAPTER, "is invalid. Abort"); - process.exit(1); - } + output += "DROP VIEW IF EXISTS view_" + view.id + " CASCADE;\n"; + output += "CREATE OR REPLACE VIEW view_" + view.id + " AS\n"; output += fs.readFileSync(referencePath + "/" + filePath, {encoding: "utf-8" }); schema += output + "\n"; engine.addView(view); @@ -76,30 +65,17 @@ for (let i = 0; i < config.buildViews.length; ++i) { const view = config.buildViews[i].view; const alias = config.buildViews[i].alias; if (!view.origin) { - const qOpt: QueryOpts = { metrics: view.metrics,dimensions: view.dimensions, - clauses: view.clauses }; - const materializedView = engine.query(new Query(qOpt)); + const materializedView = engine.query({ + metrics: view.metrics, + dimensions: view.dimensions, + clauses: view.clauses + }); const table = adapter.getQueryFromView(materializedView); - let query = "-- View: " + alias + "\n"; - if (process.env.BLENDB_ADAPTER === "postgres") { - query += "DROP MATERIALIZED VIEW IF EXISTS view_" + view.id + " CASCADE;\n" + + const query = "-- View: " + alias + "\n" + + "DROP MATERIALIZED VIEW IF EXISTS view_" + view.id + " CASCADE;\n" + "CREATE MATERIALIZED VIEW view_" + materializedView.id + " AS " + table + "\n\n"; - } - - else if (process.env.BLENDB_ADAPTER === "monet") { - console.log("MonetDb does not support Materializaed views. Abort"); - console.log("All views in config.yaml must be origin form MonetDB"); - console.log("This is a known issue."); - console.log("In the future this script will create a table and copy the data."); - process.exit(1); - } - - else { - console.log("The adapter value:", process.env.BLENDB_ADAPTER, "is invalid. Abort"); - process.exit(1); - } schema += query; engine.addView(materializedView); @@ -112,8 +88,4 @@ fs.writeFile(schemaFile, schema, (error) => { process.exitCode = 1; return; } - - else { - console.log("File: " + schemaFile + " created"); - } }); diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index cee9167ead44039aceffe6c4ac0c4d5879cd3cde..0000000000000000000000000000000000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: '3.3' -services: - blendb-postgres: - image: postgres:10 - container_name: postgres - environment: - POSTGRES_PASSWORD: passwd - PGDATA: /var/lib/postgresql/docker/pgdata - ports: - - 5432:5432 - restart: unless-stopped - security_opt: - - no-new-privileges - blendb: - # image: marula.c3sl.ufpr.br:5000/c3sl/blendb:latest - image: blendb - build: . - container_name: blendb - environment: - BLENDB_SCHEMA_FILE: config/config.yaml.example - PORT: 3000 - BLENDB_N_DB: 1 - BLENDB_DB0_USER: postgres - BLENDB_DB0_NAME: postgres - BLENDB_DB0_PASSWORD: passwd - BLENDB_DB0_HOST: postgres - BLENDB_DB0_PORT: 5432 - BLENDB_DB0_ADAPTER: postgres - ports: - - 3000:3000 - command: ["yarn","test-mode"] - restart: unless-stopped - read_only: 'true' - security_opt: - - no-new-privileges - volumes: - - - type: tmpfs - target: /tmp diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000000000000000000000000000000000000..7f04f27430d875fa6b8f186026a678d740b975f5 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,5 @@ +{ + "watch": ["src", "index.js"], + "ignore": ["*.spec.ts"], + "ext": "ts" +} diff --git a/npm-debug.log.3267702380 b/npm-debug.log.3267702380 new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..0cf1b49997bb098bb6ffb8e82e6e320a3fd03909 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5101 @@ +{ + "name": "blendb", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "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" + } + } + } + }, + "@types/async": { + "version": "3.2.15", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.15.tgz", + "integrity": "sha512-PAmPfzvFA31mRoqZyTVsgJMsvbynR429UTTxhmfsUCrWGh3/fxOrzqBtaTPJsn4UtzTv4Vb0+/O7CARWb69N4g==" + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/chai": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", + "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==" + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/js-yaml": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.7.tgz", + "integrity": "sha512-S6+8JAYTE1qdsc9HMVsfY7+SgSuUU/Tp6TYTmITW0PZxiyIMvol3Gy//y69Wkhs0ti4py5qgR3uZH6uz/DNzJQ==" + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@types/node": { + "version": "8.0.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.34.tgz", + "integrity": "sha1-VfgB+i3bKkDdbfwV7P4d3pwSn+k=" + }, + "@types/pg": { + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.5.tgz", + "integrity": "sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==", + "requires": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/superagent": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", + "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, + "a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "~2.1.16", + "negotiator": "0.6.1" + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "amdefine": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.0.8.tgz", + "integrity": "sha512-mDPHAbiIk4wSDjZFz0YFuwquVPJMj1vm9n6QONCN2bL0WOtNiTRHldplTWlyhJrDlpqe7lAc7MJfSyZJ4sqYhg==", + "dev": true + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "argh": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/argh/-/argh-0.1.4.tgz", + "integrity": "sha512-sQN85FUGbEUBLyQiSJp4v8yAHTST2ao1WVXb/L8jkVqQTsypZuJQD0gMVeOLoSZBz21p22izF6HsBQP16QKQtg==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array.prototype.reduce": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz", + "integrity": "sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "dev": true + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha512-eRYY0vPS2a9zt5w5Z0aCeWbrXTEyvk7u/Xf71EzNObrjSCPgMm1Nku/D/u2tiqHBX5j40wWhj54YJLtgn8g55A==", + "dev": true, + "requires": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + } + }, + "change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "dev": true, + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.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": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha512-/pyV40IrsdulWv+wFPmERh9k/mjsPZ64yUMDmWrtj/k1nmgrzzIENWKdaVKyBbvFdQWqkcaRxr+polCo3VMe7A==", + "dev": true + }, + "colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dev": true, + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "optional": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compose-middleware": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/compose-middleware/-/compose-middleware-2.2.0.tgz", + "integrity": "sha1-boMLHFwWjTvx/sYuOpZMLdNhzsM=", + "requires": { + "array-flatten": "^2.1.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=" + } + } + }, + "compressible": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz", + "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=", + "requires": { + "mime-db": ">= 1.29.0 < 2" + } + }, + "compression": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", + "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", + "requires": { + "accepts": "~1.3.4", + "bytes": "3.0.0", + "compressible": "~2.0.11", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.1", + "vary": "~1.1.2" + } + }, + "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 + }, + "condense-newlines": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz", + "integrity": "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-whitespace": "^0.3.0", + "kind-of": "^3.0.2" + } + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-session": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-1.3.2.tgz", + "integrity": "sha1-Rp26djCMAQtSnpp8+dh7ZJvgGQs=", + "requires": { + "cookies": "0.7.1", + "debug": "2.6.9", + "on-headers": "~1.0.1" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", + "dev": true + }, + "cookies": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", + "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=", + "requires": { + "depd": "~1.1.1", + "keygrip": "~1.0.2" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha1-6sEdpRWS3Ya58G9uesKTs9+HXSk=", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "datatype-expansion": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/datatype-expansion/-/datatype-expansion-0.4.1.tgz", + "integrity": "sha512-KI80twJSPaoNJn6AsQStuL+4ipTKT4AtW+bAKEObQ5ZMqQM6Atzquh9Nu+hj488PQfKKAzuVodOrp7C7P+oItQ==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "date-and-time": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-0.3.0.tgz", + "integrity": "sha1-V2pvpgBhEmSk0F5Bpq6E1qUVKiQ=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha512-6sEotTRGBFiNcqVoeHwnfopbSpi5NbH1VWJmYCVkmxMmaVTT0bUTrNaGyBwhgP4MZL012W/mkzIn3Da+iDYweg==", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha512-5rqszGVwYgBoDkIm2oUtvkfZMQ0vk29iDMU0W2qCa3rG0vPDNczCMT4hV/bLBgLg8k8ri6+u3Zbt+S/14eMzlA==", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "dev": true, + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.2.tgz", + "integrity": "sha1-xzdwGfxOVQeYkosrmv62ar+h8vk=" + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha1-ThUWvmiDi8kKSZlPCzmm5ZYL780=", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emits": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emits/-/emits-3.0.0.tgz", + "integrity": "sha512-WJSCMaN/qjIkzWy5Ayu0MDENFltcu4zTPPnWqdFPOVBtsENVTN+A3d76G61yuiVALsMK+76MejdPrwmccv/wag==", + "dev": true + }, + "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 + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha512-nnzgVSpB35qKrUN8358SjO1bYAmxoThECTWw9s3J0x5G8A9hokKHVDFzBjVpCoSryo6MhN8woVyascN5jheaNA==", + "dev": true, + "requires": { + "env-variable": "0.0.x" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "dependencies": { + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + } + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "integrity": "sha1-iBHpCRXZoNujYnTwskLb2nj5ySo=" + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "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 + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "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" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "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" + } + } + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "form-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz", + "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=", + "requires": { + "async": "^2.0.1", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "format-util": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.3.tgz", + "integrity": "sha1-Ay3KShFiYqEsQ/TD7IVmQWxbLZU=" + }, + "formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "got": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/got/-/got-2.4.0.tgz", + "integrity": "sha1-5Ah6LNWbXSDy0WnchdIWntnon1Y=", + "requires": { + "duplexify": "^3.2.0", + "infinity-agent": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "object-assign": "^2.0.0", + "prepend-http": "^1.0.0", + "read-all-stream": "^1.0.0", + "statuses": "^1.2.1", + "timed-out": "^2.0.0" + }, + "dependencies": { + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "requires": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + }, + "dependencies": { + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "requires": { + "@types/node": "^10.0.3" + }, + "dependencies": { + "@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "infinity-agent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/infinity-agent/-/infinity-agent-1.0.2.tgz", + "integrity": "sha1-Lp2iwHC5hkqLxmwBlOF5HtgFgCU=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "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=" + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-whitespace": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz", + "integrity": "sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jju": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.2.1.tgz", + "integrity": "sha1-7fbsINXWaMgMLADOpj+KlCKktSg=" + }, + "js-beautify": { + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.6.tgz", + "integrity": "sha512-GfofQY5zDp+cuHc+gsEXKPpNw2KbPddreEo35O6jT6i0RVK6LhsoYBhq5TvK4/n74wnA0QbK8gGd+jUZwTMKJw==", + "dev": true, + "requires": { + "config-chain": "^1.1.13", + "editorconfig": "^0.15.3", + "glob": "^8.0.3", + "nopt": "^6.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "requires": { + "abbrev": "^1.0.0" + } + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-path": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/json-path/-/json-path-0.1.3.tgz", + "integrity": "sha512-EbGs3CGmxRdOUHRYAKyPfBaNU1EpC5D1TzXjzb5avfBt0Dp1xorb1fe/G9oqAmxG2XmTatLb36N15/r/Li77xw==", + "dev": true, + "requires": { + "json-ptr": "~0.1.1" + } + }, + "json-ptr": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-0.1.1.tgz", + "integrity": "sha512-Id1WlyhEgvSAdFze7CF2pSqriY5C+6VqNuJfIF3LiMXJ0BGuuG/zHNf0toOGT3p2Xl5kyfxm2dFbw8HmkHfKeg==", + "dev": true + }, + "json-schema-compatibility": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/json-schema-compatibility/-/json-schema-compatibility-1.1.0.tgz", + "integrity": "sha1-GomBd4zaDDgYcpjZmdCJ5Rrygt8=" + }, + "json-schema-ref-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-3.3.1.tgz", + "integrity": "sha1-hudRuAmTV79gGnz+QtEBI+6QajI=", + "requires": { + "call-me-maybe": "^1.0.1", + "debug": "^3.0.0", + "es6-promise": "^4.1.1", + "js-yaml": "^3.9.1", + "ono": "^4.0.2", + "z-schema": "^3.18.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-to-ast": { + "version": "2.0.0-alpha1.3", + "resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.0.0-alpha1.3.tgz", + "integrity": "sha1-aQqngDXTp7ctUZPxtMCPm7DX4sg=" + }, + "jsonc-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", + "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + } + } + }, + "know-your-http-well": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/know-your-http-well/-/know-your-http-well-0.5.0.tgz", + "integrity": "sha512-UITbbv7opEWvgPMxHtgJIIhTnCcJIHYRKm0ozPy/IWGMymBriRRY+S9zIT51js+RmTTxhoJKxoYSS6wped18Yg==", + "dev": true, + "requires": { + "amdefine": "~0.0.4" + } + }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "dev": true, + "requires": { + "colornames": "^1.1.1" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.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" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "loophole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loophole/-/loophole-1.1.0.tgz", + "integrity": "sha512-zgLykD4MuL9HJRsoeKuGRXz4L9t1C0oDZPjFeUg5MLQyZjxWdxIbPHgRijVGN98DieVWJuo2fi9nEUDcdDbEiQ==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "^3.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "lrucache": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lrucache/-/lrucache-1.0.3.tgz", + "integrity": "sha1-Ox3tDRuoLhiLm9q6nu5khvhkpDQ=" + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "marked": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.9.tgz", + "integrity": "sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw==", + "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=" + }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "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.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "~1.30.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "minimize": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/minimize/-/minimize-2.2.0.tgz", + "integrity": "sha512-IxR2XMbw9pXCxApkdD9BTcH2U4XlXhbeySUrv71rmMS9XDA8BVXEsIuFu24LtwCfBgfbL7Fuh8/ZzkO5DaTLlQ==", + "dev": true, + "requires": { + "argh": "^0.1.4", + "async": "^2.1.5", + "cli-color": "^1.2.0", + "diagnostics": "^1.1.0", + "emits": "^3.0.0", + "htmlparser2": "^3.9.2", + "uuid": "^3.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "mocha": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.4", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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" + } + }, + "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" + } + } + } + }, + "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" + } + }, + "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" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "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" + } + }, + "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 + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "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": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "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" + } + }, + "mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "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==", + "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 + }, + "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" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "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" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "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" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nunjucks": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==", + "dev": true, + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + } + } + }, + "nunjucks-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nunjucks-markdown/-/nunjucks-markdown-2.0.1.tgz", + "integrity": "sha512-Vj85erGVoSlASDukl0JjaHSlJUH9BbKz8mQx0WiCj2P8a9DOM3cVwi5s0uVvPwR0RrwTjYO2dAuPMTZwGgUHeg==", + "dev": true + }, + "oauth2orize": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/oauth2orize/-/oauth2orize-1.10.0.tgz", + "integrity": "sha1-4M1lXINt+eDELbXUVthqpihP5Yg=", + "requires": { + "debug": "2.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object-values/-/object-values-1.0.0.tgz", + "integrity": "sha1-cq+DljARnluYw7AruMJ+MjcVgQU=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz", + "integrity": "sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==", + "dev": true, + "requires": { + "array.prototype.reduce": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.1" + } + }, + "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" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "ono": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.2.tgz", + "integrity": "sha1-Lhj/fCG56sDKt5T3owglBwANbTY=", + "requires": { + "format-util": "^1.0.3" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "osprey": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/osprey/-/osprey-0.3.2.tgz", + "integrity": "sha1-u9548qIT5LihH3H93/qPNRy4lzw=", + "requires": { + "arrify": "^1.0.0", + "body-parser": "^1.13.3", + "compose-middleware": "^2.0.1", + "compression": "^1.5.2", + "cookie-session": "^1.2.0", + "cors": "^2.7.1", + "debug": "^2.2.0", + "finalhandler": "^0.4.0", + "form-data": "^1.0.0-rc3", + "http-errors": "^1.3.1", + "invariant": "^2.1.0", + "oauth2orize": "^1.0.1", + "osprey-method-handler": "^0.10.0", + "osprey-resources": "^0.7.0", + "osprey-router": "^0.4.0", + "parseurl": "^1.3.0", + "passport": "^0.3.0", + "passport-http": "^0.3.0", + "passport-http-bearer": "^1.0.1", + "passport-oauth2-client-password": "^0.1.2", + "raml-parser": "^0.8.10", + "request-error-handler": "^1.0.0", + "type-is": "^1.5.5", + "xtend": "^4.0.0", + "yargs": "^4.1.0" + }, + "dependencies": { + "finalhandler": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", + "integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=", + "requires": { + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + } + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + } + } + }, + "osprey-method-handler": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/osprey-method-handler/-/osprey-method-handler-0.10.3.tgz", + "integrity": "sha1-9KEbg+Gc2MiSHmo9OprRFHRFyAg=", + "requires": { + "ajv": "^4.0.0", + "body-parser": "^1.10.2", + "busboy": "^0.2.9", + "compose-middleware": "^2.0.0", + "debug": "^2.2.0", + "http-errors": "^1.2.8", + "is-stream": "^1.0.1", + "json-schema-compatibility": "^1.0.1", + "lowercase-keys": "^1.0.0", + "negotiator": "^0.6.0", + "object-values": "^1.0.0", + "parseurl": "^1.3.0", + "raml-sanitize": "^1.1.2", + "raml-validate": "^1.0.6", + "standard-headers": "^0.1.0", + "stream-equal": "^0.1.5", + "type-is": "^1.5.5", + "xtend": "^4.0.0" + } + }, + "osprey-resources": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/osprey-resources/-/osprey-resources-0.7.1.tgz", + "integrity": "sha1-pRw9XT98IdRD7FZbRFZoI/PQXNA=", + "requires": { + "osprey-router": "^0.5.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=" + }, + "osprey-router": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/osprey-router/-/osprey-router-0.5.1.tgz", + "integrity": "sha1-qNG8gXYgSekRAR5Bu693SSjDMEU=", + "requires": { + "array-flatten": "^2.0.0", + "methods": "^1.1.1", + "raml-path-match": "^2.1.2", + "router": "blakeembrey/router#router-engine", + "xtend": "^4.0.1" + } + } + } + }, + "osprey-router": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/osprey-router/-/osprey-router-0.4.0.tgz", + "integrity": "sha1-EyxNwVlfHSgrICBk1D+08YGDkLs=", + "requires": { + "array-flatten": "^2.0.0", + "methods": "^1.1.1", + "raml-path-match": "^2.0.0", + "router": "git+https://github.com/blakeembrey/router.git#router-engine", + "xtend": "^4.0.1" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=" + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "router": { + "version": "git+https://github.com/blakeembrey/router.git#cfe18f9d59adca65c24c9c951ebd43e9bf07937e", + "from": "git+https://github.com/blakeembrey/router.git#router-engine", + "requires": { + "array-flatten": "2.0.0", + "debug": "^3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "setprototypeof": "1.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.0.0.tgz", + "integrity": "sha1-JN2Ys4uRlLWbIIe6QMIThNa4qNw=" + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "setprototypeof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.0.tgz", + "integrity": "sha1-1fr8oB4RdNAHm9G/iB8JyKM5eUw=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + } + } + }, + "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 + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "passport": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.3.2.tgz", + "integrity": "sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-http": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/passport-http/-/passport-http-0.3.0.tgz", + "integrity": "sha1-juU9Q4C+nGDfIVGSUCmCb3cRVgM=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha1-FHRp6jZp4qhMYWfvmdu3fh8AmKg=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-oauth2-client-password": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz", + "integrity": "sha1-TzeLZ4uS0W270jOmxwZSAJPlYbo=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, + "path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "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=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "pg": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz", + "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.5.2", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz", + "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==" + }, + "pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "requires": { + "split2": "^4.1.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pluralize": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.1.6.tgz", + "integrity": "sha1-5L9dazayr8IsgB98Nyk2F+C9xW0=" + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "pretty": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz", + "integrity": "sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==", + "dev": true, + "requires": { + "condense-newlines": "^0.2.1", + "extend-shallow": "^2.0.1", + "js-beautify": "^1.6.12" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" + }, + "raml-1-parser": { + "version": "1.1.67", + "resolved": "https://registry.npmjs.org/raml-1-parser/-/raml-1-parser-1.1.67.tgz", + "integrity": "sha512-3dcGepRbixHoQyQZ8WvLajgK3lfcyvWynU38PdkZGM/9r6KXXSCmxNypu+zwDOBT1V5O3swREIiBN5KgD91sTA==", + "dev": true, + "requires": { + "change-case": "^4.1.1", + "fs-extra": "8.1.0", + "http-response-object": "3.0.2", + "invariant": "2.2.4", + "json-path": "0.1.3", + "json-schema-compatibility": "1.1.0", + "json-stable-stringify": "1.0.1", + "loophole": "1.1.0", + "lrucache": "1.0.3", + "media-typer": "1.1.0", + "mkdirp": "^1.0.3", + "pluralize": "8.0.0", + "promise-polyfill": "8.1.3", + "q": "1.5.1", + "raml-definition-system": "^0.0.94", + "ts-model": "0.0.18", + "underscore": "^1.10.2", + "upper-case-first": "^2.0.1", + "urlsafe-base64": "1.0.0", + "xhr2": "0.2.0", + "xmldom-alpha": "^0.1.28", + "xmlhttprequest": "1.8.0", + "yaml-ast-parser": "0.0.43", + "z-schema": "^4.2.2" + }, + "dependencies": { + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "dev": true + }, + "underscore": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", + "dev": true + }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "dev": true + }, + "z-schema": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.4.tgz", + "integrity": "sha512-YvBeW5RGNeNzKOUJs3rTL4+9rpcvHXt5I051FJbOcitV8bl40pEfcG0Q+dWSwS0/BIYrMZ/9HHoqLllMkFhD0w==", + "dev": true, + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.6.0" + } + } + } + }, + "raml-definition-system": { + "version": "0.0.94", + "resolved": "https://registry.npmjs.org/raml-definition-system/-/raml-definition-system-0.0.94.tgz", + "integrity": "sha512-KawJ4uEncArvhyXThSFVN8PEbQN66rQVXX88uocaLB+MBBCduvDsVtMxAfpv5mFYXfmI/Wqgvn4CPFw6qJ9T4g==", + "dev": true, + "requires": { + "know-your-http-well": "0.5.0", + "raml-typesystem": "^0.0.96", + "ts-structure-model": "0.0.1", + "underscore": "^1.9.2" + }, + "dependencies": { + "date-and-time": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-0.11.1.tgz", + "integrity": "sha512-+1JkWME+UWRpCfvE1T0Vfbw629Ego0IcfHH0qtP4KhAXs7IJT2qsg1hNePqZhyD8Wby46HlW393lSL5PZSzDsA==", + "dev": true + }, + "raml-json-validation": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/raml-json-validation/-/raml-json-validation-0.0.18.tgz", + "integrity": "sha512-U43jM2+2203s59jMWlNQIc1SmQ4B8rJKJXL5bQJdFHVyr2W9ImLJOmDCSpkKHKlM24f72iRbU/aVupjpWY8fBA==", + "dev": true, + "optional": true, + "requires": { + "z-schema": "3.21.0" + } + }, + "raml-typesystem": { + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/raml-typesystem/-/raml-typesystem-0.0.96.tgz", + "integrity": "sha512-hf9/XlrV73ouELMe/LbwRubsNHt16/xJd7zWUuurumq2Vv6w8nxmWH0d/RImQ9Uylv80u02pcIEGKeYahdDZiA==", + "dev": true, + "requires": { + "bignumber.js": "9.0.0", + "date-and-time": "^0.11.1", + "escape-html": "1.0.3", + "json-schema-compatibility": "1.1.0", + "json-to-ast": "2.0.0-alpha1.3", + "lrucache": "1.0.3", + "raml-json-validation": "0.0.18", + "raml-xml-validation": "0.0.15", + "underscore": "^1.10.2", + "xml2js": "^0.4.23", + "xmldom-alpha": "^0.1.28" + } + }, + "raml-xml-validation": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/raml-xml-validation/-/raml-xml-validation-0.0.15.tgz", + "integrity": "sha512-ixkKvCc2b/R7WkPxhFDT7Bg7HLRyzXGp/2UrGFJfkxvsAEMC5JZ2b7LEpmrx6JGzLaHFA01KJ/IBNoZdxvM2xw==", + "dev": true, + "optional": true, + "requires": { + "xmllint-jsparser": "0.0.3" + } + }, + "underscore": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", + "dev": true + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", + "dev": true, + "optional": true + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "z-schema": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.21.0.tgz", + "integrity": "sha512-+MXJmBRZvqn+LInpJBSSETK1XLQqyhKCCNqc7MY7FqiqWCTQddAahg5i0jlfX5dli7gvIfpJvijV3ZlAJRtZ1Q==", + "dev": true, + "optional": true, + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^10.0.0" + } + } + } + }, + "raml-json-validation": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/raml-json-validation/-/raml-json-validation-0.0.13.tgz", + "integrity": "sha1-Otb7M2jumQ2UAp7NZiX97ZGggG4=", + "optional": true, + "requires": { + "z-schema": "^3.16.1" + } + }, + "raml-parser": { + "version": "0.8.18", + "resolved": "https://registry.npmjs.org/raml-parser/-/raml-parser-0.8.18.tgz", + "integrity": "sha1-CHM3UDT4uKHSDBDjFHtiebM0l6g=", + "requires": { + "got": "~2.4.0", + "jju": "~1.2.0", + "json-schema-ref-parser": "^3.1.2", + "object-assign": "^4.1.0", + "pluralize": "~1.1.1", + "q": "0.9.7", + "uritemplate": "~0.3.4" + } + }, + "raml-path-match": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/raml-path-match/-/raml-path-match-2.1.2.tgz", + "integrity": "sha1-TxmbVNEU7A0ZAxac+PETa+id69Y=", + "requires": { + "raml-sanitize": "^1.2.0", + "raml-validate": "^1.1.2", + "xtend": "^4.0.1" + } + }, + "raml-sanitize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/raml-sanitize/-/raml-sanitize-1.2.0.tgz", + "integrity": "sha1-+LrDohdDKk+DaxjaEd8kuKbmva4=" + }, + "raml-typesystem": { + "version": "0.0.75", + "resolved": "https://registry.npmjs.org/raml-typesystem/-/raml-typesystem-0.0.75.tgz", + "integrity": "sha1-CWCP7ug2fPyoWBb5o0bQFR6tpww=", + "requires": { + "date-and-time": "^0.3.0", + "json-schema-compatibility": "^1.1.0", + "json-to-ast": "^2.0.0-alpha1.2", + "lrucache": "^1.0.0", + "raml-json-validation": "0.0.13", + "raml-xml-validation": "0.0.12", + "underscore": "^1.8.3", + "xml2js": "^0.4.16", + "xmldom": "^0.1.22" + } + }, + "raml-validate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/raml-validate/-/raml-validate-1.1.2.tgz", + "integrity": "sha1-4JSZil6reVMl8zWB99RmUjdDaNQ=", + "requires": { + "raml-typesystem": "^0.0.x" + } + }, + "raml-xml-validation": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/raml-xml-validation/-/raml-xml-validation-0.0.12.tgz", + "integrity": "sha1-UwDcbP9K7K4G1+Aip8X2xE1DK7w=", + "optional": true, + "requires": { + "xmllint-jsparser": "^0.0.3" + } + }, + "raml2html": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/raml2html/-/raml2html-7.8.0.tgz", + "integrity": "sha512-3StEn6XD6vFM77EZFvpgduYz7N8YOUxyNq9QDPB9N11W+VT44ZNFBuj87cICgWVWLNi62Z9HIxVnAPu1cwVdcQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "marked": "^1.0.0", + "minimize": "2.2.x", + "nunjucks": "^3.2.2", + "nunjucks-markdown": "2.0.x", + "pretty": "^2.0.0", + "raml2html-default-theme": "^2.10.0", + "raml2obj": "^6.8.0", + "yargs": "^14.2.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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 + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "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": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "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 + }, + "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" + } + }, + "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" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "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" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.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": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", + "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "raml2html-default-theme": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/raml2html-default-theme/-/raml2html-default-theme-2.11.0.tgz", + "integrity": "sha512-dqZWkayZtta5THeTdjND16UuaDatTPcNUXyfyR7bHwgLyuUuZPukeQ7jPNgp/pKUjdGdIyBK/dL5O7DPOEORJw==", + "dev": true + }, + "raml2obj": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/raml2obj/-/raml2obj-6.8.1.tgz", + "integrity": "sha512-dtos22mQg94Qvzj5qFhnUy305nRoBGUzRmcEVwmPbyCgpv/A5NOX4ZZTyPnMG8VAHNq6WcSUapJS7KmHkk9Zbg==", + "dev": true, + "requires": { + "datatype-expansion": "^0.4.1", + "raml-1-parser": "^1.1.67" + } + }, + "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.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "read-all-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-1.0.2.tgz", + "integrity": "sha1-03jPTvbiNrGI6kLRNeWxgKiePpI=" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "request-error-handler": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/request-error-handler/-/request-error-handler-1.0.2.tgz", + "integrity": "sha1-E7aWZhW5nMx8bSC4Byqlv0bBu/s=", + "requires": { + "debug": "^2.2.0", + "dot": "^1.0.3", + "escape-html": "^1.0.2", + "invariant": "^2.1.0", + "negotiator": "^0.6.0", + "xtend": "^4.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "router": { + "version": "git://github.com/blakeembrey/router.git#cfe18f9d59adca65c24c9c951ebd43e9bf07937e", + "from": "blakeembrey/router#router-engine", + "requires": { + "array-flatten": "2.0.0", + "debug": "^3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.1", + "path-to-regexp": "0.1.7", + "setprototypeof": "1.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.0.0.tgz", + "integrity": "sha1-JN2Ys4uRlLWbIIe6QMIThNa4qNw=" + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "setprototypeof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.0.tgz", + "integrity": "sha1-1fr8oB4RdNAHm9G/iB8JyKM5eUw=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "dependencies": { + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + } + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shiki": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", + "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "^6.0.0" + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "^1.0.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "standard-headers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/standard-headers/-/standard-headers-0.1.1.tgz", + "integrity": "sha1-9/K6xKFq4S/Dn/aoTkwjukq+T7k=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stream-equal": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/stream-equal/-/stream-equal-0.1.13.tgz", + "integrity": "sha1-F8LXz43lVw0P+5njpRQqWMdrxK4=", + "requires": { + "@types/node": "*" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "supertest": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", + "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "timed-out": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", + "integrity": "sha1-84sK6B03R9YoAB9B2vxlKs5nHAo=" + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "ts-model": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ts-model/-/ts-model-0.0.18.tgz", + "integrity": "sha512-wIBuWYxYES3m0JNT8nnPTo3GgH+Xa2NGig2GWGGTryMVPiME/Tg5DQrcydBfLjf/cWcPMn9uxgANiQWaGTyFDg==", + "dev": true, + "requires": { + "underscore": "1.9.1" + }, + "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + } + } + }, + "ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "ts-structure-model": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ts-structure-model/-/ts-structure-model-0.0.1.tgz", + "integrity": "sha512-7hqYQx4kPWUkJXTVsZe++1IMd63jZAjW6O00+kHJf9/DcNaxCJxNjsQhLVcC57HZhK4SUPSxMZd+AnGrLA6Itw==", + "dev": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "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" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tslint-stylish": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslint-stylish/-/tslint-stylish-2.1.0.tgz", + "integrity": "sha1-jNo8OMnKtU57It989CuO8RXc2V8=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "lodash": "^3.10.1", + "log-symbols": "^1.0.2", + "text-table": "^0.2.0", + "tslint": "^2.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz", + "integrity": "sha1-4KkKRQB1xJRm7lE3MgV1FLgeh4w=", + "dev": true, + "requires": { + "glob": "~4.3.0" + } + }, + "glob": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tslint": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-2.5.1.tgz", + "integrity": "sha1-veTJnpfNXRxvuzAz9kt9iX/UGpI=", + "dev": true, + "requires": { + "findup-sync": "~0.2.1", + "optimist": "~0.6.0", + "underscore.string": "~3.1.1" + } + }, + "underscore.string": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.1.1.tgz", + "integrity": "sha1-DN1rytDARv12Y9MF2KeFtdoQ8zU=", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha512-f9Uv6ezcpvCQjJU0Zqbg+65qdcszv3qUQsZfjdRbWiZ7AMenrX1u0lNk9EoWWX6e1F+NULyg27mtdeZ5WhpljA==", + "dev": true + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.15" + } + }, + "typedoc": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.11.tgz", + "integrity": "sha512-FhZ2HfqlS++53UwHk4txCsTrTlpYR0So/0osMyBeP1E7llRNRqycJGfYK1qx9Wvvv5VO8tGdpwzOwDW5FrTi7A==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.0.19", + "minimatch": "^5.1.0", + "shiki": "^0.11.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "marked": { + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz", + "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==", + "dev": true + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==" + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "uritemplate": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/uritemplate/-/uritemplate-0.3.4.tgz", + "integrity": "sha1-BdCoU/+8iw9Jqj1NKtd3sNHuBww=" + }, + "urlsafe-base64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz", + "integrity": "sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" + } + }, + "validator": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", + "integrity": "sha1-PBI3KQ43CSNVNE/veMIxJJ2rd7k=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vscode-oniguruma": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "dev": true + }, + "vscode-textmate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", + "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", + "dev": true + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xhr2": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.0.tgz", + "integrity": "sha512-BDtiD0i2iKPK/S8OAZfpk6tyzEDnKKSjxWHcMBVmh+LuqJ8A32qXTyOx+TVOg2dKvq6zGBq2sgKPkEeRs1qTRA==", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", + "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xmldom-alpha": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/xmldom-alpha/-/xmldom-alpha-0.1.28.tgz", + "integrity": "sha512-u0hPuPt18K/f4bVck3elfDJr2SZ7oyB2pknGNL3uyCCiJ+z6za+skAv7oEiOcSuU4NYfRfc5SyAsowQa0E5W/g==", + "dev": true + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "dev": true + }, + "xmllint-jsparser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/xmllint-jsparser/-/xmllint-jsparser-0.0.3.tgz", + "integrity": "sha1-aLBRNDkX2pX3e3oMeg+7QAF142Y=", + "optional": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, + "yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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" + } + }, + "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" + } + }, + "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 + }, + "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": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "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 + }, + "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" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "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" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "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" + } + } + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + }, + "z-schema": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz", + "integrity": "sha1-6oEysnlTPuYL4khaAvfj5CVBqaI=", + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^8.0.0" + } + } + } +} diff --git a/package.json b/package.json index 32c49a8feccad31d6f03079bdb009ba2fd6d2fac..0ee5770fcb95c116b36ce3485ae06f737648f32a 100644 --- a/package.json +++ b/package.json @@ -4,33 +4,13 @@ "description": "BlenDB", "main": "index.js", "scripts": { - "start": "env $(cat config/config.env ) node index", + "start": "node index", "lint": "tslint -s node_modules/tslint-stylish -t stylish src/**/*.ts test/**/*.ts", - "test": "env $(cat config/test.env) ts-node node_modules/nyc/bin/nyc.js mocha", + "test": "ts-node node_modules/istanbul/lib/cli.js cover -x \"**/*.spec.ts\" -e .ts _mocha", "show-coverage": "xdg-open coverage/lcov-report/index.html", "doc-api": "raml2html -i specs/blendb-api-v1.raml -o doc/api-v1-reference.html", - "schema": "env $(cat config/config.env ) ts-node scripts/schema.ts config/config.yaml schema.sql", - "service": "./scripts/service.sh", - "test-mode": "ts-node scripts/loadTest.ts && node index", - "doc-code": "typedoc --mode 'file' --module 'commonjs' --target 'ES6' --ignoreCompilerErrors --exclude '**/*.spec.ts' --out 'doc/code' 'src'" - }, - "nyc": { - "include": [ - "src/**/*.ts" - ], - "extension": [ - ".ts" - ], - "require": [ - "ts-node/register" - ], - "reporter": [ - "text-summary", - "text", - "lcov" - ], - "sourceMap": true, - "instrument": true + "database": "ts-node database/config.ts database", + "service": "./scripts/service.sh" }, "repository": { "type": "git", @@ -43,33 +23,29 @@ "@types/chai": "^4.2.0", "@types/express": "^4.17.1", "@types/js-yaml": "^3.12.1", - "@types/pg": "^7.11.0", - "async": "^3.1.0", + "@types/pg": "^8.0.3", + "async": "^3.2.4", "express": "^4.17.1", "js-yaml": "^3.13.1", - "json-2-csv": "^3.5.6", - "log4js": "^5.1.0", - "monetdb": "^1.1.4", "osprey": "^0.3.2", - "pg": "^7.12.1", - "raml-parser": "^0.8.18", + "pg": "^8.0.1", + "pg-pool": "^3.4.1", "ts-node": "^8.3.0", "typescript": "^3.5.3" }, "devDependencies": { + "@types/cors": "^2.8.12", "@types/mocha": "^5.2.7", "@types/supertest": "^2.0.8", - "chai": "^4.2.0", + "chai": "^3.4.33", "mocha": "^6.2.0", - "nyc": "^14.1.1", - "raml2html": "^7.4.0", + "raml2html": "^7.8.0", "supertest": "^4.0.2", "tslint": "^5.19.0", "tslint-stylish": "^2.1.0", - "typedoc": "^0.15.0" + "typedoc": "^0.23.11" }, "engines": { "node": "^10.16.3" } - } diff --git a/scripts/loadTest.ts b/scripts/loadTest.ts deleted file mode 100644 index e0c53a684ee43dedc5e72f3a0ca84846ae4b856d..0000000000000000000000000000000000000000 --- a/scripts/loadTest.ts +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env node - -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - - -import { Fixture as FixPostgres } from "../test/postgres/fixture"; -import { ConfigParser } from "../src/util/configParser"; - -let config: any; -let fixture; - -let configPath; - -if(process.env.BLENDB_SCHEMA_FILE){ - configPath = process.env.BLENDB_SCHEMA_FILE; -} -else{ - throw new Error("BLENDB_SCHEMA_FILE wasn't informed"); -} -config = ConfigParser.parse(configPath); - -fixture = new FixPostgres(config.connections[0]); - -fixture.load(config.loadViews, (err) => { - if (err) { - throw err; - } -}) diff --git a/scripts/service.sh b/scripts/service.sh index 9112fd5211f6bddef97748f66421e43c2f827ea9..25597fd8137bcf48ec84b0569b59642c4a46722f 100755 --- a/scripts/service.sh +++ b/scripts/service.sh @@ -6,7 +6,7 @@ cd $basePath/.. mkdir -p service WORKSPACE=$(pwd) REAL_USER=$USER -BLENDB_PORT=3001 +BLENDB_PORT=3002 if [[ $1 != "" ]]; then @@ -61,9 +61,6 @@ echo "To set different user and port use npm run service -- <port> [<user>]" echo "Run this commands, as root (or sudo) to finish the process and start blendb" SYSTEMD_PATH=/etc/systemd/system/blendb.service -mkdir -p /var/log/ -touch /var/log/blendb.log -chown root:$REAL_USER /var/log/blendb.log echo -n "rm -f $SYSTEMD_PATH && " echo -n "ln -s $WORKSPACE/service/blendb.service $SYSTEMD_PATH && " echo "systemctl daemon-reload && systemctl restart blendb.service" diff --git a/specs/blendb-api-v1.raml b/specs/blendb-api-v1.raml index eac48517e3671d71aed5b0e36dcd08986bf7fe19..2693c9cae169ea0dbc0c6d65322bc9d88f869b71 100644 --- a/specs/blendb-api-v1.raml +++ b/specs/blendb-api-v1.raml @@ -271,27 +271,6 @@ traits: description: | Fields to be returned. type: string - - formatable: - queryParameters: - format: - description: | - Response format. Defines if the response objects will be a - json or a csv-like file. The default value is json. - The csv-like formats are: csv, ssv and tsv which the - separator is comma, semi-colon and tab respectively. - example: "ssv+" - required: false - pattern: "^json$|^csv$|^ssv$|^tsv$" - type: string - - taggable: - queryParameters: - tags: - description: | - Tags that restrict the elements returned for your request. - Similar to a filter, but used in Blendb elements, not in - query results. - required: false - type: string /metrics: description: | @@ -300,15 +279,6 @@ traits: system and their descriptions. securedBy: [ null, oauth_2_0 ] get: - is: [ formatable, taggable ] -/sources: - description: | - A Source represents a type of object that can be inserted in the database. - This collection allows the user to list all the sources available in the - system and their descriptions - securedBy: [ null, oauth_2_0 ] - get: - is: [ formatable ] /dimensions: description: | @@ -317,23 +287,7 @@ traits: the system and their descriptions. securedBy: [ null, oauth_2_0 ] get: - is: [ formatable, taggable ] -/enumtypes: - description: | - A EnumType is short for enumerable type. This is a special data type that only accepts a few possible values. This - collection allows the user to list all the enumerable types available in the system, their descriptions and possible - values. - get: - is: [ formatable ] - securedBy: [ null, oauth_2_0 ] -/tags: - description: | - A Tag can be placed in a metric or dimension to add some extra meaning - to it. Tags can be used to filter the amount of elements returned by a - route. Tags are like filters, but instead of filtering query results, - filter blendb elements. - get: - is: [ formatable ] + /data: description: | This is the main part of the API. You may query it for report @@ -342,7 +296,7 @@ traits: start/end dates to refine your query. type: base get: - is: [ filtered, formatable ] + is: [ filtered ] queryParameters: metrics: description: | diff --git a/src/adapter/monet.ts b/src/adapter/monet.ts deleted file mode 100644 index 4b97c876ffd6ae26162e21371b2a7eeed70d2b05..0000000000000000000000000000000000000000 --- a/src/adapter/monet.ts +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blend. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blend. If not, see <http://www.gnu.org/licenses/>. - */ - -import { SQLAdapter } from "./sql"; -import { View } from "../core/view"; -import { Source } from "../core/source"; -import { FilterOperator } from "../core/filter"; -import { DataType } from "../common/types"; -/** @hidden */ -const MDB = require("monetdb")(); - -/** - * Params required to connect with a MonetDB database and - * to create a MonetAdapter object. - */ -export interface MonetConfig { - /** Database hostname */ - host: string; - /** Database port */ - port: number; - /** Database name */ - dbname: string; - /** Database user */ - user: string; - /** Datavase password */ - password: string; -} -/** - * Represent the data format returned by MonetDB. - * This interface is used to parse this format to the BlenDB Standart. - */ -interface MonetResult { - /** Query result as a list of values */ - data: any[]; - /** Meta data of each attribute required. */ - structure: {type: string, column: string, index: number}[]; -} - -/** - * Adapter which connects with a MonetDB database. - */ -export class MonetAdapter extends SQLAdapter { - /** Information used to connect with a MonetDB database. */ - private config: MonetConfig; - - /** - * Creates a new adapter with the database connection configuration. - * @param conf - The information required to create a connection with - * the database. - */ - constructor (conf: MonetConfig) { - super(); - this.config = conf; - } - - /** - * Asynchronously reads all data from given view. - * In other words perform a SELECT query. - * @param view - "Location" from all data should be read. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Data got from view. - */ - public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void { - const query = this.getQueryFromView(view); - this.executeQuery(query, cb); - } - - /** - * Asynchronously executes a query and get its result. - * @param query - Query (SQL format) to be executed. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - private executeQuery(query: string, cb: (error: Error, result?: any[]) => void): void { - let pool: any = new MDB(this.config); - pool.connect(); - pool.query(query).then((result: MonetResult) => { - if (result) { - let res = result.data.map((item) => { - let obj: any = {}; - for (let i = 0; i < result.structure.length; ++i) { - let struct = result.structure[i]; - if (struct.type === "timestamp") { - obj[struct.column] = new Date(item[struct.index]); - } - else { - obj[struct.column] = item[struct.index]; - } - } - return obj; - }); - cb(null, res); - } - else { - cb(null, null); - } - }).fail((err: Error) => { - cb(err, null); - }); - pool.close(); - } - /** - * Asynchronously executes a query from Source and get its resut - * @param query - Query (SQL format) to be executed. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - - private executeQuerySource(query: string, cb: (error: Error, result?: any[]) => void): void { - let pool: any = new MDB(this.config); - pool.connect(); - pool.query(query).then((result: any) => { - if (result) { - cb(null, result); - } - else { - cb(null, null); - } - }).fail((err: Error) => { - cb(err, null); - }); - pool.close(); - } - - /** - * Asynchronously insert one register into a given Source. - * @param source - Insertion "location". - * @param data - Data to be inserted. - * @param cb - Callback function which contains the query result. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - public insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void { - const query = this.getQueryFromSource(source, data); - this.executeQuerySource(query, cb); - } - - /** - * Cast BlenDB data types to be used in MonetDB queries. - * @param quotedValue - SQL query attribute wrapped by quotes. - * @param dt - Attribute data type. - */ - protected typeCast(quotedValue: string, dt: DataType): string { - switch (dt) { - case DataType.DATE: - return "CAST(" + quotedValue + " AS TIMESTAMP)"; - case DataType.INTEGER: - return "CAST(" + quotedValue + " AS INTEGER)"; - case DataType.BOOLEAN: - return "CAST(" + quotedValue + " AS BOOLEAN)"; - default: - return quotedValue; - } - } - - /** - * Translate filter operator to be used in MonetDB queries. - * @param lSide - Operation left side operator. - * @param rSide - Operation right side operator. - * @param op - Operation to be performed. - */ - protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string { - switch (op) { - case FilterOperator.EQUAL: - return lSide + " = " + rSide; - case FilterOperator.NOTEQUAL: - return "NOT(" + lSide + " = " + rSide + ")"; - case FilterOperator.GREATER: - return lSide + " > " + rSide; - case FilterOperator.LOWER: - return lSide + " < " + rSide; - case FilterOperator.GREATEREQ: - return lSide + " >= " + rSide; - case FilterOperator.LOWEREQ: - return lSide + " <= " + rSide; - default: - return ""; - } - } -} diff --git a/src/adapter/postgres.spec.ts b/src/adapter/postgres.spec.ts index 02d722bbd89051b94b3125ed972d618fb2d4c251..597692c0ec4cdd718bc148ac4808a30113b5f162 100644 --- a/src/adapter/postgres.spec.ts +++ b/src/adapter/postgres.spec.ts @@ -19,280 +19,380 @@ */ import { expect } from "chai"; + import { PostgresAdapter } from "./postgres"; -import { MonetAdapter, MonetConfig } from "./monet"; import { Adapter } from "../core/adapter"; -import { Fixture as FixPostgres } from "../../test/postgres/fixture"; -import { Fixture as FixMonet } from "../../test/monet/fixture"; +import { Fixture } from "../../test/postgres/fixture"; + +import { ConfigParser } from "../util/configParser"; import { adapterScenario } from "../../test/scenario"; -import { eachOf } from "async"; -let adapters: Adapter[] = []; -let fixture; +describe("postgres adapter", () => { -function loadDb(db: string, index: number, cb: (err: any, result: Adapter) => void): void { + // Initializing + let config: any; let adapter: Adapter; - - if (db === "postgres") { - fixture = new FixPostgres(adapterScenario.config.connections[index]); - fixture.load(adapterScenario.config.loadViews, (err) => { + let fixture; + before((done) => { + config = ConfigParser.parse("config/test.yaml"); + fixture = new Fixture(config.connection); + fixture.load(config.loadViews, config.struct.create, (err) => { if (err) { throw err; } - adapter = new PostgresAdapter(adapterScenario.config.connections[index]); - cb(null, adapter); + adapter = new PostgresAdapter(config.connection); + done(); }); - } - else if (db === "monet") { - fixture = new FixMonet(adapterScenario.config.connections[index]); - fixture.load(adapterScenario.config.loadViews, (err) => { - if (err) { - throw err; - } - let parsedConfig: MonetConfig = { - user: adapterScenario.config.connections[index].user, - dbname: adapterScenario.config.connections[index].database, - password: adapterScenario.config.connections[index].password, - host: adapterScenario.config.connections[index].host, - port: adapterScenario.config.connections[index].port - }; - adapter = new MonetAdapter(parsedConfig); - cb(null, adapter); + }); + // Tests + it("should get data from single materialized view", (done) => { + let view = adapterScenario.materializedView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + done(); + }); + }); + it("should get data from join of 2 views (without selection)", (done) => { + let view = adapterScenario.noSelectionView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(1); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + done(); + }); + }); + it("should get data from join of 2 views (with selection)", (done) => { + let view = adapterScenario.withSelectionView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + done(); + }); + }); + it("should get data from single view (with sub-dimension)", (done) => { + let view = adapterScenario.subDimensionView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + done(); + }); + }); + it("should get data from join of 4 views (with selection)", (done) => { + let view = adapterScenario.join4View; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); + done(); }); - } - else{ - cb("invalid adapter", null); - } -} + }); -describe("Sql adapter", () => { - // Initializing - before(function (done): void { - // Arrow function not used to get acces to this and skip the test - eachOf(adapterScenario.config.adapters , function(database, key: number, callback) { - loadDb(database, key, function(err, result ) { - if (err){ - return callback(err); - } - else{ - adapters[key] = result; - } - callback(); + it("should get data from different sub dimensions with same parent", (done) => { + let view = adapterScenario.dateView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + expect(row).to.have.property("dim:0:year", 2017); }); - }, function (err){ - if (err){ - this.skip(); - } - else{ - done(); - } + done(); }); }); + it("should get data from view with all types of agreggation", (done) => { + let view = adapterScenario.aggrView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(1); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); + }); - for (let i = 0; i < adapterScenario.config.ndb; i++ ){ + expect(parseInt(result[0]["met:0"], 10)).to.be.equal(15); + expect(parseInt(result[0]["met:1"], 10)).to.be.equal(3); + expect(parseInt(result[0]["met:6"], 10)).to.be.equal(5); + expect(parseInt(result[0]["met:10"], 10)).to.be.equal(5); + expect(parseInt(result[0]["met:11"], 10)).to.be.equal(1); + done(); + }); + }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from single materialized view", (done) => { - let view = adapterScenario.materializedView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + it("should get data from view when a single clause exists", (done) => { + let view = adapterScenario.clauseView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(1); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + expect(parseInt(result[0]["met:0"], 10)).to.be.equal(1); + expect(parseInt(result[0]["met:1"], 10)).to.be.equal(1); + expect(parseInt(result[0]["met:2"], 10)).to.be.equal(1); + expect(result[0]["dim:0"].getDate()).to.be.equal(1); + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should sort data from join of two views", (done) => { - let view = adapterScenario.sortView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(4); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view with single clause, with more than on filter", (done) => { + let view = adapterScenario.multiFilterView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(2); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from single view (with sub-dimension)", (done) => { - let view = adapterScenario.subDimensionView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); - }); + }); + + it("should get data from view with multiple clauses", (done) => { + let view = adapterScenario.multiClauseView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(0); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from join of one view", (done) => { - let view = adapterScenario.joinWithOneView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view with a clause with not equal operator", (done) => { + let view = adapterScenario.notEqualView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(2); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from view with a single clause", (done) => { - let view = adapterScenario.filterWithEqual; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(1); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view, using > AND < operators on filters", (done) => { + let view = adapterScenario.gtltView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(1); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from reduce with the same attributes of view", (done) => { - let view = adapterScenario.reduceAsView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view, using >= AND <= operators on filters", (done) => { + let view = adapterScenario.geleView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(3); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from join into reduce with a single clause", (done) => { - let view = adapterScenario.filterAverageBought; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(3); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data when a filter does not have any effect on the query", (done) => { + let view = adapterScenario.notMatchFilterView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from view with multiple clauses", (done) => { - let view = adapterScenario.multipleClause; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(1); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data using COUNT when the view is not origin", (done) => { + let view = adapterScenario.notOriginCount; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(4); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from view with single clause, with more than one filter", (done) => { - let view = adapterScenario.singleClause; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(4); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from a unmaterializeble view", (done) => { + let view = adapterScenario.unMaterializebleView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from view with no metrics", (done) => { - let view = adapterScenario.joinWithNoMetrics; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from partial joins", (done) => { + let view = adapterScenario.partialJoinView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(5); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from join with one metric and one view", (done) => { - let view = adapterScenario.growOneView; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view when joins can be propagated", (done) => { + let view = adapterScenario.propagatedClauseView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(2); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - it(adapterScenario.config.adapters[i] + ": " + "should get data from join with unrelated dimension", (done) => { - let view = adapterScenario.JoinWithAncestors; - adapters[i].getDataFromView(view, (err, result) => { - expect(err).to.be.a("null"); - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(view.metrics.map((item) => item.name)); - keys = keys.concat(view.dimensions.map((item) => item.name)); - result.forEach((row) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - done(); + }); + + it("should get data from view when joins propaged is in the aggregation", (done) => { + let view = adapterScenario.propagatedClauseAggrView; + adapter.getDataFromView(view, (err, result) => { + expect(err).to.be.a("null"); + expect(result).to.be.an("array"); + expect(result).to.have.length(4); + expect(result[0]).to.be.an("object"); + let keys: string[] = []; + keys = keys.concat(view.metrics.map((item) => item.name)); + keys = keys.concat(view.dimensions.map((item) => item.name)); + result.forEach((row) => { + expect(row).to.be.an("object"); + expect(row).to.have.all.keys(keys); }); + + done(); }); - } + }); }); diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts index 61c6b0d57d9f08ead616f6fe501966a4910e3bcc..89ed874f4c97037abd1269ae35db98b1080469ab 100644 --- a/src/adapter/postgres.ts +++ b/src/adapter/postgres.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre + * Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre * Departamento de Informatica - Universidade Federal do Parana * * This file is part of blend. @@ -18,52 +18,75 @@ * along with blend. If not, see <http://www.gnu.org/licenses/>. */ -import { SQLAdapter } from "./sql"; +import { Adapter } from "../core/adapter"; +import { Metric } from "../core/metric"; +import { Dimension } from "../core/dimension"; +import { Clause } from "../core/clause"; +import { Filter, FilterOperator } from "../core/filter"; +import { AggregationType, RelationType } from "../common/types"; import { View } from "../core/view"; -import { Source } from "../core/source"; -import { FilterOperator } from "../core/filter"; import { Pool, PoolConfig } from "pg"; -import { DataType } from "../common/types"; -/** Adapter which connects with a PostgreSQL database. */ -export class PostgresAdapter extends SQLAdapter { - /** Information used to connect with a PostgreSQL database. */ +interface ExpandedView { + dimensions: Dimension[]; + metrics: Metric[]; + dimMetrics: Metric[]; + keys: Dimension[]; + clauses: Clause[]; + from: string; + id: string; + origin: boolean; +} + +interface DimInfo { + dim: Dimension; + views: ExpandedView[]; +} + +interface DimTranslation { + aliased: string; + noalias: string; +} + +export class PostgresAdapter extends Adapter { private pool: Pool; - /** - * Creates a new adapter with the database connection configuration. - * @param config - The information required to create a connection with - * the database. - */ - constructor (config: PoolConfig) { + constructor(config: PoolConfig) { super(); - this.pool = new Pool(config); + this.pool = new Pool({ + user: config.user, + password: config.password, + database: config.database, + host: config.host, + port: config.port, + max: config.max, + idleTimeoutMillis: config.idleTimeoutMillis + }) } - /** - * Asynchronously reads all data from given view. - * In other words perform a SELECT query. - * @param view - "Location" from all data should be read. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Data got from view. - */ + /* + j is the line number, just used to keep track of the lines; + i is the char's delimiter. if you need to have a better view on the console, + you can change the i's incrementer to a more confortable number + */ + private showQuery(query: string) { + console.log("query final!", query); + let j = 0; + for (let i = 0; i < 5000; i += 200) { + console.log(j, query.substring(i, i + 200)); + j++; + } + } public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void { const query = this.getQueryFromView(view); this.executeQuery(query, cb); } + /* if the connection doesn't show anything, you should take a look at the pg and node versions */ + private async executeQuery(query: string, cb: (err: Error, result?: any[]) => void): Promise<void> { - /** - * Asynchronously executes a query and get its result. - * @param query - Query (SQL format) to be executed. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - private executeQuery(query: string, cb: (err: Error, result?: any[]) => void): void{ this.pool.connect((err, client, done) => { if (err) { - cb (err); + cb(err); return; } client.query(query, [], (error, result) => { @@ -74,59 +97,813 @@ export class PostgresAdapter extends SQLAdapter { }); } - /** - * Asynchronously insert one register into a given Source. - * @param source - Insertion "location". - * @param data - Data to be inserted. - * @param cb - Callback function which contains the query result. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - public insertIntoSource(source: Source, data: any[], cb: (err: Error, result?: any[]) => void): void { - const query = this.getQueryFromSource(source, data); - this.executeQuery(query, cb); + public materializeView(view: View): boolean { + return false; } - /** - * Cast BlenDB data types to be used in PostgreSQL queries. - * @param quotedValue - SQL query attribute wrapped by quotes. - * @param dt - Attribute data type. - */ - protected typeCast(quotedValue: string, dt: DataType): string { - switch (dt) { - case DataType.DATE: - return quotedValue + "::DATE"; - case DataType.INTEGER: - return quotedValue + "::INTEGER"; - case DataType.BOOLEAN: - return quotedValue + "::BOOLEAN"; + public getQueryFromView(view: View): string { + /* + Find the base (materialized) views that has this data and expand + them (make a parse to the format used in the adapter) + */ + const materialized = this.searchMaterializedViews(view).sort((a, b) => { + return (a.id < b.id) ? -1 : 1; + }).map((item) => { + return { + id: item.id, + from: "view_" + item.id, + dimMetrics: [], + metrics: item.metrics.filter((i) => { + return view.metrics.some((j) => i.name === j.name); + }), + dimensions: item.dimensions, + keys: item.keys, + clauses: item.clauses, + origin: item.origin + }; + }); + + // Remove repeated views from the result + let partialJoin = [materialized[0]]; + for (let i = 1; i < materialized.length; ++i) { + if (materialized[i - 1].id !== materialized[i].id) { + partialJoin.push(materialized[i]); + } + } + + const blackList = view.dimensions.map((i) => i.name); + for (let i = 0; i < view.clauses.length; ++i) { + if (view.clauses[i].filters.length === 1) { + let filter = view.clauses[i].filters[0]; + if (filter.operator === FilterOperator.EQUAL) { + blackList.push(filter.target.name); + } + } + } + + /* + If there is more than one source of data (tables/views) + a join is needed. + + Partial Join represents how many sources still exists, + every join reduces this number. + */ + let clausesToCover = view.clauses.map((i) => i); + while (partialJoin.length > 1) { + /* + Variable map finds what dimenensions are still needed to + complete this query, they are required for 2 reasons. + 1 - To make joins + 2 - Because they are in the query + + For each view that has this dimension we add one score to + this dimension, if they are in the query the same. + + Automatically if the dimension is in the query there will be + at least one view with this atribute (or the query could not be + completed) so dimensions in the query always have score of + at least 2. + + To make a join the dimension must be in 2 different views, + creating a score of 2 either. + + If the score is less than 2 so this dimension is not required + anymore and can be removed. + */ + let map: { [key: string]: number } = {}; + let partialsChange = false; + for (let i = 0; i < partialJoin.length; ++i) { + const dims = partialJoin[i].dimensions; + for (let k = 0; k < dims.length; ++k) { + if (!map[dims[k].name]) { + map[dims[k].name] = 1; + } + + else { + ++map[dims[k].name]; + } + } + } + + for (let i = 0; i < view.dimensions.length; ++i) { + let dim = view.dimensions[i]; + while (dim !== null) { + if (map[dim.name]) { + ++map[dim.name]; + } + dim = dim.parent; + } + } + + /* + Also mark scores for dimensions inside clauses + */ + for (let i = 0; i < clausesToCover.length; ++i) { + for (let j = 0; j < clausesToCover[i].targets.length; ++j) { + if (map[clausesToCover[i].targets[j].name]) { + ++map[clausesToCover[i].targets[j].name]; + } + } + } + + for (let i = 0; i < partialJoin.length; ++i) { + const dims = partialJoin[i].dimensions.filter((item) => { + return map[item.name] > 1; + }); + const keys = partialJoin[i].keys.filter((item) => { + return map[item.name] > 1; + }); + /* + At this point the dimensions with less than score 2 + are removed, if this happens the view is agreggated + again, with less dimensions, removing this dimension + from the view. + */ + + let coveredClauses: Clause[] = []; + let notCoveredClauses: Clause[] = []; + /* + If all dimensions in a clause are a sub set of the + dimensions of a view, this clause is apllied now, + propagating the clause to this point. + + Then this clause is removed from the set of clauses + */ + for (let j = 0; j < clausesToCover.length; ++j) { + if (clausesToCover[j].isCovered(partialJoin[i].dimensions)) { + coveredClauses.push(clausesToCover[j]); + } + else { + notCoveredClauses.push(clausesToCover[j]); + } + } + clausesToCover = notCoveredClauses.filter((clause) => { + return !partialJoin[i].clauses.some((c) => c.id === clause.id); + }); + if (dims.length < partialJoin[i].dimensions.length || coveredClauses.length > 0) { + const partial = new View({ + metrics: partialJoin[i].metrics, + dimensions: dims, + keys: keys, + origin: false, + clauses: coveredClauses.concat(partialJoin[i].clauses), + materialized: false + }); + const from = "(" + + this.buildQuery(partial, [partialJoin[i]]) + + ") AS view_" + partial.id + "\n"; + + partialJoin[i].id = partial.id; + partialJoin[i].dimensions = partial.dimensions; + partialJoin[i].keys = partial.keys; + partialJoin[i].origin = partial.origin; + partialJoin[i].from = from; + + partialsChange = true; + } + } + /* + If at least one of the views changed (have the number of + dimensions reduced) returns to the begining of the loop + again. + + Othewise we need to make a join. + */ + if (!partialsChange) { + /* + Sorting the views by keys. + If the keys are identical, then they + will be in sequence, and views with identical + keys can be joined. + + Sort an array of keys is the same as sort a + array of strings. + */ + const sorted = partialJoin.sort((a, b) => { + return this.compareKeys(a.keys, b.keys, blackList); + }); + /* + SUPER WARNING: WHEN THE BLACK LIST IS USED THE VIEW IS + UNMATERIALIZEBLE, BUT THE QUERY CAN AGGREGATE THE VALUES + + The blackList is the array of dimensions of the query plus + the dimensions in filters using the equality operator. + In further coments is expained that the relation to make + a join must be one-to-one between the tables. + However and a dimension is choosed, a sub view is + created and if the relation is preserved in the sub view + the query can be agregated, but this view cannot be re-used + so it is unmaterializeble. + + The equality operator is the same as select one subview. + */ + /* + First of all, the remaining views are splited in segments. + + A segment contains views with the same keys that are great + to make joins. Joins like this do not create "dimensional + metrics". + + In joins like this one row of each view will be connected + with at most one row of each other table. + */ + const segment = [[sorted[0]]]; + let segmentId = 0; + for (let i = 1; i < sorted.length; ++i) { + if (this.compareKeys(sorted[i - 1].keys, sorted[i].keys, blackList) === 0) { + segment[segmentId].push(sorted[i]); + } + else { + ++segmentId; + segment.push([sorted[i]]); + } + } + + partialJoin = []; + let ableToJoin = false; + + for (let i = 0; i < segment.length; ++i) { + /* + If a segment has more than one view, a join can be made + */ + if (segment[i].length > 1) { + let mets: Metric[] = []; + let clauses: Clause[] = []; + let dims: Dimension[] = []; + let dimMetrics: Metric[] = []; + for (let j = 0; j < segment[i].length; ++j) { + mets = mets.concat(segment[i][j].metrics); + clauses = clauses.concat(segment[i][j].clauses); + dims = dims.concat(segment[i][j].dimensions); + dimMetrics = dimMetrics.concat(segment[i][j].dimMetrics); + } + + dims = this.removeDuplicatedDimensions(dims); + /* + Its atributes are just concatenated and the + duplicates removed. + */ + + const partial = new View({ + metrics: mets, + dimensions: dims, + keys: segment[i][0].keys, + origin: false, + clauses: clauses, + materialized: false + }); + const viewFrom = "(" + + this.buildQuery(partial, segment[i]) + + ") AS view_" + partial.id + "\n"; + + partialJoin.push({ + id: partial.id, + from: viewFrom, + dimMetrics: dimMetrics, + metrics: partial.metrics, + dimensions: partial.dimensions, + keys: partial.keys, + clauses: partial.clauses, + origin: partial.origin + }); + + ableToJoin = true; + } + + else { + /* + If the segment has just one view, anything can be + done at this point, so just reinsert this view in + set of views. + */ + partialJoin.push(segment[i][0]); + } + } + + /* + If at least one join was made in the last part (a segment + with more than one view) than return to the begining of the + loop. + + This permits after a join remove the dimensions that were + only choosen to this join, and are no longer required + + Ideally the joins should be restrict the join method used + above, but in some cases this can not be done. + + So if all the segments have only one view inside, move + to the next method. + */ + if (!ableToJoin) { + /* + At this point 2 views will be joined, first the + similarity with each pair of views is calculated, + the pair with the biggedt similarity will be joined. + + Similarity is calculated with the number of common + dimensions in the keys. + */ + let similarity = 0; + let idx0 = 0; + let idx1 = 1; + for (let i = 0; i < partialJoin.length; ++i) { + for (let j = i + 1; j < partialJoin.length; ++j) { + const pi = partialJoin[i].keys; + const pj = partialJoin[j].keys; + let score = this.similarDimensions(pi, pj); + if (similarity < score) { + similarity = score; + idx0 = i; + idx1 = j; + } + } + } + + const partial0 = partialJoin[idx0]; + const partial1 = partialJoin[idx1]; + + partialJoin.splice(idx1, 1); + partialJoin.splice(idx0, 1); + + /* + Once the views are select they are joined with the + same method, concatenedted its atributes and + removing duplicates, however the nasty effect of + this join is the creation of "dimensional metrics". + + "Dimensional metrics" are metrics that can no longer + be aggregated, and at this point to the end + of a query they will act as dimensions. + + This change happens to avoid inconsistency generated + by a join where one row of one table can be connected + to more than one of other table. + + Take this example. + + View0 : metrics [met0], dimensions [dim0] + values: [{met0: 10, dim0: 1}] + View1 : metrics [met1], dimensions [dim2] + values: [{met1: 10, dim2: 1}. {met1: 5, dim2: 2}] + View2 : metrics [], dimensions [dim0, dim1, dim2] + values: [ + {dim0: 1, dim1: 1, dim2: 1}, + {dim0: 1, dim1: 1, dim2: 2} + ] + The query is metrics [met0, met1] and dimensions [dim1] + First a join of View0 and View1 is made, the result + is: [ + {dim0: 1, dim1: 1, dim2: 1, met0: 10}, + {dim0: 1, dim1: 1, dim2: 2, met0: 10} + ] + Note that the value of met0 is duplicated. + Now dim0 is removed, than joined with view2 resulting + in: [ + {met1: 10, dim1: 1, dim2: 1, met0: 10}, + {met1: 5 , dim1: 1, dim2: 2, met0: 10} + ] + + Lets assume that the agregation is SUM + If we remove dim2 and re-agregate the result is: [ + {met1: 15, dim1: 1, met0: 20} + ] + + This result is wrong. The replication of the value + met0 affects the result. + + See if met1 was not required, first the dimemnsion would + be reduced, left dim0 and dim1, than joined that reduced + again resulting in the value [ + {dim1:1, met0: 10} + ] + + Is this case there is no duplication and the aggregation + does not include more rows than should. + + To solve this problem the met0 must become a dimension, + in other words, not aggregated again. If the met0 was + not agregated in the query met0, met1, dim1 the result + is: [ + {met1: 15, dim1: 1, met0: 10} + ] + what is compatible. + + After this extreme long explanation what must be + known is: Joining views with diferent keys + generate "dimensional metrics". + + Views with "dimensional metrics" can not used for future + queries because can not be re-agregated, so this must be + avoided and is one-query only views. + */ + + let dimMetrics: Metric[]; + let mets: Metric[]; + let dims = partial0.dimensions.concat(partial1.dimensions); + dims = this.removeDuplicatedDimensions(dims); + let keys = partial0.keys.concat(partial1.keys); + keys = this.removeDuplicatedDimensions(keys); + if (partial0.keys.length === similarity) { + /* + Here the metrics become dimensions, but the effect + can be reduced. If the keys of partial0 + is a sub set of the keys ou partial1 + than the number of rows of partial 1 is not + affected, in other words the metrics of partial1 + can be aggregated and does not need to become + dimensions. + */ + partial0.dimMetrics = partial0.dimMetrics.concat(partial0.metrics); + partial0.metrics = []; + mets = partial1.metrics; + } + + else if (partial1.keys.length === similarity) { + /* + The same occurs if the keys of partia1 is a subset + of partial0. + */ + partial1.dimMetrics = partial1.dimMetrics.concat(partial1.metrics); + partial1.metrics = []; + mets = partial0.metrics; + } + + else { + /* + But if there is no sub set, than both sides have + the metrics turned in dimensions. + */ + partial0.dimMetrics = partial0.dimMetrics.concat(partial0.metrics); + partial0.metrics = []; + partial1.dimMetrics = partial1.dimMetrics.concat(partial1.metrics); + partial1.metrics = []; + mets = []; + } + + dimMetrics = partial0.dimMetrics.concat(partial1.dimMetrics); + const partial = new View({ + metrics: mets, + dimensions: dims, + keys: keys, + origin: false, + clauses: partial0.clauses.concat(partial1.clauses), + materialized: false + }); + const id = new View({ + metrics: mets.concat(dimMetrics), + dimensions: dims, + keys: keys, + origin: false, + clauses: partial0.clauses.concat(partial1.clauses), + materialized: false + }).id; + const viewFrom = "(" + + this.buildQuery(partial, [partial0, partial1]) + + ") AS view_" + id + "\n"; + partialJoin.push({ + id: id, + from: viewFrom, + dimMetrics: dimMetrics, + metrics: mets, + dimensions: dims, + keys: keys, + clauses: partial.clauses, + origin: false + }); + + } + } + } + + /* + When only one view remain, the query is made and a ; + is added at the end. + + TODO: Probrably this last line adds one more + layer to the query, that is in fact unnecessary. + Think a way to remove-it. + */ + return this.buildQuery(view, partialJoin) + ";"; + } + + private searchMaterializedViews(view: View): View[] { + let r: View[] = []; + if (view.materialized) { + return [view]; + } + + else { + let children = view.childViews; + for (let i = 0; i < children.length; ++i) { + r = r.concat(this.searchMaterializedViews(children[i])); + } + } + + return r; + } + + private buildQuery(target: View, views: ExpandedView[]) { + const metrics = target.metrics; + const dimensions = target.dimensions; + const clauses = target.clauses; + + let dimMap: { [key: string]: DimInfo } = {}; + let nameMap: { [key: string]: ExpandedView } = {}; + + for (let i = 0; i < views.length; ++i) { + const mets = views[i].metrics; + const dims = views[i].dimensions; + for (let j = 0; j < mets.length; ++j) { + if (!nameMap[mets[j].name]) { + nameMap[mets[j].name] = views[i]; + } + + } + + for (let j = 0; j < dims.length; ++j) { + if (!dimMap[dims[j].name]) { + dimMap[dims[j].name] = { + dim: dims[j], + views: [views[i]] + }; + nameMap[dims[j].name] = views[i]; + } + + else { + dimMap[dims[j].name].views.push(views[i]); + } + } + } + + // Projection + const strMetrics = metrics.map((metric) => { + const view = nameMap[metric.name]; + if (view) { + return this.translateMetric(metric, view); + } + + return ""; + }).filter((item) => item !== ""); + + const parsedDimensions = dimensions.map((dimension) => { + let dim = dimension; + while (!nameMap[dim.name]) { + dim = dim.parent; + } + const view = nameMap[dim.name]; + return this.translateDimension(dimension, dim, view); + }); + + let parsedDimMetrics: DimTranslation[] = []; + + for (let i = 0; i < views.length; ++i) { + const dimMets = views[i].dimMetrics.map((item) => { + return this.translateDimMetric(item, views[i]); + }); + + parsedDimMetrics = parsedDimMetrics.concat(dimMets); + } + + const totalDimensions = parsedDimensions.concat(parsedDimMetrics); + + const strDimensions = totalDimensions.map((item) => item.aliased); + const grouped = totalDimensions.map((item) => item.noalias); + const elements = strMetrics.concat(strDimensions); + + // Joins + let conds: string[] = []; + for (let i in dimMap) { + let remainViews = dimMap[i].views.slice(); + let dim = dimMap[i].dim; + let leftSide = this.buildColumn(dim, remainViews.shift().id); + if (remainViews.length > 0) { + while (remainViews.length > 0) { + const id = remainViews.shift().id; + const rightSide = this.buildColumn(dim, id); + conds.push(leftSide + " = " + rightSide); + } + } + + } + + // Selection + let covered: Clause[] = []; + for (let i = 0; i < views.length; ++i) { + // Get the clauses that children already cover + covered = covered.concat(views[i].clauses); + } + + const toCover = clauses.filter((item) => !covered.some((clause) => { + return clause.id === item.id; + })); + + toCover.forEach((item) => { + const clause = "(" + this.translateClause(item, nameMap) + ")"; + if (clause !== "()") { + conds.push(clause); + } + }); + + // Assembly + + const projection = "SELECT " + elements.join(","); + const source = " FROM " + views.map((view) => view.from).join(","); + const selection = (conds.length > 0) ? " WHERE " + conds.join(" AND ") : ""; + let grouping = ""; + if (grouped.length > 0) { + grouping = " GROUP BY " + grouped.join(","); + } + + return projection + source + selection + grouping; + + } + + private getAggregateFunction(aggrType: AggregationType, origin: boolean): string { + switch (aggrType) { + case AggregationType.SUM: + return "SUM"; + case AggregationType.AVG: + return "AVG"; + case AggregationType.COUNT: + return (origin) ? "COUNT" : "SUM"; + case AggregationType.MAX: + return "MAX"; + case AggregationType.MIN: + return "MIN"; + default: + return ""; + } + + } + + private translateRelation(relation: RelationType, arg: string): string { + switch (relation) { + case RelationType.DAY: + return this.applyRelation("EXTRACT", ["DAY FROM "], [arg]); + case RelationType.MONTH: + return this.applyRelation("EXTRACT", ["MONTH FROM "], [arg]); + case RelationType.YEAR: + return this.applyRelation("EXTRACT", ["YEAR FROM "], [arg]); + case RelationType.DAYOFWEEK: + return this.applyRelation("EXTRACT", ["DOW FROM "], [arg]); default: - return quotedValue; + return ""; } + } - /** - * Translate filter operator to be used in PostgreSQL queries. - * @param lSide - Operation left side operator. - * @param rSide - Operation right side operator. - * @param op - Operation to be performed. - */ - protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string { + private applyRelation(name: string, args: string[], values: string[]): string { + /* + This adapter uses the concept of functions in Postgres to + implement BLENDB sub-dimention relations, this functions + applys the transformation to build the call of a Postgres + funtion. Note that this function can be native from postgres, + like EXTRACT, or even implemented on the database. + This function is short and only used in the translateRelation + method however is a bit complex and is possible to be used + several times, because of that is puted appart to make easyer update + and avoid problems + Example + applyRelation ("EXTRACT", "["DAY FROM"]", ["view_0.date"]) + output: EXTRACT(DAY FROM view_0.date) + */ + return name + "(" + args.map((item, idx) => item + values[idx]).join(",") + ")"; + } + + private buildColumn(item: Metric | Dimension, id: string): string { + const quotedName = "\"" + item.name + "\""; + return "view_" + id + "." + quotedName; + } + + private translateClause(clause: Clause, map: { [key: string]: ExpandedView }): string { + const r = clause.filters.map((item) => { + return this.translateFilter(item, map); + }).filter((item) => { + return item !== ""; + }); + return r.join(" OR "); + } + + private translateFilter(filter: Filter, map: { [key: string]: ExpandedView }): string { + if (!map[filter.target.name]) { + return ""; + } + + const viewId = map[filter.target.name].id; + const leftSide = this.buildColumn(filter.target, viewId); + const op = this.translateOperator(filter.operator); + const dataType = this.translateDataType(filter.target.dataType); + const quotedValue = "'" + filter.value + "'"; + return leftSide + op + quotedValue + dataType; + } + + private translateMetric(metric: Metric, view: ExpandedView): string { + const func = this.getAggregateFunction(metric.aggregation, view.origin); + const quotedName = "\"" + metric.name + "\""; + const extMetric = func + "(" + this.buildColumn(metric, view.id) + ")"; + return extMetric + " AS " + quotedName; + } + + private translateDimMetric(metric: Metric, view: ExpandedView): DimTranslation { + const quotedName = "\"" + metric.name + "\""; + const extMetric = this.buildColumn(metric, view.id); + return { aliased: extMetric + " AS " + quotedName, noalias: extMetric }; + } + + private translateDimension(dimension: Dimension, + ancestor: Dimension, + view: ExpandedView): DimTranslation { + const quotedName = "\"" + dimension.name + "\""; + let extDimension = this.buildColumn(ancestor, view.id); + let aux = dimension; + while (aux.name !== ancestor.name) { + extDimension = this.translateRelation(aux.relation, extDimension); + aux = aux.parent; + } + return { aliased: extDimension + " AS " + quotedName, noalias: extDimension }; + } + + private translateOperator(op: FilterOperator): string { switch (op) { case FilterOperator.EQUAL: - return lSide + " = " + rSide; + return " = "; case FilterOperator.NOTEQUAL: - return lSide + " != " + rSide; + return " != "; case FilterOperator.GREATER: - return lSide + " > " + rSide; + return " > "; case FilterOperator.LOWER: - return lSide + " < " + rSide; + return " < "; case FilterOperator.GREATEREQ: - return lSide + " >= " + rSide; + return " >= "; case FilterOperator.LOWEREQ: - return lSide + " <= " + rSide; + return " <= "; + default: + return ""; + } + + } + + private translateDataType(dt: string): string { + switch (dt) { + case "date": + return "::DATE"; + case "integer": + return "::INTEGER"; + case "boolean": + return "::BOOLEAN"; default: - return ""; + return ""; + } + } + + private compareKeys(a: Dimension[], b: Dimension[], blackList: string[]): number { + /* + SUPER WARNING: WHEN THE BLACK LIST IS USED THE VIEW IS + UNMATERIALIZEBLE, BUT THE QUERY CAN AGGREGATE THE VALUES + */ + let c = a.filter((i) => !blackList.some((bad) => bad === i.name)); + let d = b.filter((i) => !blackList.some((bad) => bad === i.name)); + let length = 0; + let res = c.length - d.length; + if (c.length < d.length) { + length = c.length; + } + else { + length = d.length; + } + + for (let i = 0; i < length; ++i) { + if (c[i].name < d[i].name) { + return -1; + } + + else if (c[i].name > d[i].name) { + return 1; + } + } + + return res; + } + + private similarDimensions(a: Dimension[], b: Dimension[]): number { + let count = 0; + for (let i = 0; i < a.length; ++i) { + if (b.some((itemB) => a[i].name === itemB.name)) { + count++; + } + } + return count; + } + + private removeDuplicatedDimensions(candidateDims: Dimension[]): Dimension[] { + let filterDims: { [key: string]: boolean } = {}; + const dims = []; + for (let i = 0; i < candidateDims.length; ++i) { + if (!filterDims[candidateDims[i].name]) { + dims.push(candidateDims[i]); + filterDims[candidateDims[i].name] = true; + } } + return dims; } } diff --git a/src/adapter/sql.ts b/src/adapter/sql.ts deleted file mode 100644 index 17c38ee1e5b8cb81ffd23bf9b7c1250c0852fe5b..0000000000000000000000000000000000000000 --- a/src/adapter/sql.ts +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blend. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blend. If not, see <http://www.gnu.org/licenses/>. - */ - -import { Adapter } from "../core/adapter"; -import { Metric } from "../core/metric"; -import { Source } from "../core/source"; -import { Dimension } from "../core/dimension"; -import { Clause } from "../core/clause"; -import { Filter, FilterOperator } from "../core/filter"; -import { AggregationType, RelationType, DataType } from "../common/types"; -import { Operation, Opcode } from "../common/expression"; -import { View } from "../core/view"; -import { Tsort } from "../util/tsort"; - -/** - * Information required to make a join clause. - * The dimension and views that contain this dimension. - */ -interface DimInfo { - /** Dimension object. */ - dim: Dimension; - /** Set of views that contain the dimension. */ - views: View[]; -} - -/** - * Several translations of a dimension that will be used in different - * parts of a query - */ -interface DimTranslation { - /** Translation with the AS clause. Used on SELECT clause. */ - aliased: string; - /** Translation without the AS clause. USED on GROUP BY clause. */ - noalias: string; - /** The alias of the dimension. The quoted name. */ - alias: string; - /** Expansion of a sub dimension. */ - expanded: boolean; -} - -/** Translated view, the query which gets all data and its name */ -interface QueryAndName { - /** Query that returns all the data of a view. */ - query: string; - /** The view name. */ - name: string; -} - -/** Dictonary indexed by view name, that returns the QueryAndName object. */ -interface QNMap { - [key: string]: QueryAndName; -} - -/** - * Two Dictionaries, both indexed with a dimension name. - * Used to get the views where a dimension is. - * The dimensions also have the Dimension object inside. - */ -interface DimAndNameMap { - /** Dictionary indexed by dimension name that returns DimInfo */ - dimensions: {[key: string]: DimInfo}; - /** - * Dictionary indexed by dimension name that returns - * a view where this dimension is. Used as right side - * of a join clause. - */ - views: {[key: string]: View}; -} - -/** - * Generic SQL adapter. - * Contains most implementation to perform a SQL query. - * However, which database has its peculiarities, so this - * adapter must be extended to each SGBD. - */ -export abstract class SQLAdapter extends Adapter { - /** - * Translate a view to a SQL query. - * @param view - View to be translated. - */ - public getQueryFromView(view: View): string { - const map = this.buildPartials(view); - const topSort = Tsort.view(view); - const partials = topSort.map((i) => { - return (map[i]) ? map[i] : {query : "", name: i}; - }).filter((i) => { - return i.query !== ""; - }).map((i) => { - return i.name + " AS (" + i.query + ")"; - }); - - let withClause = ""; - if (partials.length > 0) { - withClause = "WITH " + partials.join(", ") + " "; - } - - let sort = ""; - if (view.sort.length > 0) { - // Sorting - const order = view.sort.map((item) => { - return "\"" + item.name + "\""; - }).join(","); - - sort = " ORDER BY " + order; - } - - const dimensions = view.dimensions.map((item) => { - return "\"" + item.name + "\""; - }).join(","); - - const metrics = view.metrics.map((item) => { - return "\"" + item.name + "\""; - }).join(","); - - let attributes = ""; - if (dimensions.length > 0) { - if (metrics.length > 0) { - attributes = dimensions + "," + metrics; - } - - else { - attributes = dimensions; - } - } - - else { - attributes = metrics; - } - - return withClause + "SELECT " + attributes + " FROM " + view.name + sort + ";"; - } - - /** - * Translates a view to a SQL sub-query. The main diffence between - * this method and getQueryFromView is that a sub-query cannot have - * sorting properties. Also a sub-query is called a partial and - * partials can only have one metric. - * @param view - View which the partial will be built. - */ - private buildPartials(view: View): QNMap { - let op = view.operation; - let queue: View[] = op.values.map((i) => i); - const output: QNMap = {}; - output[view.name] = { - query: this.operation(op, view), - name: view.name - }; - - const map: {[key: string]: boolean } = {}; - - while (queue.length > 0) { - const partial = queue.shift(); - if (!map[partial.id]) { - const query = this.operation(partial.operation, partial); - if (query !== "") { - map[partial.id] = true; - if (!output[partial.name]) { - output[partial.name] = { - query: query, - name: partial.name - }; - } - queue = queue.concat(partial.operation.values); - } - } - } - - return output; - } - - /** - * Constructs a query from a view based in a given operation - * @param op - Operation used to construct the view. - * @param view - View to be querified. - */ - private operation(op: Operation, view: View): string { - switch (op.opcode) { - case Opcode.REDUCE: - return this.buildOperation(view, op.values, false); - case Opcode.JOIN: - return this.buildOperation(view, op.values, true); - default: - // Is unnecessary make a push function. Push = materialized - // No need for materialized partials - return ""; - } - } - - /** - * Constructs a query to a expecific view, from a set of given partials. - * @param view - View to be built. - * @param partials - Partials (other views) required to built the view. - * @param isJoin - Used to check if join clauses must be added. - */ - private buildOperation(view: View, partials: View[], isJoin: boolean): string { - // Mapping, which views the metrics and dimensions are - const mapping = this.buildMaps(partials); - // Projection - const metrics = view.metrics.map((i) => { - const sourceView = mapping.views[i.name]; - return this.translateMetric(i, sourceView); - }); - const dimensions = view.dimensions.map((dimension) => { - let dim = dimension; - while (!mapping.views[dim.name]) { - dim = dim.parent; - } - const sourceView = mapping.views[dim.name]; - return this.translateDimension(dimension, dim, sourceView); - }); - const projElem = dimensions.map((i) => i.aliased).concat(metrics); - - // Grouping - const grouped = dimensions.map((item) => { - return (item.expanded) ? item.alias : item.noalias; - }); - - // Selection - const conds = []; - const clauses = this.orphanClauses(view, partials); - for (let i = 0; i < clauses.length; ++i) { - const trClause = this.translateClause(clauses[i], mapping.views); - if (trClause) { - conds.push("(" + trClause + ")"); - } - } - - // Joinning - if (isJoin) { - const dimMap = mapping.dimensions; - for (let i of Object.keys(dimMap)) { - if (dimMap[i].views.length > 1) { - const views = dimMap[i].views; - const dim = dimMap[i].dim; - const leftSide = this.buildColumn(dim, views.shift().name); - while (views.length > 0) { - const rightSide = this.buildColumn(dim, views.shift().name); - conds.push("(" + leftSide + "=" + rightSide + ")"); - } - } - } - } - - // Assembly - const projection = "SELECT " + projElem.join(", "); - const sources = "FROM " + partials.map((i) => (i.name)).join(", "); - const selection = (conds.length > 0) ? " WHERE " + conds.join(" AND ") : ""; - - let grouping = ""; - if (grouped.length > 0) { - grouping = " GROUP BY " + grouped.join(","); - } - - return projection + sources + selection + grouping; - } - - /** - * Constructs and returns the dictionaries which inform - * in which views a given dimension is. - * @param views - Set of views to be scored. - */ - private buildMaps(views: View[]): DimAndNameMap { - let dimMap: {[key: string]: DimInfo} = {}; - let nameMap: {[key: string]: View} = {}; - - for (let i = 0; i < views.length; ++i) { - const mets = views[i].metrics; - const dims = views[i].dimensions; - for (let j = 0; j < mets.length; ++j) { - if (!nameMap[mets[j].name]) { - nameMap[mets[j].name] = views[i]; - } - - } - - for (let j = 0; j < dims.length; ++j) { - if (!dimMap[dims[j].name]) { - dimMap[dims[j].name] = { - dim: dims[j], - views: [views[i]] - }; - nameMap[dims[j].name] = views[i]; - } - - else { - dimMap[dims[j].name].views.push(views[i]); - } - } - } - - return { - dimensions: dimMap, - views: nameMap - }; - } - - /** - * Returns a set o clauses of the given view that is not fulfilled - * by any of the partials. In other words, clauses that has not been - * added to the query yet. - * @param view - View with all clauses. - * @param partials - Views with some of the clauses. - */ - private orphanClauses(view: View, partials: View[]): Clause[] { - let parentClauses: Clause[] = []; - for (let i = 0; i < partials.length; ++i) { - parentClauses = parentClauses.concat(partials[i].clauses); - } - - // return clauses that does not exist in the partials - return view.clauses.filter((i) => !parentClauses.some((j) => j.id === i.id)); - } - - /** - * Parse a BlenDB enumeration of agregation functions to a proper string - * to be used in the SQL query. - * @param aggrType - Aggregation function. - * @param origin - Will be applied in a view with origin flag ? - */ - private getAggregateFunction(aggrType: AggregationType, origin: boolean): string { - switch (aggrType) { - case AggregationType.SUM: - return "SUM"; - case AggregationType.AVG: - return "AVG"; - case AggregationType.COUNT: - return (origin) ? "COUNT" : "SUM"; - case AggregationType.MAX: - return "MAX"; - case AggregationType.MIN: - return "MIN"; - default: - return ""; - } - - } - - /** - * Parse a BlenDB enumeration of relationships to a proper string - * to be used in the SQL query. - * @param relation - The realtion function that will be used. - * @param arg - The attribute that is the function argument. - */ - private translateRelation(relation: RelationType, arg: string): string { - switch (relation) { - case RelationType.DAY: - return this.applyRelation("EXTRACT", ["DAY FROM "], [arg]); - case RelationType.MONTH: - return this.applyRelation("EXTRACT", ["MONTH FROM "], [arg]); - case RelationType.YEAR: - return this.applyRelation("EXTRACT", ["YEAR FROM "], [arg]); - default: - return ""; - } - - } - - /** - * Generic translate a SQL function to a query - * @param name - Function name. - * @param args - Function argument names. - * @param values - Function argument values. - */ - private applyRelation(name: string, args: string[], values: string[]): string { - /* - This adapter uses the concept of functions in Postgres to - implement BLENDB sub-dimention relations, this functions - applys the transformation to build the call of a Postgres - funtion. Note that this function can be native from postgres, - like EXTRACT, or even implemented on the database. - This function is short and only used in the translateRelation - method however is a bit complex and is possible to be used - several times, because of that is puted appart to make easyer update - and avoid problems - Example - applyRelation ("EXTRACT", "["DAY FROM"]", ["view_0.date"]) - output: EXTRACT(DAY FROM view_0.date) - */ - return name + "(" + args.map((item, idx) => item + values[idx]).join(",") + ")"; - } - - /** - * Add quotes and the proper view name to a attribute in a SQL query. - * @param item - Attribute to get the name quoted. - * @param viewName - View name used to build the view name. - */ - private buildColumn (item: Metric|Dimension, viewName: string): string { - const quotedName = "\"" + item.name + "\""; - return viewName + "." + quotedName; - } - - /** - * Translate Clause object into a SQL query condition. - * @param clause - Clause to be translated. - * @param map - Dictionary indexed bu attributes name - * containing its locations. - */ - private translateClause(clause: Clause, map: {[key: string]: View}): string { - const r = clause.filters.map((item) => { - return this.translateFilter(item, map); - }).filter((item) => { - return item !== ""; - }); - return r.join(" OR "); - } - - /** - * Translate Filter object into a SQL query condition. - * @param filter - Filter to be translated. - * @param map - Dictionary indexed bu attributes name - * containing its locations. - */ - private translateFilter(filter: Filter, map: {[key: string]: View}): string { - if (!map[filter.target.name]) { - return ""; - } - - const viewName = map[filter.target.name].name; - const leftSide = this.buildColumn(filter.target, viewName); - const quotedValue = "'" + filter.value + "'"; - const castedValue = this.typeCast(quotedValue, filter.target.dataType); - return this.applyOperator(leftSide, castedValue, filter.operator); - } - - /** - * Translate Metric object into a SQL query attribute. - * @param metric - Metric to be translated. - * @param view - View which contains the metric. Used to create the name - */ - private translateMetric(metric: Metric, view: View): string { - const func = this.getAggregateFunction(metric.aggregation, view.origin); - const quotedName = "\"" + metric.name + "\""; - const extMetric = func + "(" + this.buildColumn(metric, view.name) + ")"; - return extMetric + " AS " + quotedName; - } - - /** - * Translate Dimension object into a SQL query attribute. - * @param dimension - Dimension to be translated. - * @param ancestor - Dimension ancestor found in the view - * @param view - View which contains the dimenion/ancestor. - * Used to create the name. - */ - private translateDimension(dimension: Dimension, - ancestor: Dimension, - view: View): DimTranslation { - const quotedName = "\"" + dimension.name + "\""; - let extDimension = this.buildColumn(ancestor, view.name); - let aux = dimension; - let expanded = false; - while (aux.name !== ancestor.name) { - extDimension = this.translateRelation(aux.relation, extDimension); - aux = aux.parent; - expanded = true; - } - return { - aliased: extDimension + " AS " + quotedName, - noalias: extDimension, - alias: quotedName, - expanded: expanded - }; - } - - /** - * Generates a generic insertion query for one register. - * @param source - Data insertion "location". - * @param data - Data to be inserted. - */ - public getQueryFromSource(source: Source, data: any[]): string { - let consult: string; - let colums: any[] = []; - let values: string[] = []; - let tam = Object.keys(data).length; - colums = source.fields.map(o => o.name); - for (let i = 0; i < tam; i++){ - values[i] = data[colums[i]]; - } - consult = "INSERT INTO " + source.name + " (\""; - consult = consult.concat(colums.join("\",\"")); - consult = consult.concat("\") VALUES ('"); - consult = consult.concat(values.join("' , '")); - consult = consult.concat("')"); - - return consult; - } - - /** - * Parse a filter operation. Varies in each database. - * @param lSide - Operation left side operator. - * @param rSide - Operation right side operator. - * @param op - Operation to be performed. - */ - protected abstract applyOperator(leftSide: string, rightSide: string, op: FilterOperator): string; - /** - * Cast BlenDB types to proper database types. - * @param quotedValue - SQL query attribute wrapped by quotes. - * @param dt - Attribute data type. - */ - protected abstract typeCast(quotedValue: string, dt: DataType): string; -} diff --git a/src/api/controllers/collect.spec.ts b/src/api/controllers/collect.spec.ts index 355152e0008354e6a5066cf86e302153b05368c9..958196db90dbc26854be8d8b37959ca7a0e980d2 100644 --- a/src/api/controllers/collect.spec.ts +++ b/src/api/controllers/collect.spec.ts @@ -20,339 +20,37 @@ import * as request from "supertest"; import { expect } from "chai"; -import * as server from "../../main"; -import { Adapter } from "../../core/adapter"; -import { ConfigParser, ParsedConfig } from "../../util/configParser"; -import { Fixture as FixPostgres } from "../../../test/postgres/fixture"; -import { Fixture as FixMonet } from "../../../test/monet/fixture"; -import { MonetAdapter, MonetConfig } from "../../adapter/monet"; -import { PostgresAdapter } from "../../adapter/postgres"; -import { eachOf } from "async"; -import { Source } from "../../core/source"; - -let adapter: Adapter[] = []; -let fixture; -let config: ParsedConfig; - -function loadDb(db: string, index: number, cb: (err: any, result: Adapter) => void): void { - let adapter: Adapter; - if (db === "postgres") { - fixture = new FixPostgres(config.connections[index]); - fixture.loadSource(config.sources, (err) => { - if (err) { - throw err; - } - adapter = new PostgresAdapter(config.connections[index]); - cb(null, adapter); - }); - } - else if (db === "monet") { - fixture = new FixMonet(config.connections[index]); - fixture.loadSource(config.sources, (err) => { - if (err) { - throw err; - } - let parsedConfig: MonetConfig = { - user: config.connections[index].user, - dbname: config.connections[index].database, - password: config.connections[index].password, - host: config.connections[index].host, - port: config.connections[index].port - }; - adapter = new MonetAdapter(parsedConfig); - cb(null, adapter); - }); - } - else{ - cb("invalid adapter", null); - } -} +import * as server from "../../main"; describe("API collect controller", () => { - // Initializing - before(function (done): void { - // Arrow function not used to get acces to this and skip the test - let configPath; - - if(process.env.BLENDB_SCHEMA_FILE){ - configPath = process.env.BLENDB_SCHEMA_FILE; - } - else{ - throw new Error("BLENDB_SCHEMA_FILE wasn't informed"); - } - config = ConfigParser.parse(configPath); - - eachOf(config.adapters , function(database, key: number, callback) { - loadDb(database, key, function(err, result ) { - if (err){ - return callback(err); - } - else{ - adapter[key] = result; - } - callback(); - }); - }, function (err){ - if (err){ - this.skip(); - } - else{ - done(); - } - }); - }); - it("should respond 500 when req.params.class does not exist on Sources", (done) => { - request(server) - .post("/v1/collect/thisisjustatest") - .send({"fields:1": 1, "fields:2": 2}) - .expect(500) - .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Engine Error] Required Source: 'thisisjustatest' do not exist in the database."+ - " Check source spelling and database configuration."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - - }) - .end(done); - }); - it("should respond 500 when name does not exist in Product from market", (done) => { - request(server) - .post("/v1/collect/Product") - .send({ - "pricein": 17.51, - "priceout": 30.55, - "validity": "2018-05-16", - "id": 5 - }) - .expect(500) - .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] 'name' is mandatory, but no data was received."+ - " Review the data sent."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - }) - .end(done); - }); - it("should respond 200 when data has been stored on Product", (done) => { + it("should respond 400 when _id field is in request body", (done) => { request(server) - .post("/v1/collect/Sell") - .send({ - "Registered": false, - "Product.id": 1, - "Client.id": 1, - "Seller.id": 3, - "Quantity": 10, - "Datein" : "2017-10-30" - }) - .expect(200) + .post("/v1/collect/class") + .send({"_id": 1}) + .expect(400) .expect((res: any) => { - const message = "Data has been successfully received and stored by the server"; + const message = "Property named \"_id\" is protected."; expect(res.body).to.be.an("object"); expect(res.body).to.have.property("message"); expect(res.body.message).to.be.eql(message); - }) .end(done); }); - it("should respond 500 when value isn't defined on enumtype ", (done) => { - request(server) - .post("/v1/collect/Seller") - .send({ - "name": "radom", - "age" : 25, - "sex" : "thisisjustatest", - "CPF" : "145.827.483-76", - "id" : 4 - }) - .expect(500) - .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] EnumType: 'thisisjustatest' from 'sex' isn't allowed on enumsex." - + " Review configuration files." - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - }) - .end(done); - }); - it("should respond 500 when dataType from id isn't integer", (done) => { + it("should respond 500 on error on writing in the database", (done) => { request(server) - .post("/v1/collect/Product") - .send({ - "name":"strategy", - "pricein": 17.51, - "priceout": 30.55, - "validity": "1991-05-16", - "id": "nope" - }) + .post("/v1/collect/class") + .send({"field1": 1, "field2": 2}) .expect(500) .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: 'nope' from 'id' could not be converted to type: integer."+ - " Review configuration files." + const message = "Error while writing to the database."; expect(res.body).to.be.an("object"); expect(res.body).to.have.property("message"); expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); }) .end(done); }); - it("should respond 500 when dataType from pricein isn't float", (done) => { - request(server) - .post("/v1/collect/Product") - .send({ - "name": "strategy", - "pricein": "notafloat", - "priceout": 30.55, - "validity": "1991-05-16", - "id": 5 - }) - .expect(500) - .expect((res: any) => { - - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: 'notafloat' from 'pricein' could not be converted to type: float." + - " Review configuration files." - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - }) - .end(done); - }); - it("should respond 500 when dataType from name isn't string", (done) => { - request(server) - .post("/v1/collect/Client") - .send({ - "name": 5, - "CPF" : "500.345.583-65", - "id" : 5 - }) - .expect(500) - .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: '5' from 'name' could not be converted to type: string."+ - " Review configuration files."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - }) - .end(done); - }); - it("should respond 500 when dataType from fields:3 isn't boolean", (done) => { - request(server) - .post("/v1/collect/Sell") - .send({ - "Registered": "notaboolean", - "Product.id": 1, - "Client.id": 9, - "Seller.id": 12, - "Quantity": 50, - "Datein" : "1980-01-30" - }) - .expect(500) - .expect((res: any) => { - - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: 'notaboolean' from 'Registered' could not be converted to type: boolean."+ - " Review configuration files."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - - }) - .end(done); - }); - it("should respond 500 when the first dataType from Datein isn't a valid date", (done) => { - request(server) - .post("/v1/collect/Sell") - .send({ - "Registered": "true", - "Product.id": 9, - "Client.id": 6, - "Seller.id": 8, - "Quantity": 23, - "Datein" : "1999-25-25" - }) - .expect(500) - .expect((res: any) => { - - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: '1999-25-25' from 'Datein' could not be converted to type: date." + - " Review configuration files."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - - }) - .end(done); - }); - it("should respond 500 when the first dataType from Datein isn't a valid format date", (done) => { - request(server) - .post("/v1/collect/Sell") - .send({ - "Registered": "true", - "Product.id": 5, - "Client.id": 16, - "Seller.id": 13, - "Quantity": 7, - "Datein" : "1999/12/12" - }) - .expect(500) - .expect((res: any) => { - - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Collect error] Datatype: '1999/12/12' from 'Datein' could not be converted to type: date."+ - " Review configuration files."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - - }) - .end(done); - }); - it("should respond 200 when data has been stored on Seller", (done) => { - request(server) - .post("/v1/collect/Seller") - .send({ - "name": "radom", - "age" : 25, - "sex" : "male", - "CPF" : "145.827.483-76", - "id" : 4 - }) - .expect(200) - .expect((res: any) => { - const message = "Data has been successfully received and stored by the server"; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body.message).to.be.eql(message); - - }) - .end(done); - }); }); diff --git a/src/api/controllers/collect.ts b/src/api/controllers/collect.ts index 3e0680885c8df42f2232e4e5f66bb61756dc5495..a273be52624a964fb57ccc8dcd158d6f9ff265fc 100644 --- a/src/api/controllers/collect.ts +++ b/src/api/controllers/collect.ts @@ -19,184 +19,16 @@ */ import * as express from "express"; -import { Request } from "../types"; -import { Source, Field } from "../../core/source"; -import { EnumType } from "../../core/enumType"; -import { DataType } from "../../common/types"; -import { EnumHandler } from "../../util/enumHandler"; -/** - * Dictionary indexed by a type name which return a - * validation function that returns true if the - * objetct is a valid object of that type - * or false otherwise. - */ -interface Valid{ - [key: string]: (value: any) => boolean; -} - -/** - * Constroller responsable for collect part from the API. In other - * words, controller responsable for inserting data in BlenDB. - */ export class CollectCtrl { - /** - * Route that validates and insert data. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - public static write(req: Request, res: express.Response, next: express.NextFunction) { - - const validador: Valid = { - "integer": function(value: any) { - let test = parseInt(value, 10); - if (test === undefined || isNaN(value) ) { - return false; - } - - else { - return true; - } - }, - "float": function(value: any) { - let test = parseFloat(value); - if (test === undefined || isNaN(value) ) { - return false; - } - - else { - return true; - } - }, - "string": function(value: any) { - let test = typeof(value); - if (test === "string") { - return true; - } - - else{ - return false; - } - }, - "date": function(value: any) { - - let test: string[] = []; - let date = new Date(value); - try { - test = date.toISOString().split("T"); - } - catch (e) { - return false; - } - if (test[0] === value){ - return true; - } - else{ - return false; - } - - }, - "boolean": function(value: any) { - let test = typeof(value); - if(test === "boolean"){ - return true; - }else{ - let test: string = value; - test = test.toLocaleLowerCase(); - if (test === "true" || test === "false"){ - return true; - }else{ - return false; - } - } - } - }; - - let fields: Field[] = []; - let data: string[] = []; - let types: string[] = []; - let source: Source; - let enumType: EnumType; - - const id: string = req.params.class; - try { - source = req.engine.getSourceByName(id); - // If source does not exist them return error - - fields = source.fields; - - for (let i = 0; i < fields.length; i++){ - data[i] = req.body[fields[i].name]; - // check if the data is empty, however since data may be - // true/false, it must guarantee that it isn't a boolean - // then it'll test if it's empty - if (!(typeof(data[i]) === "boolean") && !data[i]){ - const message = "[Collect error] '" + fields[i].name + - "' is mandatory, but no data was received. Review the data sent." - throw new Error(message); - } - req.log.debug("Sucessfuly accepted the data: " + data[i] + " from source: ",source.name); - } - - for (let i = 0; i < fields.length; i++){ - // check if it's a valid enumtype - if (fields[i].dataType === DataType.ENUMTYPE){ - enumType = req.engine.getEnumTypeByName(fields[i].enumType); - types = enumType.values; - let found: boolean = false; - for (let j = 0; j < types.length; j++){ - if (data[i] === types[j]){ - found = true; - break; - } - } - if (!found) { - const message = "[Collect error] EnumType: '" + data[i] + "' from '" + fields[i].name + - "' isn't allowed on " + fields[i].enumType + - ". Review configuration files." - throw new Error(message); - } - }else if (!validador[EnumHandler.stringfyDataType(fields[i].dataType)](data[i]) === true){ - const message = "[Collect error] Datatype: '" + data[i] + "' from '" + fields[i].name + - "' could not be converted to type: " + [EnumHandler.stringfyDataType(fields[i].dataType)] + - ". Review configuration files." - throw new Error(message); - } - req.log.debug("Sucessfuly accepted the enumType data: " + data[i] + " from source: ",source.name); - } - } - - catch (e) { - const message = "Query execution failed: " + - "Could not construct query with the given parameters." - req.log.warn(message); - res.status(500).json({ - message: message, - error: e.message - }); + public static write(req: express.Request, res: express.Response, next: express.NextFunction) { + if ("_id" in req.body) { + res.status(400) + .json({ message: "Property named \"_id\" is protected." }); return; } - req.adapter.insertIntoSource(source, req.body, (err: Error, result: any[]) => { - if (err) { - const message = "Insertion has failed"; - req.log.error(message,err); - res.status(500).json({ - message: message, - error: err - }); - return; - } - else{ - const message = "Data has been successfully received and stored by the server"; - req.log.info(message); - res.status(200).json({message: message}); - return; - } - - }); - + res.status(500) + .json({ message: "Error while writing to the database." }); } } diff --git a/src/api/controllers/data.spec.ts b/src/api/controllers/data.spec.ts index ab7865bf387ead6ed4e1427ae509472d945012e3..5cf78079cdf2b0e85ef8479b6b69e12dca38416f 100644 --- a/src/api/controllers/data.spec.ts +++ b/src/api/controllers/data.spec.ts @@ -20,18 +20,15 @@ import * as request from "supertest"; import { expect } from "chai"; + import * as server from "../../main"; import { dataCtrlScenario as tests } from "../../../test/scenario"; import { Query } from "../../common/query"; -import { waterfall } from "async"; -import * as fs from "fs"; interface StrQuery { metrics: string; dimensions: string; filters?: string; - sort?: string; - format?: string; } function parseQuery(obj: Query): StrQuery { @@ -54,9 +51,8 @@ describe("API data controller", () => { .expect(500) .expect((res: any) => { const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Engine Error] Metric: 'met:this:is:just:a:test' do not exist in the database." + - " Check metric spelling and database configuration."; + "Could not construct query with the paramters given."; + const error = "The metric named met:-1 was not found"; expect(res.body).to.be.an("object"); expect(res.body).to.have.property("message"); expect(res.body).to.have.property("error"); @@ -73,30 +69,8 @@ describe("API data controller", () => { .expect(500) .expect((res: any) => { const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "[Engine Error] Dimension: 'dim:this:is:just:a:test' do not exist in the database."+ - " Check dimension spelling and database configuration."; - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("message"); - expect(res.body).to.have.property("error"); - expect(res.body.message).to.be.eql(message); - expect(res.body.error).to.be.eql(error); - }) - .end(done); - }); - - it("should respond 500 when query has sort item that is not in query data", (done) => { - let query = parseQuery(tests.clausal); - query.sort = "dim:does:not:exist"; - request(server) - .get("/v1/data") - .query(query) - .expect(500) - .expect((res: any) => { - const message = "Query execution failed: " + - "Could not construct query with the given parameters."; - const error = "The item 'dim:does:not:exist'" + - " is not present in neither metrics nor dimensions list"; + "Could not construct query with the paramters given."; + const error = "The dimension named dim:-1 was not found"; expect(res.body).to.be.an("object"); expect(res.body).to.have.property("message"); expect(res.body).to.have.property("error"); @@ -128,8 +102,10 @@ describe("API data controller", () => { }); it("should respond 200 and get some data, using a single filter", (done) => { + // Clause does not come to scenario besause is a lot of work for + // only a single test let query = parseQuery(tests.clausal); - query.filters = "dim:product:name==Bacon"; + query.filters = "dim:7==1"; request(server) .get("/v1/data") .query(query) @@ -151,8 +127,10 @@ describe("API data controller", () => { }); it("should respond 200 and get some data, using filters with OR", (done) => { + // Clause does not come to scenario besause is a lot of work for + // only a single test let query = parseQuery(tests.clausal); - query.filters = "dim:product:name==Trento,dim:product:name==Meat"; + query.filters = "dim:7==1,dim:7==2"; request(server) .get("/v1/data") .query(query) @@ -174,77 +152,10 @@ describe("API data controller", () => { }); it("should respond 200 and get some data, using filters with AND", (done) => { + // Clause does not come to scenario besause is a lot of work for + // only a single test let query = parseQuery(tests.clausal); - query.filters = "dim:product:name!=Bacon;dim:product:validity!=2018-05-10"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(3); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(tests.clausal.metrics.map((item) => item.name)); - keys = keys.concat(tests.clausal.dimensions.map((item) => item.name)); - result.forEach((row: any) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - }) - .end(done); - }); - it("should respond 200 and get some data, sorted", (done) => { - let query = parseQuery(tests.clausal); - query.sort = "dim:product:id,met:product:avg:pricein"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(tests.clausal.metrics.map((item) => item.name)); - keys = keys.concat(tests.clausal.dimensions.map((item) => item.name)); - for (let i = 0; i < result.length; ++i) { - const row = result[i]; - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - // the magic number will be the first dim:product:id - expect(row["dim:product:id"]).to.be.eql(i + 53); - } - }) - .end(done); - }); - it("should respond 200 and get some data, using filters with GREATER", (done) => { - let query = parseQuery(tests.clausal); - query.filters = "dim:product:id>55"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(2); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(tests.clausal.metrics.map((item) => item.name)); - keys = keys.concat(tests.clausal.dimensions.map((item) => item.name)); - result.forEach((row: any) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - }) - .end(done); - }); - it("should respond 200 and get some data, using filters with LOWEREQ", (done) => { - let query = parseQuery(tests.clausal); - query.filters = "dim:product:id<=55"; + query.filters = "dim:7!=1;dim:0!=2017-01-01"; request(server) .get("/v1/data") .query(query) @@ -252,7 +163,7 @@ describe("API data controller", () => { .expect((res: any) => { let result = res.body; expect(result).to.be.an("array"); - expect(result).to.have.length(3); + expect(result).to.have.length(4); expect(result[0]).to.be.an("object"); let keys: string[] = []; keys = keys.concat(tests.clausal.metrics.map((item) => item.name)); @@ -263,119 +174,6 @@ describe("API data controller", () => { }); }) .end(done); - }); - it("should respond 200 and get some data, using filters with default", (done) => { - let query = parseQuery(tests.seller); - query.filters = "dim:sell:registered==false"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(1); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(tests.seller.metrics.map((item) => item.name)); - keys = keys.concat(tests.seller.dimensions.map((item) => item.name)); - result.forEach((row: any) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - }) - .end(done); }); - it("should respond 200 and get some data, using filters with default", (done) => { - let query = parseQuery(tests.expensive); - query.sort = "met:product:max:pricein" - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(5); - expect(result[0]).to.be.an("object"); - let keys: string[] = []; - keys = keys.concat(tests.expensive.metrics.map((item) => item.name)); - keys = keys.concat(tests.expensive.dimensions.map((item) => item.name)); - result.forEach((row: any) => { - expect(row).to.be.an("object"); - expect(row).to.have.all.keys(keys); - }); - }) - .end(done); - }); - - it("should respond 200 and get some data with format as csv", (done) => { - waterfall([(cb: (err: Error, data: string) => void) => { - fs.readFile("test/files/data.csv", "utf8", (err, data) => { - cb(err, data); - }); - } - , (file: string, cb: (err: Error) => void) => { - let query = parseQuery(tests.csv); - query.format = "csv"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - expect(res.text).to.be.eql(file); - }) - .end(cb); - }], (err) => { - expect(err).to.be.eql(null); - done(); - }); - }); - - it("should respond 200 and get some data with format as ssv", (done) => { - waterfall([(cb: (err: Error, data: string) => void) => { - fs.readFile("test/files/data.ssv", "utf8", (err, data) => { - cb(err, data); - }); - } - , (file: string, cb: (err: Error) => void) => { - let query = parseQuery(tests.csv); - query.format = "ssv"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - expect(res.text).to.be.eql(file); - }) - .end(cb); - }], (err) => { - expect(err).to.be.eql(null); - done(); - }); - }); - - it("should respond 200 and get some data with format as tsv", (done) => { - waterfall([(cb: (err: Error, data: string) => void) => { - fs.readFile("test/files/data.tsv", "utf8", (err, data) => { - cb(err, data); - }); - } - , (file: string, cb: (err: Error) => void) => { - let query = parseQuery(tests.csv); - query.format = "tsv"; - request(server) - .get("/v1/data") - .query(query) - .expect(200) - .expect((res: any) => { - expect(res.text).to.be.eql(file); - }) - .end(cb); - }], (err) => { - expect(err).to.be.eql(null); - done(); - }); - }); }); diff --git a/src/api/controllers/data.ts b/src/api/controllers/data.ts index 2dbd01b6d9bdf0775c02709f29029cff78f5d9ff..83046981de443ed885c28bed8098f6d915576601 100644 --- a/src/api/controllers/data.ts +++ b/src/api/controllers/data.ts @@ -20,42 +20,22 @@ import * as express from "express"; import { Request } from "../types"; -import { Query, QueryOpts } from "../../common/query"; +import { Query } from "../../common/query"; -/** - * Constroller responsable for data part from the API. In other - * words, controller responsable for reading data in BlenDB. - */ export class DataCtrl { - /** - * Route that validates a query and returns the query data. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ + /* divides the URL in metrics, dimensions and filters */ public static read(req: Request, res: express.Response, next: express.NextFunction) { - req.log.info("Query: ",req.query); - let metrics = req.query.metrics.split(",").filter((item: string) => item !== ""); - let dimensions = req.query.dimensions.split(",").filter((item: string) => item !== ""); - let clauses = []; - let sort: string[] = []; + let metrics = req.query.metrics.toString().split(",").filter((item: string) => item !== ""); + let dimensions = req.query.dimensions.toString().split(",").filter((item: string) => item !== ""); + let clauses: string | any[] = []; if (req.query.filters) { - clauses = req.query.filters.split(";").filter((item: string) => item !== ""); - } - if (req.query.sort) { - sort = req.query.sort.split(",").filter((item: string) => item !== ""); + clauses = req.query.filters.toString().split(";").filter((item: string) => item !== ""); } - let format = "json"; - if (req.query.format) { - format = req.query.format; - } - let view; + /* validates metrics, dimensions and filters */ try { - const qOpt: QueryOpts = { metrics: [], dimensions: []}; - let query = new Query(qOpt); + let query: Query = { metrics: [], dimensions: [], clauses: [] }; for (let i = 0; i < metrics.length; ++i) { query.metrics.push(req.engine.getMetricByName(metrics[i])); } @@ -67,75 +47,30 @@ export class DataCtrl { for (let i = 0; i < clauses.length; ++i) { query.clauses.push(req.engine.parseClause(clauses[i])); } - - for (let i = 0; i < sort.length; ++i) { - const m = query.metrics.find((item) => item.name === sort[i]); - if (!m) { - const d = query.dimensions.find((item) => item.name === sort[i]); - if (!d) { - throw new Error( - "The item '" + sort[i] + - "' is not present in neither metrics nor dimensions list"); - } - else { - query.sort.push(d); - } - } - - else { - query.sort.push(m); - } - - } view = req.engine.query(query); } catch (e) { - const message = "Query execution failed: " + - "Could not construct query with the given parameters." - req.log.warn(message,e); res.status(500).json({ - message: message, + message: "Query execution failed: " + + "Could not construct query with the paramters given.", error: e.message }); return; } - + /* call the adapter to acess the DB */ req.adapter.getDataFromView(view, (err: Error, result: any[]) => { if (err) { - const message = "Query execution failed " + - "failed on execute query on database." - req.log.error(message,err); res.status(500).json({ - message: message, + message: "Query execution failed " + + "failed on execute query on database.", error: err }); return; } - - if (format === "json") { - req.log.info("Response (json) send with success"); - res.status(200).json(result); - } - - else { - req.csvParser(result, format, (error: Error, csv: string) => { - if (error) { - const message = "Error generating csv file. " + - "Try json format." - req.log.error(message,error); - res.status(500).json({ - message: message, - error: error - }); - return; - } - - req.log.info("Response (csv) send with success"); - res.setHeader("Content-Type", "text/csv"); - res.setHeader("Content-disposition", "attachment;filename=data.csv"); - res.status(200).send(csv); - }); - } + res.setHeader('Access-Control-Allow-Origin','*'); + res.setHeader('Access-Control-Allow-Methods','*'); + res.setHeader('Access-Control-Allow-Headers','*'); + res.status(200).json(result); return; }); } diff --git a/src/api/controllers/engine.spec.ts b/src/api/controllers/engine.spec.ts index ee086ea233db5e9087a43526a1c4c24038947156..dc436712347eafbb1f57da91512ac50c7b5e141d 100644 --- a/src/api/controllers/engine.spec.ts +++ b/src/api/controllers/engine.spec.ts @@ -19,10 +19,9 @@ */ import * as request from "supertest"; -import * as fs from "fs"; import { expect } from "chai"; + import * as server from "../../main"; -import { waterfall } from "async"; describe("API engine controller", () => { @@ -33,21 +32,11 @@ describe("API engine controller", () => { .expect((res: any) => { let result = res.body; expect(result).to.be.an("array"); - expect(result).to.have.length(16); - }) - .end(done); - }); - it("should respond 200 and the list of sources", (done) => { - request(server) - .get("/v1/sources") - .expect(200) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(8); + expect(result).to.have.length(12); }) .end(done); }); + it("should respond 200 and the list of dimensions", (done) => { request(server) .get("/v1/dimensions") @@ -55,73 +44,7 @@ describe("API engine controller", () => { .expect((res: any) => { let result = res.body; expect(result).to.be.an("array"); - expect(result).to.have.length(19); - }) - .end(done); - }); - it("should respond 200 and the list of enumTypes", (done) => { - request(server) - .get("/v1/enumtypes") - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(3); - }) - .end(done); - }); - - it("should respond 200 and the list of tags", (done) => { - request(server) - .get("/v1/tags") - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(8); - }) - .end(done); - }); - - it("should respond 200 and the list of metrics (in ssv)", (done) => { - waterfall([(cb: (err: Error, data: string) => void) => { - fs.readFile("test/files/metrics.csv", "utf8", (err, data) => { - cb(err, data); - }); - } - , (file: string, cb: (err: Error) => void) => { - request(server) - .get("/v1/metrics") - .query({format: "ssv"}) - .expect(200) - .expect((res: any) => { - expect(res.text).to.be.eql(file); - }) - .end(cb); - }], (err) => { - expect(err).to.be.eql(null); - done(); - }); - }); - - it("should respond 200 and the filtered list of metrics", (done) => { - request(server) - .get("/v1/metrics") - .query({tags: "seller,buyout"}) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(7); - }) - .end(done); - }); - - it("should respond 200 and the filtered list of dimensions", (done) => { - request(server) - .get("/v1/dimensions") - .query({tags: "seller"}) - .expect((res: any) => { - let result = res.body; - expect(result).to.be.an("array"); - expect(result).to.have.length(1); + expect(result).to.have.length(13); }) .end(done); }); diff --git a/src/api/controllers/engine.ts b/src/api/controllers/engine.ts index 998c14e3bf645e892f9bdfd8f7352d1c2bff8aa7..18de1e1a4252ecfed38bf340af6fe67a21b2f6fe 100644 --- a/src/api/controllers/engine.ts +++ b/src/api/controllers/engine.ts @@ -21,109 +21,12 @@ import * as express from "express"; import { Request } from "../types"; -/** - * Constroller responsable for the static part from the API. In other - * words, controller responsable for return the meta data stored in the - * engine object that API users can use to create queries. - */ export class EngineCtrl { - /** - * Auxiliary function that returns engine information. - * @param list - List of objects to return - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - private static respondList(list: any[], fileName: string, req: Request, res: express.Response, next: express.NextFunction) { - let format = "json"; - if (req.query.format) { - format = req.query.format; - } - - if (format === "json") { - req.log.info("Response (json) send with success"); - res.status(200).json(list); - } - - else { - req.csvParser(list, format, (error: Error, csv: string) => { - if (error) { - req.log.error("Error generating csv file: ",error); - res.status(500).json({ - message: "Error generating csv file. " + - "Try json format.", - error: error - }); - return; - } - - const disposition = "attachment;filename=" + fileName + ".csv"; - req.log.info("Response (csv) send with success"); - res.setHeader("Content-Type", "text/csv"); - res.setHeader("Content-disposition", disposition); - res.status(200).send(csv); - }); - } - } - - /** - * Route that returns the list of available metrics. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ public static metrics(req: Request, res: express.Response, next: express.NextFunction) { - const metrics = req.engine.getMetricsDescription(req.query.tags); - EngineCtrl.respondList(metrics, "metrics", req, res, next); - } - - /** - * Route that returns the list of available dimensions. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - public static dimensions(req: Request, res: express.Response, next: express.NextFunction) { - const dimensions = req.engine.getDimensionsDescription(req.query.tags); - EngineCtrl.respondList(dimensions, "dimensions", req, res, next); - } - - /** - * Route that returns the list of available enumerable types. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) { - const enumTypes = req.engine.getEnumTypesDescription(); - EngineCtrl.respondList(enumTypes, "enums", req, res, next); - } - - /** - * Route that returns the list of available data sources for insertion. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - public static sources(req: Request, res: express.Response, next: express.NextFunction) { - const sources = req.engine.getSourcesDescription(); - EngineCtrl.respondList(sources, "sources", req, res, next); + res.status(200).json(req.engine.getMetricsDescription()); } - /** - * Route that returns the list of available tags. - * @param req - Object with request information - * @param res - Object used to create and send the response - * @param next - Call next middleware or controller. Not used but required - * by typescript definition of route. - */ - public static tags(req: Request, res: express.Response, next: express.NextFunction) { - const tags = req.engine.getTagsDescription(); - EngineCtrl.respondList(tags, "tags", req, res, next); + public static dimensions(req: Request, res: express.Response, next: express.NextFunction) { + res.status(200).json(req.engine.getDimensionsDescription()); } } diff --git a/src/api/middlewares/adapter.ts b/src/api/middlewares/adapter.ts index b8f06214f384da1af1db484a84ea065b1268587a..997f63dcbdd520fc6d40229feabc53b22d020077 100644 --- a/src/api/middlewares/adapter.ts +++ b/src/api/middlewares/adapter.ts @@ -21,50 +21,13 @@ import { Middleware } from "../types"; import { Adapter } from "../../core/adapter"; import { PostgresAdapter } from "../../adapter/postgres"; -import { MonetAdapter, MonetConfig } from "../../adapter/monet"; import { PoolConfig } from "pg"; -import { Connection } from "../../util/configParser"; -/** - * Creates a PostgreSQL adapter and middleware that - * inserts the adapter into the request objects. - * @param config - Parameters required to connect in database. - */ -export function PostgresMw(config: Connection): Middleware { - let parsedConfig: PoolConfig = { - user: config.user, - database: config.database, - password: config.password, - host: config.host, - port: config.port, - max: 10, - idleTimeoutMillis: 3000 - }; - let adapter: Adapter = new PostgresAdapter(parsedConfig); +export function PostgresMw(config: PoolConfig): Middleware { + let adapter: Adapter = new PostgresAdapter(config); return function postgresMiddleware(req, res, next) { req.adapter = adapter; next(); }; } - -/** - * Creates a MonetDB adapter and middleware that - * inserts the adapter into the request objects. - * @param config - Parameters required to connect in database. - */ -export function MonetMw(config: Connection): Middleware { - let parsedConfig: MonetConfig = { - user: config.user, - dbname: config.database, - password: config.password, - host: config.host, - port: config.port, - }; - let adapter: Adapter = new MonetAdapter(parsedConfig); - return function monetMiddleware(req, res, next) { - req.adapter = adapter; - next(); - }; - -} diff --git a/src/api/middlewares/csv.ts b/src/api/middlewares/csv.ts deleted file mode 100644 index 42540aae3cfc6d3765a40e0d6e48f1c7f289c343..0000000000000000000000000000000000000000 --- a/src/api/middlewares/csv.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015-2019 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import * as json2csv from "json-2-csv"; -import { Middleware } from "../types"; - -/** - * Creates a csv parser and middleaew that - * inserts the parser into the request objects. - */ -export function CsvMw(): Middleware { - return function csvMiddleware(req, res, next) { - req.csvParser = function parseCsv(json: any, format: string, cb) { - const separator = format.substring(0, 1); - - let sep = ","; - if (separator === "s") { - sep = ";"; - } - - else if (separator === "t"){ - sep = "\t"; - } - - json2csv.json2csv(json, cb, { - delimiter: { - field: sep - , wrap: "\"" - , eol: "\n" - } - , prependHeader: true - }); - }; - next(); - }; - -} diff --git a/src/api/middlewares/engine.ts b/src/api/middlewares/engine.ts index 6230f2b6ac423376f342269cf3ce7980ba6064bc..b6c37e0df3f27eccf23d4060f89e29f3fb9165f5 100644 --- a/src/api/middlewares/engine.ts +++ b/src/api/middlewares/engine.ts @@ -22,13 +22,12 @@ import { Engine } from "../../core/engine"; import { ParsedConfig } from "../../util/configParser"; import { Middleware } from "../types"; -/** - * Creates a engine and middleware that - * inserts the engine into the request objects. - * @param config - Parsed database schema. - */ -export function EngineMw (config: ParsedConfig): Middleware { - let engine: Engine = new Engine(config); +export function EngineMw(config: ParsedConfig): Middleware { + let engine: Engine = new Engine(); + + config.metrics.forEach((met) => engine.addMetric(met)); + config.dimensions.forEach((dim) => engine.addDimension(dim)); + config.views.forEach((view) => engine.addView(view)); return function engineMiddleware(req, res, next) { req.engine = engine; diff --git a/src/api/middlewares/error.spec.ts b/src/api/middlewares/error.spec.ts index f510594d4d8c6b304e8bd4fab14266e74acf1f9a..be9181ab3f2f90643661c91f29d940b571ed6993 100644 --- a/src/api/middlewares/error.spec.ts +++ b/src/api/middlewares/error.spec.ts @@ -53,14 +53,4 @@ describe("API error middleware", () => { }) .end(done); }); - it("should respond 400 when you connect, and do not send data", (done) => { - request(server) - .post("/v1/collect/Seller") - .expect(400) - .expect((res: any) => { - expect(res.body).to.be.an("object"); - expect(res.body).to.have.property("error"); - }) - .end(done); - }); }); diff --git a/src/api/middlewares/error.ts b/src/api/middlewares/error.ts index 1bb7f1d6c22d50e1364c66beb081ab2747f234e2..a35bb41e8b2ca7d71c18253b8b252201e6685ac7 100644 --- a/src/api/middlewares/error.ts +++ b/src/api/middlewares/error.ts @@ -20,10 +20,6 @@ import * as express from "express"; -/** - * Creates a middleware to handle errors proper to each API version. - * @param config - API version. - */ export function ErrorMw(config: string): express.ErrorRequestHandler { const handlers: { [key: string]: express.ErrorRequestHandler } = { "v1": function(err, req, res, next) { diff --git a/src/api/middlewares/log.ts b/src/api/middlewares/log.ts deleted file mode 100644 index 2ea6de5fd6e0326f2c3bad6a3764dbb5ed4f3995..0000000000000000000000000000000000000000 --- a/src/api/middlewares/log.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import { Log } from "../../util/log"; -import { Middleware } from "../types"; - -/** - * Creates a log and middleware that - * inserts the log into the request objects. - */ -export function LogMw (): Middleware { - let log: Log = new Log(); - - return function logMiddleware(req, res, next) { - req.log = log; - next(); - }; -} diff --git a/src/api/router-v1.ts b/src/api/router-v1.ts index e80dea65bcc35e96fcbeeedbb58ac68a70c74f02..40db5d881649ff2a0b8ec5597adf97ab86a0bc01 100644 --- a/src/api/router-v1.ts +++ b/src/api/router-v1.ts @@ -18,7 +18,6 @@ * along with blendb. If not, see <http://www.gnu.org/licenses/>. */ -/** @hidden */ const osprey = require("osprey"); // import controllers @@ -26,13 +25,13 @@ import { DataCtrl } from "./controllers/data"; import { CollectCtrl } from "./controllers/collect"; import { EngineCtrl } from "./controllers/engine"; -/** @hidden */ export const router = osprey.Router(); +/* getMetrics */ router.get("/metrics", EngineCtrl.metrics); -router.get("/sources", EngineCtrl.sources); +/* getDimensions */ router.get("/dimensions", EngineCtrl.dimensions); -router.get("/enumtypes", EngineCtrl.enumTypes); -router.get("/tags", EngineCtrl.tags); +/* database operations */ router.get("/data", DataCtrl.read); +/* doesn't do anything */ router.post("/collect/{class}", CollectCtrl.write); diff --git a/src/api/types.ts b/src/api/types.ts index a0fb52a912895ed41a8afa4b411481cf89ac04b1..eb643c32b1bd20d4d5585aa3d3605819455f10e2 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -21,32 +21,12 @@ import * as express from "express"; import { Engine } from "../core/engine"; import { Adapter} from "../core/adapter"; -import { Log } from "../core/log"; -/** - * Extension of Express requests that suports the addition - * of an engine and an adapter. - * This extension is required because some Middlewares - * add some objetcs, in this case metrics and dimensions, - * to the Request object. To typescript compiler do not - * return a error the extension must be made. - */ export interface Request extends express.Request { - /** A engine object. Represents the database in BlenDB perspective. */ engine: Engine; - /** A adapter object. Used to communicate with the database in use. */ adapter: Adapter; - /** A csvParser function. Used to parse json object into csv file. */ - csvParser: (json: any, format: string, cb: (err: Error, csv?: string)); - /** A log object. Used store logs into file. */ - log: Log; } -/** - * Extension Middleware function of ExpressJS Module. - * Uses the custom Request object and is used to define - * the middlewares of BlenDB API. - */ export interface Middleware { (req: Request, res: express.Response, next: express.NextFunction): void; } diff --git a/src/common/expression.ts b/src/common/expression.ts deleted file mode 100644 index 8a9ac07029ed01b7fa893ce3b282c106e8dbbf85..0000000000000000000000000000000000000000 --- a/src/common/expression.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blend. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blend. If not, see <http://www.gnu.org/licenses/>. - */ - -import { View } from "../core/view"; - -/** - * Operation codes to each allowed operation over a view. - */ -export enum Opcode { - /** - * Push operation. - * This operation means that the view is materialized. - * This also means that there are no need to create it - * using other views. - * And also means that this view is a valid data location. - */ - PUSH, - /** - * Join operation. - * The view will be created using a set of others view. - * This operation is equivalent a INNER JOIN of SQL - * or as close as possible of JOIN. - */ - JOIN, - /** - * Reduce operation. - * The reduce operation removes irrelevant metrics and - * dimensions and apply clauses. Represents the Projection - * and Selecion operations of Relational Algebra. - */ - REDUCE -} - -/** - * Defines how to construct a View with a operation - * and a set of chidren Views. - */ -export interface Operation { - /** Operation code used. */ - opcode: Opcode; - /** Set of views required to perform the operation. */ - values: View[]; -} diff --git a/src/common/query.ts b/src/common/query.ts index b0d3112695e626601c20447f063fcdacda21b782..3303711764c288bc5202e51784255fef2903dea1 100644 --- a/src/common/query.ts +++ b/src/common/query.ts @@ -22,37 +22,8 @@ import { Metric } from "../core/metric"; import { Dimension } from "../core/dimension"; import { Clause } from "../core/clause"; -/** - * Internal representation of a query in BlenDB perspective. - */ -export interface QueryOpts { - /** Set of metrics of the query. */ - metrics: Metric[]; - /** Set of dimensions of the query. */ - dimensions: Dimension[]; - /** Set of clauses of the query. */ - clauses?: Clause[]; - /** List of metrics and dimensions to sort the query. */ - sort?: (Metric|Dimension)[]; -} - export class Query { - /** Set of metrics of the query. */ public readonly metrics: Metric[]; - /** Set of dimensions of the query. */ public readonly dimensions: Dimension[]; - /** Set of clauses of the query. */ - public readonly clauses: Clause[]; - /** List of metrics and dimensions to sort the query. */ - public readonly sort: (Metric|Dimension)[]; - /** - * Create Query - * @param opts - Parameters required to create a query. - */ - constructor(opts: QueryOpts){ - this.metrics = opts.metrics.map((i) => i); - this.dimensions = opts.dimensions.map((i) => i); - this.clauses = (opts.clauses) ? opts.clauses.map((i) => i) : []; - this.sort = (opts.sort) ? opts.sort.map((i) => i) : []; - } + public readonly clauses?: Clause[]; } diff --git a/src/common/tag.ts b/src/common/tag.ts deleted file mode 100644 index 1b0b3fdf410f02036a04ee61a9a2e00c00bc2bcd..0000000000000000000000000000000000000000 --- a/src/common/tag.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -/** - * Parameters used to create a Tag object. - * Parameters used to define tag object in the configuration file. - * Also the string description of a tag. - */ -export interface TagOptions { - /** Tag name. */ - name: string; - /** Breif description of what this tag represents. */ - description?: string; -} - -/** - * A Tag can be attached to other elements (such as metrics and dimensions) - * to create groups of similar elements. A tag can also be used to filter - * these elements, search for itens that only contain the given tags. - */ -export class Tag { - /** Tag name. */ - public readonly name: string; - /** Breif description of what this tag represents. */ - public readonly description: string; - - /** - * Creates a tag. - * @param options - Parameters required to create a tag. - */ - constructor(options: TagOptions) { - this.name = options.name; - this.description = (options.description) ? options.description : ""; - } - - /** - * Creates a object with the same options used to create this - * tag as strings. Used to inform the API users. - */ - public strOptions(): TagOptions { - return { - name: this.name - , description: this.description - }; - } -} diff --git a/src/common/types.ts b/src/common/types.ts index 6e31f1123d0b8129da29133e643242f1eb6abf6e..661fce354b942243046905bcb9b986662e818f8b 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -18,71 +18,19 @@ * along with blend. If not, see <http://www.gnu.org/licenses/>. */ -/** - * Available aggregation function to metrics. - */ export enum AggregationType { - /** Used as error code. So suitable aggregation found. */ - NONE, - /** Sum aggregation function. Sum of all registers. */ - SUM, - /** Average aggregation function. Average of all registers. */ - AVG, - /** Count agggreation function. Count the number of registers. */ - COUNT, - /** Maximum aggregation function. The biggest value of all registers. */ - MAX, - /** Minimum aggregation function. The smallest value of all registers. */ - MIN -} + NONE, + SUM, + AVG, + COUNT, + MAX, + MIN +}; -/** - * Available relationships between sub dimensions and its parents. - */ export enum RelationType { - /** Used when there are no relation. The dimension is not a sub dimension. */ - NONE, - /** - * Day relation. - * The parent is a timestamp and the dimension is only the day of - * the timestamp. - */ - DAY, - /** - * Month relation. - * The parent is a timestamp and the dimension is only the month of - * the timestamp. - */ - MONTH, - /** - * Year relation. - * The parent is a timestamp and the dimension is only the year of - * the timestamp. - */ - YEAR, -} - -/** - * Available data types for metrics, dimensions and source members. - * In other words types that BlenDB can handle. - */ -export enum DataType { - /** Used as error code when no suitable type is found. */ - NONE, - /** Interger type. */ - INTEGER, - /** Floating number type. */ - FLOAT, - /** String type. */ - STRING, - /** Timestamp type. ISO format */ - DATE, - /** True/False type. */ - BOOLEAN, - /** - * Enumerable type. - * Custom type, that only accepts a set of previeous defined values. - * Custom enumeration defined in configuration file. - */ - ENUMTYPE -} + NONE, + DAY, + MONTH, + YEAR, + DAYOFWEEK +}; diff --git a/src/core/adapter.ts b/src/core/adapter.ts index 4b266f40f6f6a972cee58beb58bf9235b67be72c..20cb90cfa5b995959f0aa7fb6b1d9381d97e0cdf 100644 --- a/src/core/adapter.ts +++ b/src/core/adapter.ts @@ -19,30 +19,8 @@ */ import { View } from "./view"; -import { Source } from "./source"; -/** - * Absraction of the SGBD from the BlenDB perspective. Used to - * perform all the operations into the database that the Blendb - * requires. This operations include read and write data. - */ export abstract class Adapter { - /** - * Asynchronously reads all data from given view. - * In other words perform a SELECT query. - * @param view - "Location" from all data should be read. - * @param cb - Callback function which contains the data read. - * @param cb.error - Error information when the method fails. - * @param cb.result - Data got from view. - */ public abstract getDataFromView(view: View, cb: (err: Error, result: any[]) => void): void; - /** - * Asynchronously insert one register into a given Source. - * @param source - Insertion "location". - * @param data - Data to be inserted. - * @param cb - Callback function which contains the query result. - * @param cb.error - Error information when the method fails. - * @param cb.result - Query result. - */ - public abstract insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void; + public abstract materializeView(view: View): boolean; } diff --git a/src/util/tsort.spec.ts b/src/core/aggregate.spec.ts similarity index 50% rename from src/util/tsort.spec.ts rename to src/core/aggregate.spec.ts index cbb268c47a198de482461745a3b9a85487556980..bcc3a3f66649c1e1ee0abaec24d0584e340f9d8c 100644 --- a/src/util/tsort.spec.ts +++ b/src/core/aggregate.spec.ts @@ -20,26 +20,21 @@ import { expect } from "chai"; -import { Tsort, TsortDep } from "./tsort"; +import { Aggregate } from "./aggregate"; -describe("topological sorting utility library", () => { - it("should sort the dependencies", () => { - let deps: TsortDep[] = [ - {value: "dim:1", dependOf: "dim:0"}, - {value: "dim:2", dependOf: "dim:0"}, - {value: "dim:3", dependOf: "dim:1"}, - {value: "dim:4", dependOf: "dim:2"}, - {value: "dim:5", dependOf: "dim:3"}, - {value: "dim:5", dependOf: "dim:2"}, - ]; - let sorted = Tsort.dependencies(deps); - let res: string[] = ["dim:0", "dim:2", "dim:4", "dim:1", "dim:3", "dim:5"]; +describe("aggregate class", () => { + it("should be instantiated with an array metrics and one of dimensions", () => { + let aggr = new Aggregate(["met:one"], ["dim:one", "dim:two"]); + expect(aggr).to.be.an("object"); + }); + + it("should not be instantiated with an empty array of metrics", () => { + let aggr = new Aggregate([], ["dim:one", "dim:two"]); + expect(aggr).to.be.an("object"); + }); - expect(res).to.be.a("array"); - expect(res).to.not.be.empty; - for (let i = 0; i < sorted.length; ++i) { - expect(sorted[i]).to.be.a("string"); - expect(sorted[i]).to.be.eql(res[i]); - } + it("should not be instantiated with an empty array of dimensions", () => { + let aggr = new Aggregate(["met:one"], []); + expect(aggr).to.be.an("object"); }); }); diff --git a/src/core/aggregate.ts b/src/core/aggregate.ts new file mode 100644 index 0000000000000000000000000000000000000000..a1e3ccf54da6dde4b858b744bb34124995d9c685 --- /dev/null +++ b/src/core/aggregate.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blendb. + * + * blendb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blendb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blendb. If not, see <http://www.gnu.org/licenses/>. + */ + +export interface IAggregateData { + metrics: any; + dimensions: any; +} + +export class Aggregate { + public metrics: string[]; + public dimensions: string[]; + private data: IAggregateData[]; + + constructor(metrics: string[], dimensions: string[], options?: any) { + this.metrics = metrics; + this.dimensions = dimensions; + + this.data = []; + } + + public push(data: IAggregateData) { + this.data.push(data); + } + + public truncate() { + this.data = []; + } + + public find(query: any) { + let result: any = []; + + this.data.forEach((doc: IAggregateData) => { + let match = true; + + for (let key in query) { + if (query.hasOwnProperty(key)) { + let value = query[key]; + + if (doc.dimensions[key] !== value) { + match = false; + break; + } + } + } + + if (match) { + result.push(doc); + } + }); + + return result; + } +} diff --git a/src/core/clause.ts b/src/core/clause.ts index 5e70f6bc2b72e52353bd9554fa408b62b6b370e3..1b7c47e6f47d07586f36f40b0e7b3a657bdc06ae 100644 --- a/src/core/clause.ts +++ b/src/core/clause.ts @@ -23,25 +23,15 @@ import { Hash } from "../util/hash"; import { Dimension } from "./dimension"; import { Metric } from "./metric"; -/** Parameters used to create a Clause object. */ export interface ClauseOptions { - /** Set of filters that form the clause. */ filters: Filter[]; } -/** Set of restrictions applied to a query united by the operator OR. */ export class Clause { - /** Hash of components that unique identify the clause. */ public readonly id: string; - /** Set of filters the form the clause. */ public readonly filters: Filter[]; - /** Set of attributes affected by this clause. */ public readonly targets: (Metric|Dimension)[]; - /** - * Create a clause object. - * @param options - Parameters required to create a clause object. - */ constructor (options: ClauseOptions) { this.filters = options.filters.map((i) => i); const t = this.filters.map((i) => i.target).sort((a, b) => { @@ -62,14 +52,6 @@ export class Clause { this.id = Hash.sha1(filtersIds.sort()); } - /** - * Checks if the targets of this clause is a sub set of - * the given coverage set. - * In other words, this clause could be applied to a view - * which has the coverage set as set of metrics and dimensions - * @param coverage - Set of attributes which will be verified if - * contain all targets in the clause. - */ public isCovered(coverage: (Metric|Dimension)[]): boolean { return this.targets.every((i) => coverage.some((j) => i.name === j.name)); } diff --git a/src/core/dimension.ts b/src/core/dimension.ts index af69a5955126a6d59b344f598f95c402253efd96..bda4e07fe43ad15b09e71294ebdd8abe4392746c 100644 --- a/src/core/dimension.ts +++ b/src/core/dimension.ts @@ -18,107 +18,86 @@ * along with blend. If not, see <http://www.gnu.org/licenses/>. */ -import { RelationType, DataType } from "../common/types"; -import { EnumHandler } from "../util/enumHandler"; -import { Tag } from "../common/tag"; +import { RelationType } from "../common/types"; -/** Parameters used to create a Dimension object. */ export interface DimensionOptions { - /** Dimension name. */ name: string; - /** Dimension data type. */ - dataType: DataType; - /** Parent dimension, in case this dimension is a sub dimenion. */ + dataType: string; parent?: Dimension; - /** Relationship with the parent. */ relation?: RelationType; - /** Breif description of what this dimension represents. */ description?: string; - /** Enumerable type name, used if data type is enumerable type. */ - enumType?: string; - /** List of tags, a complement to attribute description. */ - tags?: Tag[]; } -/** - * Parameters used to define dimension object in the configuration file. - * Also the string description of a dimension. - */ export interface DimensionStrOptions { - /** Dimension name. */ name: string; - /** Dimension data type. */ dataType: string; - /** Parent dimension, in case this dimension is a sub dimenion. */ parent?: string; - /** Relationship with the parent. */ relation?: string; - /** Breif description of what this dimension represents. */ description?: string; - /** Dimension enum type */ - enumType?: string; - /** List of tag names, a complement to attribute description. */ - tags?: string[]; } -/** - * One attribute of database that can be read. - * A dimension defines a aspect or characteristic of the data. - * Used in a query as a desired information and is separated from - * the metrics because this two types of attributes behave differently - * in the query. While dimensions are grouped, metrics are aggregated. - */ export class Dimension { - /** Dimension name. */ public readonly name: string; - /** Dimenion data type. */ - public readonly dataType: DataType; - /** Parent dimension, in case this dimension is a sub dimenion. */ + public readonly dataType: string; public readonly parent: Dimension; - /** Relationship with the parent. */ public readonly relation: RelationType; - /** Breif description of what this dimension represents. */ public readonly description: string; - /** Enumerable type name, used if data type is enumerable type. */ - public readonly enumType: string; - /** List of tags, a complement to attribute description. */ - public readonly tags: Tag[]; - /** - * Creates a dimension. - * @param options - Parameters required to create a dimension. - */ constructor(options: DimensionOptions) { this.name = options.name; this.dataType = options.dataType; this.relation = (options.relation) ? options.relation : RelationType.NONE; this.parent = (options.parent) ? options.parent : null; this.description = (options.description) ? options.description : ""; - this.enumType = (options.enumType) ? options.enumType : ""; - this.tags = (options.tags) ? options.tags.map((i) => i) : []; } - /** - * Creates a object with the same options used to create this - * dimension as strings. Used to inform the API users. - */ public strOptions(): DimensionStrOptions { - let o: DimensionStrOptions = { - name: this.name, - dataType: EnumHandler.stringfyDataType(this.dataType), - description: this.description, - tags: this.tags.map ((i) => i.name) - }; + if (this.relation === RelationType.NONE) { + return { + name: this.name, + dataType: this.dataType, + description: this.description + }; + } - if (this.relation !== RelationType.NONE) { - o.relation = EnumHandler.stringifyRelationType(this.relation); - o.parent = this.parent.name; + else { + return { + name: this.name, + dataType: this.dataType, + parent: this.parent.name, + relation: Dimension.stringifyRelationType(this.relation), + description: this.description + }; } + } - if (this.dataType === DataType.ENUMTYPE) { - o.enumType = this.enumType; + public static parseRelationType(r: string): RelationType { + switch (r) { + case "day": + return RelationType.DAY; + case "month": + return RelationType.MONTH; + case "year": + return RelationType.YEAR; + case "dayofweek": + return RelationType.DAYOFWEEK; + default: + return RelationType.NONE; } + } - return o; + public static stringifyRelationType(r: RelationType): string { + switch (r) { + case RelationType.DAY: + return "day"; + case RelationType.MONTH: + return "month"; + case RelationType.YEAR: + return "year"; + case RelationType.DAYOFWEEK: + return "dayofweek"; + default: + return ""; + } } } diff --git a/src/core/engine.spec.ts b/src/core/engine.spec.ts index f1943f484cadb60e260fc434ca1fab1262f08e04..df5d4950421810f8c6bd46147a3778f11c48cf5a 100644 --- a/src/core/engine.spec.ts +++ b/src/core/engine.spec.ts @@ -19,43 +19,52 @@ */ import { expect } from "chai"; + import { Engine } from "./engine"; -import { FilterOperator } from "./filter"; +import { Metric } from "./metric"; +import { Filter, FilterOperator } from "./filter"; +import { Clause } from "./clause"; import { View } from "./view"; import { engineScenario } from "../../test/scenario"; -import { EnumType } from "./enumType"; -import { Dimension } from "./dimension"; describe("engine class", () => { + const engine = new Engine(); - const engine = new Engine(engineScenario.config); + const met = engineScenario.metrics; + const dim = engineScenario.dimensions; const subdim = engineScenario.subDimensions; + const views = engineScenario.views; - for (let key in subdim){ - if (subdim[key]){ - engine.addDimension(subdim[key]); - } - } + met.forEach((item) => engine.addMetric(item)); + dim.forEach((item) => engine.addDimension(item)); + subdim.forEach((item) => engine.addDimension(item)); + + views.forEach((view) => engine.addView(view)); it("should be create a fill that cover all metrics and dimensions", () => { - let query = engineScenario.queryMetsDims; + let query = { + metrics : met.slice(0) + , dimensions : dim.slice(0) + }; let optimalView = engine.query(query); expect(optimalView).to.be.an("object"); expect(optimalView).to.have.property("metrics"); expect(optimalView).to.have.property("dimensions"); + expect(optimalView).to.have.property("childViews"); expect(optimalView.metrics).to.be.an("array"); expect(optimalView.dimensions).to.be.an("array"); - expect(optimalView.metrics).to.have.length(16); - expect(optimalView.dimensions).to.have.length(19); + expect(optimalView.childViews).to.be.an("array"); + expect(optimalView.metrics).to.have.length(12); + expect(optimalView.dimensions).to.have.length(13); }); it("should throw an exception, query with non-existent metric", () => { let error: boolean = false; try { - engine.query(engineScenario.queryNoMets); + engine.query({metrics: [engineScenario.wrongMet], dimensions: [dim[0]]}); } catch (e){ error = true; - expect(e.message).to.be.equal("[Engine Error] Engine views cannot cover the query"); + expect(e.message).to.be.equal("Engine views cannot cover the query"); } expect(error); @@ -64,82 +73,133 @@ describe("engine class", () => { it("should throw an exception, query with non-existent dimension", () => { let error: boolean = false; try { - engine.query(engineScenario.queryNoDims); + engine.query({metrics: [met[0]], dimensions: [engineScenario.wrongDim]}); } catch (e){ error = true; - expect(e.message).to.be.equal("[Engine Error] Engine views cannot cover the query"); + expect(e.message).to.be.equal("Engine views cannot cover the query"); } expect(error); }); it("should be create a fill that cover the query, that match perfectly with a existent view", () => { - let query = engineScenario.queryProduct; + let query = { + metrics : [met[0], met[1], met[2], met[10]] + , dimensions : [dim[0], dim[7]] + }; let optimalView = engine.query(query); expect(optimalView).to.be.an("object"); expect(optimalView).to.have.property("metrics"); expect(optimalView).to.have.property("dimensions"); - expect(optimalView).to.have.property("operation"); + expect(optimalView).to.have.property("childViews"); expect(optimalView.metrics).to.be.an("array"); expect(optimalView.dimensions).to.be.an("array"); - expect(optimalView.operation).to.be.an("object"); - expect(optimalView.metrics).to.have.length(6); - expect(optimalView.dimensions).to.have.length(3); - expect(optimalView.operation).to.have.property("opcode"); - expect(optimalView.id).to.be.equal(engineScenario.viewProduct.id); + expect(optimalView.childViews).to.be.an("array"); + expect(optimalView.metrics).to.have.length(4); + expect(optimalView.dimensions).to.have.length(2); + expect(optimalView.childViews).to.have.length(0); + + expect(optimalView.id).to.be.equal(views[0].id); }); it("should be create a fill that cover the query, that match perfectly with a existent view, with clauses", () => { - let query = engineScenario.queryActive; + const clause = new Clause({ + filters: [new Filter({ + target: dim[2], + operator: FilterOperator.NOTEQUAL, + value: "1" + })] + }); + let query = { + metrics : [met[5], met[6], met[7]] + , dimensions : [dim[2]] + , clauses: [clause] + }; let optimalView = engine.query(query); expect(optimalView).to.be.an("object"); expect(optimalView).to.have.property("metrics"); expect(optimalView).to.have.property("dimensions"); - expect(optimalView).to.have.property("operation"); + expect(optimalView).to.have.property("childViews"); + expect(optimalView).to.have.property("materialized"); expect(optimalView.metrics).to.be.an("array"); expect(optimalView.dimensions).to.be.an("array"); - expect(optimalView.operation).to.be.an("object"); - expect(optimalView.metrics).to.have.length(1); - expect(optimalView.dimensions).to.have.length(2); - expect(optimalView.operation).to.have.property("opcode"); - expect(optimalView.id).to.be.equal(engineScenario.viewActiveSeller.id); + expect(optimalView.childViews).to.be.an("array"); + expect(optimalView.metrics).to.have.length(3); + expect(optimalView.dimensions).to.have.length(1); + expect(optimalView.childViews).to.have.length(0); + expect(optimalView.materialized).to.be.true; + + expect(optimalView.id).to.be.equal(views[9].id); }); it("should be create a fill that cover the query, using sub dimensions", () => { - let query = engineScenario.querySubDim; + let emptyMetrics: Metric[] = []; + let query = { + metrics : emptyMetrics + , dimensions : subdim.slice(0, 2) + }; + let optimalView = engine.query(query); + expect(optimalView).to.be.an("object"); + expect(optimalView).to.have.property("metrics"); + expect(optimalView).to.have.property("dimensions"); + expect(optimalView).to.have.property("childViews"); + expect(optimalView.metrics).to.be.an("array"); + expect(optimalView.dimensions).to.be.an("array"); + expect(optimalView.childViews).to.be.an("array"); + expect(optimalView.metrics).to.have.length(0); + expect(optimalView.dimensions).to.have.length(2); + expect(optimalView.childViews).to.have.length(3); + + expect(optimalView).satisfy((optView: View) => { + return optView.dimensions.some((item) => item.name === subdim[0].name); + }); + expect(optimalView).satisfy((optView: View) => { + return optView.dimensions.some((item) => item.name === subdim[1].name); + }); + }); + + it("should be create a fill that cover the query, using the parents of sub dimensions", () => { + let emptyMetrics: Metric[] = []; + let query = { + metrics : emptyMetrics + , dimensions : [subdim[2], subdim[4]] + }; let optimalView = engine.query(query); expect(optimalView).to.be.an("object"); expect(optimalView).to.have.property("metrics"); expect(optimalView).to.have.property("dimensions"); + expect(optimalView).to.have.property("childViews"); expect(optimalView.metrics).to.be.an("array"); expect(optimalView.dimensions).to.be.an("array"); + expect(optimalView.childViews).to.be.an("array"); expect(optimalView.metrics).to.have.length(0); expect(optimalView.dimensions).to.have.length(2); + expect(optimalView.childViews).to.have.length(3); expect(optimalView).satisfy((optView: View) => { - return optView.dimensions.some((item) => item.name === subdim["subdims_day"].name); + return optView.dimensions.some((item) => item.name === subdim[2].name); }); expect(optimalView).satisfy((optView: View) => { - return optView.dimensions.some((item) => item.name === subdim["subdims_month"].name); + return optView.dimensions.some((item) => item.name === subdim[4].name); }); }); it("should throw an exception, sub-dimension with non-existent parent", () => { let error: boolean = false; try { - engine.query(engineScenario.queryNoParent); + engine.query({metrics: [met[0]], dimensions: [subdim[3]]}); } catch (e){ error = true; - expect(e.message).to.be.equal("[Engine Error] Engine views cannot cover the query"); + expect(e.message).to.be.equal("Engine views cannot cover the query"); } expect(error).to.be.true; }); it("should parse a clause, with target as dimension and operator as ==", () => { - const strFilter = "dim:client:name==Laci"; + const strFilter = "dim:0==0"; const clause = engine.parseClause(strFilter); expect(clause).to.be.an("object"); expect(clause).to.have.property("filters"); @@ -150,13 +210,12 @@ describe("engine class", () => { expect(clause.filters[0]).to.have.property("target"); expect(clause.filters[0]).to.have.property("value"); expect(clause.filters[0]).to.have.property("operator"); - expect(clause.filters[0].target).to.be.equal(engine.getDimensionByName("dim:client:name")); - expect(clause.filters[0].value).to.be.equal("Laci"); + expect(clause.filters[0].target).to.be.equal(dim[0]); + expect(clause.filters[0].value).to.be.equal("0"); expect(clause.filters[0].operator).to.be.equal(FilterOperator.EQUAL); }); - it("should parse a clause, with target as metric and operator as !=", () => { - const strFilter = "met:product:avg:pricein!=0"; + const strFilter = "met:0!=0"; const clause = engine.parseClause(strFilter); expect(clause).to.be.an("object"); expect(clause).to.have.property("filters"); @@ -167,15 +226,14 @@ describe("engine class", () => { expect(clause.filters[0]).to.have.property("target"); expect(clause.filters[0]).to.have.property("operator"); expect(clause.filters[0]).to.have.property("value"); - expect(clause.filters[0].target).to.be.equal(engine.getMetricByName("met:product:avg:pricein")); + expect(clause.filters[0].target).to.be.equal(met[0]); expect(clause.filters[0].value).to.be.equal("0"); expect(clause.filters[0].operator).to.be.equal(FilterOperator.NOTEQUAL); }); - it("should throw an exception, when a dimension is not found", () => { let error: boolean = false; - const strFilter = "dim:seller:willfail==teste"; - const exeption = "[Engine Error] Filter could not be created: \"dim:seller:willfail\" was not found. Check target spelling."; + const strFilter = "dim:-1==0"; + const exeption = "Filter could not be created: \"dim:-1\" was not found"; try { engine.parseClause(strFilter); } @@ -186,11 +244,10 @@ describe("engine class", () => { } expect(error).to.be.true; }); - it("should throw an exception, when a metric is not found", () => { let error: boolean = false; - const strFilter = "met:seller:count:willfail==0"; - const exeption = "[Engine Error] Filter could not be created: \"met:seller:count:willfail\" was not found. Check target spelling."; + const strFilter = "met:-1==0"; + const exeption = "Filter could not be created: \"met:-1\" was not found"; try { engine.parseClause(strFilter); } @@ -201,11 +258,10 @@ describe("engine class", () => { } expect(error).to.be.true; }); - it("should throw an exception, when a operator is not found", () => { let error: boolean = false; - let strFilter = "met:sell:sum:quantity=?0"; - let exeption = "[Engine Error] Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"; + let strFilter = "met:-1=?0"; + let exeption = "Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"; try { engine.parseClause(strFilter); } @@ -216,8 +272,8 @@ describe("engine class", () => { } expect(error).to.be.true; error = false; - strFilter = "met:sell:sum:quantity!?0"; - exeption = "[Engine Error] Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"; + strFilter = "met:-1!?0"; + exeption = "Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"; try { engine.parseClause(strFilter); } @@ -233,8 +289,8 @@ describe("engine class", () => { const operators = [">", "<", "<=", ">="]; for (let i = 0; i < operators.length; ++i) { let error: boolean = false; - let strFilter = "dim:client:name" + operators[i] + "Firoz"; - let exeption = "[Engine Error] Filter could not be created: Operator \"" + operators[i] + "\" is invalid for target \"dim:client:name\""; + let strFilter = "dim:3" + operators[i] + "joao"; + let exeption = "Filter could not be created: Operator \"" + operators[i] + "\" is invalid for target \"dim:3\""; try { engine.parseClause(strFilter); } @@ -243,7 +299,6 @@ describe("engine class", () => { expect(e.message).to.be.equal(exeption); } - expect(error).to.be.true; } }); @@ -256,8 +311,8 @@ describe("engine class", () => { "==": FilterOperator.EQUAL, "!=": FilterOperator.NOTEQUAL }; - for (let op of Object.keys(operators)) { - const strFilter = "dim:sell:datein" + op + "2018-02-17"; + for (let op in operators) { + const strFilter = "dim:0" + op + "0"; const clause = engine.parseClause(strFilter); expect(clause).to.be.an("object"); expect(clause).to.have.property("filters"); @@ -268,13 +323,13 @@ describe("engine class", () => { expect(clause.filters[0]).to.have.property("target"); expect(clause.filters[0]).to.have.property("operator"); expect(clause.filters[0]).to.have.property("value"); - expect(clause.filters[0].target).to.be.equal(engine.getDimensionByName("dim:sell:datein")); - expect(clause.filters[0].value).to.be.equal("2018-02-17"); + expect(clause.filters[0].target).to.be.equal(dim[0]); + expect(clause.filters[0].value).to.be.equal("0"); expect(clause.filters[0].operator).to.be.equal(operators[op]); } - for (let op of Object.keys(operators)) { - const strFilter = "dim:seller:id" + op + "0"; + for (let op in operators) { + const strFilter = "dim:2" + op + "0"; const clause = engine.parseClause(strFilter); expect(clause).to.be.an("object"); expect(clause).to.have.property("filters"); @@ -285,48 +340,9 @@ describe("engine class", () => { expect(clause.filters[0]).to.have.property("target"); expect(clause.filters[0]).to.have.property("operator"); expect(clause.filters[0]).to.have.property("value"); - expect(clause.filters[0].target).to.be.equal(engine.getDimensionByName("dim:seller:id")); + expect(clause.filters[0].target).to.be.equal(dim[2]); expect(clause.filters[0].value).to.be.equal("0"); expect(clause.filters[0].operator).to.be.equal(operators[op]); } }); - it("should return all views", () => { - let views: View[]; - views = engine.getViews(); - expect(views).to.have.length(9); - for (let i = 0 ; i < views.length; i++){ - expect(views[i]).to.have.property("metrics"); - expect(views[i]).to.have.property("dimensions"); - expect(views[i]).to.have.property("clauses"); - expect(views[i]).to.have.property("origin"); - expect(views[i]).to.have.property("operation"); - expect(views[i]).to.have.property("id"); - expect(views[i]).to.have.property("name"); - } - }); - it("should return null from addView", () => { - let view: View; - view = engine.addView(null); - expect(view).to.be.null; - }); - it("should return null from addDimension", () => { - let dimension: Dimension; - dimension = engine.addDimension(null); - expect(dimension).to.be.null; - }); - - it("should return all views", () => { - let enumtype: EnumType; - let error: boolean = false; - try { - enumtype = engine.getEnumTypeByName("test"); - } - catch (e){ - error = true; - expect(e.message).to.be.equal("[Engine Error] EnumType: 'test' do not exist in the database." + - " Check enumtype spelling and database configuration."); - } - expect(error); - }); - }); diff --git a/src/core/engine.ts b/src/core/engine.ts index 7157ae55022440c54c9fcb1699f2c57a14b38832..e2bb9bde972230aaa36dd92bd57e594c2773f5a0 100644 --- a/src/core/engine.ts +++ b/src/core/engine.ts @@ -18,133 +18,40 @@ * along with blend. If not, see <http://www.gnu.org/licenses/>. */ -import { Dimension, DimensionStrOptions } from "./dimension"; -import { Metric, MetricStrOptions } from "./metric"; -import { Tag, TagOptions } from "../common/tag"; +import { Dimension } from "./dimension"; +import { Metric } from "./metric"; import { Clause } from "./clause"; import { Filter } from "./filter"; import { View } from "./view"; -import { Query, QueryOpts } from "../common/query"; +import { Query } from "../common/query"; import { Graph } from "../util/graph"; -import { EnumType, EnumTypeOptions} from "./enumType"; -import { Source , SourceStrOptions } from "./source"; -import { ViewHandler } from "../util/viewHandler"; -import { ParsedConfig } from "../util/configParser"; -/** - * Represents the database schema from the BlenDB perspective. - * The engine is an abstraction of a generic analytics database. - * All the operations that would be realised in the database - * are made through the engine. The main purpose of the engine - * is to translate a localition less query into a localized query. - * In other words, discover in which view a metric/dimension is. - */ export class Engine { - /** Set of views available in the database */ - private views: View[]; - /** Set of metrics available in the database. */ - private metrics: Metric[]; - /** Set of enumerable types available in the database. */ - private enumTypes: EnumType[]; - /** Set of dimensions available in the database. */ - private dimensions: Dimension[]; - /** Set of sources available in the database. */ - private sources: Source[]; - /** Set of tags available in the database. */ - private tags: Tag[]; - /** Graph which represents the database schema. */ + private views: View[] = []; + private metrics: Metric[] = []; + private dimensions: Dimension[] = []; private graph: Graph; - /** Constructs an empty database schema. */ - constructor (config: ParsedConfig) { - - this.graph = new Graph(); - - this.enumTypes = []; + constructor() { this.views = []; this.metrics = []; this.dimensions = []; - this.sources = []; - this.tags = []; - - config.metrics.forEach ((met) => this.addMetric(met)); - config.dimensions.forEach ((dim) => this.addDimension(dim)); - config.views.forEach ((view) => this.addView(view)); - config.enumTypes.forEach ((enumt) => this.addEnumType(enumt)); - config.sources.forEach ((sourc) => this.addSource(sourc)); - config.tags.forEach ((tag) => this.addTag(tag)); - + this.graph = new Graph(); } - /** Gets all the available */ - public getViews(): View[] { + public getViews() { return this.views; } - /** - * Gets a string description for all the available metrics. - * @param expression - Expression to be used in the tags - */ - public getMetricsDescription(expression: string): MetricStrOptions[] { - let list = this.metrics.map((i) => i.strOptions()); - if (!expression) { - return list; - } - - const clauses = expression.split(";").filter((item: string) => item !== ""); - - for (let i = 0; i < clauses.length; ++i) { - const tags = clauses[i].split(",").filter((item: string) => item !== ""); - list = list.filter((item) => { - return item.tags.some((o) => tags.some((t) => t === o)); - }); - } - - return list; - } - - /** Gets a string description for all the available enumerable types. */ - public getEnumTypesDescription(): EnumTypeOptions[] { - return this.enumTypes.map((i) => i.strOptions()); - } - - /** Gets a string description for all the available sources. */ - public getSourcesDescription(): SourceStrOptions[] { - return this.sources.map((i) => i.strOptions()); - } - - /** - * Gets a string description for all the available dimensions. - * @param expression - Expression to be used in the tags - */ - public getDimensionsDescription(expression: string): DimensionStrOptions[] { - let list = this.dimensions.map((i) => i.strOptions()); - if (!expression) { - return list; - } - - const clauses = expression.split(";").filter((item: string) => item !== ""); - - for (let i = 0; i < clauses.length; ++i) { - const tags = clauses[i].split(",").filter((item: string) => item !== ""); - list = list.filter((item) => { - return item.tags.some((o) => tags.some((t) => t === o)); - }); - } - - return list; + public getMetricsDescription() { + return this.metrics.map((i) => i.strOptions()); } - /** Gets a string description for all the available tags. */ - public getTagsDescription(): TagOptions[] { - return this.tags.map((i) => i.strOptions()); + public getDimensionsDescription() { + return this.dimensions.map((i) => i.strOptions()); } - /** - * Adds a new view to the database schema (engine). - * @param view - View to be added. - */ - public addView(view: View): View { + public addView(view: View) { if (this.graph.addView(view)) { this.views.push(view); return view; @@ -153,38 +60,7 @@ export class Engine { return null; } - /** - * Adds a new enumerable type to the database schema (engine). - * @param enumType - Enumerable type to be added. - */ - public addEnumType(enumType: EnumType): EnumType { - this.enumTypes.push(enumType); - return enumType; - } - - /** - * Adds a new tag to the database schema (engine). - * @param enumType - Enumerable type to be added. - */ - public addTag(tag: Tag): Tag { - this.tags.push(tag); - return tag; - } - - /** - * Adds a new source to the database schema (engine). - * @param source - Source to be added. - */ - public addSource(source: Source): Source { - this.sources.push(source); - return source; - } - - /** - * Adds a new metric to the database schema (engine). - * @param metric - Metric to be added. - */ - public addMetric(metric: Metric): Metric { + public addMetric(metric: Metric) { if (this.graph.addMetric(metric)) { this.metrics.push(metric); return metric; @@ -193,56 +69,17 @@ export class Engine { return null; } - /** - * Gets the metric object given its name. - * @param name - Metric's name. - */ - public getMetricByName(name: string): Metric { + public getMetricByName(name: string) { let result = this.metrics.find(metric => metric.name === name); if (!result) { - throw new Error("[Engine Error] Metric: '" + name + "' do not exist in the database." + - " Check metric spelling and database configuration."); - } - - return result; - } - - /** - * Gets the enumerable type object given its name. - * @param name - Enumerable type name. - */ - public getEnumTypeByName(name: string): EnumType { - let result = this.enumTypes.find(EnumType => EnumType.name === name); - - if (!result) { - throw new Error("[Engine Error] EnumType: '" + name + "' do not exist in the database." + - " Check enumtype spelling and database configuration."); - } - - return result; - } - - /** - * Gets the source object given its name. - * @param name - Source's name. - */ - public getSourceByName(name: string): Source { - let result = this.sources.find(source => source.name === name); - - if (!result) { - throw new Error("[Engine Error] Required Source: '" + name + "' do not exist in the database." + - " Check source spelling and database configuration."); + throw new Error("The metric named " + name + " was not found"); } return result; } - /** - * Adds a new dimension to the database schema (engine). - * @param dimension - Dimension to be added. - */ - public addDimension(dimension: Dimension): Dimension { + public addDimension(dimension: Dimension) { if (this.graph.addDimension(dimension)) { this.dimensions.push(dimension); return dimension; @@ -251,25 +88,16 @@ export class Engine { return null; } - /** - * Gets the dimension object given its name. - * @param name - Dimension's name. - */ - public getDimensionByName(name: string): Dimension { + public getDimensionByName(name: string) { let result = this.dimensions.find(dimension => dimension.name === name); if (!result) { - throw new Error("[Engine Error] Dimension: '" + name + "' do not exist in the database." + - " Check dimension spelling and database configuration."); + throw new Error("The dimension named " + name + " was not found"); } return result; } - /** - * Translate a string clause into a clause object. - * @param strClause - Clause in string format. - */ public parseClause(strClause: string): Clause { let strFilters = strClause.split(",").filter((item: string) => item !== ""); let filters: Filter[] = []; @@ -277,19 +105,15 @@ export class Engine { filters.push(this.parseFilter(strFilters[i])); } - return new Clause({filters: filters}); + return new Clause({ filters: filters }); } - /** - * Translate a string filter into a clause object. - * @param strFilter - Filter in string format. - */ public parseFilter(strFilter: string): Filter { let segment = Filter.segment(strFilter); if (segment) { // Segment never returns NONE let op = Filter.parseOperator(segment.operator); - let target: Metric|Dimension = null; + let target: Metric | Dimension = null; try { target = this.getDimensionByName(segment.target); } @@ -305,7 +129,7 @@ export class Engine { } if (!target) { - throw new Error("[Engine Error] Filter could not be created: \"" + segment.target + "\" was not found. Check target spelling."); + throw new Error("Filter could not be created: \"" + segment.target + "\" was not found"); } const filter = new Filter({ @@ -315,87 +139,65 @@ export class Engine { }); if (!filter.isValid) { - throw new Error("[Engine Error] Filter could not be created: Operator \"" + segment.operator + "\" is invalid for target \"" + segment.target + "\""); + throw new Error("Filter could not be created: Operator \"" + segment.operator + "\" is invalid for target \"" + segment.target + "\""); } return filter; } else { - throw new Error("[Engine Error] Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"); + throw new Error("Filter could not be created: Operator on \"" + strFilter + "\" could not be extracted"); } } - - /** - * Transform a query (location less) into a view (localized). - * The main difference between a query object and a view object - * is that a view object can be built from other view objects - * and construct a valid query to conventional SGBD's. - * The query object do not have any location, so can not be - * translate in a valid SGBD query. In other words this method - * find a location (FROM clause in SQL) to the query object. - * @param q - Query to be located. - */ - public query (q: Query): View { + public query(q: Query) { return this.selectOptimalView(q); } - /** - * Selects the best location (view) to a given query. - * @param q - Query to be located. - */ - private selectOptimalView (q: Query): View { - let queries: Query[] = []; - let qOpt: QueryOpts; - if (q.metrics.length > 0) { - for (let i = 0; i < q.metrics.length; ++i) { - qOpt = { metrics: [q.metrics[i]], - dimensions: q.dimensions, - clauses: q.clauses, - sort: q.sort }; - queries.push(new Query(qOpt)); - } - const views = queries.map((query) => { - return ViewHandler.growView(query, this.getCover(query)); - }); - - return ViewHandler.queryJoin(q, views); - } - - else { - let query = new Query(q); - return ViewHandler.growView(query, this.getCover(query)); - } - - } - - /** - * Finds a set of views that has 2 properties: - * 1- Contain all the attributes (metrics/dimensions) - * required do make the query. - * 2- The set of views is connected. This means that - * if the set has more than one view is possible to take - * any view in the set exists another view that share - * at least one dimension. This meke possible to join - * views. - * @param q - Query to be covered. - */ - private getCover (q: Query): View[] { - const optimalViews = this.graph.cover(q); + private selectOptimalView(q: Query) { + let optimalViews = this.graph.cover(q); if (optimalViews.length === 0) { - throw new Error("[Engine Error] Engine views cannot cover the query"); + throw new Error("Engine views cannot cover the query"); + } + + // If all the metrics and dimensions are the same and only exist one child view + // return this single child view + const metrics = q.metrics; + const dimensions = q.dimensions; + const clauses = ((q.clauses) ? q.clauses : []); + if (optimalViews.length === 1 && + optimalViews[0].metrics.length === metrics.length && + optimalViews[0].dimensions.length === dimensions.length && + optimalViews[0].clauses.length === clauses.length && + optimalViews[0].metrics.every((item) => metrics.indexOf(item) !== -1) && + optimalViews[0].dimensions.every((item) => dimensions.indexOf(item) !== -1) && + perfectMatch(optimalViews[0].clauses, clauses)) { + return optimalViews[0]; } - - let matViews: View[] = optimalViews.sort((a, b) => (a.id < b.id) ? -1 : 1); - - let noRepeat: View[] = [matViews[0]]; - for (let i = 1; i < matViews.length; ++i) { - if (matViews[i - 1].id !== matViews[i].id) { - noRepeat.push(matViews[i]); - } + else { + let options = { + metrics: metrics, + dimensions: dimensions, + clauses: clauses, + materialized: false, + origin: false, // Never a dynamic generated view will be origin + childViews: optimalViews + }; + + let view = new View(options); + // this.addView(view); + /* + This line has been removed for now because not all views can be + re-used by other views (unmaterializeble views), and so far this + is only detected in the adapter, when this can be detected in + engine, than the queries can be added again to the engine + */ + return view; } - - return noRepeat; - } +} +function perfectMatch(array1: Clause[], + array2: Clause[]) { + return array1.every((item: Clause) => { + return array2.some((otherItem: Clause) => item.id === otherItem.id); + }); } diff --git a/src/core/enumType.ts b/src/core/enumType.ts deleted file mode 100644 index 76eba3341aabfe7416dd28d884bf21f25641298d..0000000000000000000000000000000000000000 --- a/src/core/enumType.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blend. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blend. If not, see <http://www.gnu.org/licenses/>. - */ - -/** Parameters used to create a Enumerable type object. */ -export interface EnumTypeOptions { - /** The type name. */ - name: string; - /** The allowed values to this type. */ - values: string[]; -} - -/** - * Defines a custom data type. - * This custom type has one restriction. Only a finite - * set o values is allowed to this type. All the - * valid values to this type are set in its definition. - */ -export class EnumType { - /** The type name. */ - public name: string; - /** The allowed values to this type. */ - public values: string[]; - - /** - * Create a enumerable type definition. - * @param options - Parameters required to create a enumerable type. - */ - constructor(options: EnumTypeOptions) { - this.name = options.name; - this.values = options.values; - } - - /** Gets a string description of this enumerable type. */ - public strOptions(): EnumTypeOptions { - return{ - name: this.name, - values: this.values - }; - } -} diff --git a/src/core/filter.ts b/src/core/filter.ts index 336b524ed7c98264b43d2178d2522495732a7e7b..29538096f560861067d87e593b0a8ff7a08496d7 100644 --- a/src/core/filter.ts +++ b/src/core/filter.ts @@ -21,65 +21,36 @@ import { Dimension } from "./dimension"; import { Metric } from "./metric"; import { Hash } from "../util/hash"; -import { DataType } from "../common/types"; -/** Parameters used to create a filter object. */ export interface FilterOptions { - /** Metric/Dimension that will be filtered. */ target: Metric|Dimension; - /** Operation applied to filter. */ operator: FilterOperator; - /** Constant value to be compared. */ value: string; } -/** - * Parameters used to define filter object in the configuration file. - * Also the string description of a filter. - */ export interface StrFilterOptions { - /** Metric/Dimension that will be filtered. */ target: string; - /** Operation applied to filter. */ operator: string; - /** Constant value to be compared. */ value: string; } -/** Available operations to be used in filters */ export enum FilterOperator { - /** Used as error code. So suitable operation found. */ NONE, - /** Equality (==). */ EQUAL, - /** Not equality (!=). */ NOTEQUAL, - /** Greater than (>). */ GREATER, - /** Lower than (<). */ LOWER, - /** Greater or equal than( >=). */ GREATEREQ, - /** Lower or equal than (<=). */ LOWEREQ } export class Filter { - /** Hash of components that unique identify the filter. */ public readonly id: string; - /** Metric/Dimension that will be filtered. */ public readonly target: Metric|Dimension; - /** Constant value to be compared. */ public readonly operator: FilterOperator; - /** Constant value to be compared. */ public readonly value: string; - /** Constant that informs if the target type allow the operator. */ public readonly isValid: boolean; - /** - * Create a filter. - * @param options - Parameters required to create a filter. - */ constructor (options: FilterOptions) { this.target = options.target; this.operator = options.operator; @@ -88,10 +59,6 @@ export class Filter { this.isValid = Filter.isTypeValid(options); } - /** - * Parse a string to enum(Filter Operator). - * @param op - Filter operator in string format. - */ public static parseOperator(op: string): FilterOperator { switch (op) { case "==": @@ -111,10 +78,6 @@ export class Filter { } } - /** - * Splits a continuous string in the string representation of the filter. - * @param strFilter - Filter in string format. - */ public static segment(strFilter: string): StrFilterOptions { for (let i = 0; i < strFilter.length; ++i) { switch (strFilter[i]){ @@ -174,21 +137,16 @@ export class Filter { return null; } - /** - * Verify if the target allows the operation. - * @param op - Operator to be validated. - */ private static isTypeValid(op: FilterOptions): boolean { if (op.operator === FilterOperator.NONE) { return false; } - if (op.operator === FilterOperator.GREATER || - op.operator === FilterOperator.LOWER || + if (op.operator === FilterOperator.GREATER || + op.operator === FilterOperator.LOWER || op.operator === FilterOperator.GREATEREQ || - op.operator === FilterOperator.LOWEREQ) { - if (op.target.dataType === DataType.DATE || - op.target.dataType === DataType.INTEGER) { + op.operator === FilterOperator.LOWEREQ) { + if (op.target.dataType === "date" || op.target.dataType === "integer") { return true; } diff --git a/src/core/metric.ts b/src/core/metric.ts index 3802f1f4945d561452842270b7000a16107349af..7812a2c41e31edb592dfbc73750bbde03f30640a 100644 --- a/src/core/metric.ts +++ b/src/core/metric.ts @@ -18,83 +18,75 @@ * along with blend. If not, see <http://www.gnu.org/licenses/>. */ -import { AggregationType, DataType } from "../common/types"; -import { EnumHandler } from "../util/enumHandler"; -import { Tag } from "../common/tag"; +import { AggregationType } from "../common/types"; -/** Parameters used to create a metric object. */ export interface MetricOptions { - /** Metric name. */ name: string; - /** Aggregation function applied on this metric */ aggregation: AggregationType; - /** Metric data type. */ - dataType: DataType; - /** Breif description of what this metric represents. */ + dataType: string; description?: string; - /** List of tags, a complement to attribute description. */ - tags?: Tag[]; } -/** - * Parameters used to define metric object in the configuration file. - * Also the string description of a metric. - */ export interface MetricStrOptions { - /** Metric name. */ name: string; - /** Aggregation function applied on this metric */ aggregation: string; - /** Metric data type. */ dataType: string; - /** Breif description of what this metric represents. */ description?: string; - /** List of tag names, a complement to attribute description. */ - tags?: string[]; } -/** - * One attribute of database that can be read. - * A metric defines a numeric agggregated aspect of the data. - * Used in a query as a desired information and is separated from - * the dimension because this two types of attributes behave differently - * in the query. While metrics are aggregated, dimensions are grouped. - */ export class Metric { - /** Metric name. */ public readonly name: string; - /** Aggregation function applied on this metric */ public readonly aggregation: AggregationType; - /** Metric data type. */ - public readonly dataType: DataType; - /** Breif description of what this metric represents. */ + public readonly dataType: string; public readonly description: string; - /** List of tags, a complement to attribute description. */ - public readonly tags: Tag[]; - /** - * Create a metric. - * @param options - Parameters required to create a metric. - */ constructor(options: MetricOptions) { this.name = options.name; this.aggregation = options.aggregation; this.dataType = options.dataType; this.description = (options.description) ? options.description : ""; - this.tags = (options.tags) ? options.tags.map((i) => i) : []; } - /** - * Created a object with the same options used to create this - * metric as strings. Used to inform the API users. - */ public strOptions(): MetricStrOptions { return { name: this.name, - aggregation: EnumHandler.stringifyAggrType(this.aggregation), - dataType: EnumHandler.stringfyDataType(this.dataType), - description: this.description, - tags: this.tags.map ((i) => i.name) + aggregation: Metric.stringifyAggrType(this.aggregation), + dataType: this.dataType, + description: this.description }; } + + public static stringifyAggrType(a: AggregationType): string { + switch (a) { + case AggregationType.SUM: + return "sum"; + case AggregationType.AVG: + return "avg"; + case AggregationType.COUNT: + return "count"; + case AggregationType.MAX: + return "max"; + case AggregationType.MIN: + return "min"; + default: + return ""; + } + } + + public static parseAggrType (str: string): AggregationType { + switch (str) { + case "sum": + return AggregationType.SUM; + case "avg": + return AggregationType.AVG; + case "count": + return AggregationType.COUNT; + case "min": + return AggregationType.MIN; + case "max": + return AggregationType.MAX; + default: + return AggregationType.NONE; + } + } } diff --git a/src/core/server.spec.ts b/src/core/server.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9e0dfbbb0d2f9fa30333608a826674ac3e7d0659 --- /dev/null +++ b/src/core/server.spec.ts @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blendb. + * + * blendb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blendb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blendb. If not, see <http://www.gnu.org/licenses/>. + */ + +import { expect } from "chai"; + +import { Server } from "./server"; + +describe("server class", () => { + it("should be able to create and retrieve sources", () => { + const server = new Server(); + + // create two sources + const source1 = server.source("source1"); + const source2 = server.source("source2"); + + // retrieve the first one + const retrieved = server.source("source1"); + + // check if sources were actually created/retrieved + expect(source1).to.be.an("object"); + expect(source2).to.be.an("object"); + expect(retrieved).to.be.an("object"); + + // check if the two created sources are different + expect(source1).to.not.be.equal(source2); + + // check if the retrieved source is the same as the created one + expect(source1).to.be.equal(retrieved); + }); + + it("should be able to create and retrieve aggregates", () => { + const server = new Server(); + + // create two aggregates + const aggr1 = server.aggregate(["met:one"], ["dim:one", "dim:two"]); + const aggr2 = server.aggregate(["met:two"], ["dim:one", "dim:two"]); + + // retrieve the first one + const retrieved = server.aggregate(["met:one"], ["dim:two", "dim:one"]); + + // check if aggregates were actually created/retrieved + expect(aggr1).to.be.an("object"); + expect(aggr2).to.be.an("object"); + expect(retrieved).to.be.an("object"); + + // check if the two created aggregates are different + expect(aggr1).to.not.be.equal(aggr2); + + // check if the retrieved aggregate is the same as the created one + expect(aggr1).to.be.equal(retrieved); + }); + + it("should be able to create and retrieve transformers", () => { + const server = new Server(); + + const source1 = server.source("source1"); + const aggr1 = server.aggregate(["met:one"], ["dim:one", "dim:two"]); + const aggr2 = server.aggregate(["met:one", "met:two"], ["dim:one"]); + + // create two transformers + const transformer1 = server.transformer("transformer1", { + source: source1, + destination: aggr1, + functions: { + map: (doc: any, emit: Function) => { return; }, + reduce: (dimensions: any, metrics: any) => { return {}; } + } + }); + const transformer2 = server.transformer("transformer2", { + source: source1, + destination: aggr2, + functions: { + map: (doc: any, emit: Function) => { return; }, + reduce: (dimensions: any, metrics: any) => { return {}; } + } + }); + + // retrieve the first one + const retrieved = server.transformer("transformer1"); + + // check if transformers were actually created/retrieved + expect(transformer1).to.be.an("object"); + expect(transformer2).to.be.an("object"); + expect(retrieved).to.be.an("object"); + + // check if the two created transformers are different + expect(transformer1).to.not.be.equal(transformer2); + + // check if the retrieved transformer is the same as the created one + expect(transformer1).to.be.equal(retrieved); + }); + + it("should fail to create two transformer with name collision", () => { + const server = new Server(); + + const source1 = server.source("source1"); + const aggr1 = server.aggregate(["met:one"], ["dim:one", "dim:two"]); + const aggr2 = server.aggregate(["met:one", "met:two"], ["dim:one"]); + + server.transformer("transformer1", { + source: source1, + destination: aggr1, + functions: { + map: (doc: any, emit: Function) => { return; }, + reduce: (dimensions: any, metrics: any) => { return {}; } + } + }); + + expect(() => { + server.transformer("transformer1", { + source: source1, + destination: aggr2, + functions: { + map: (doc: any, emit: Function) => { return; }, + reduce: (dimensions: any, metrics: any) => { return {}; } + } + }); + }).to.throw(Error); + }); + + it("should fail to retrieve a transformer that doesn't exist", () => { + const server = new Server(); + + expect(() => { + server.transformer("transformerX"); + }).to.throw(Error); + }); +}); diff --git a/src/core/server.ts b/src/core/server.ts new file mode 100644 index 0000000000000000000000000000000000000000..235cbca2bcbe488b6eaacb8dc34c8969e00583ee --- /dev/null +++ b/src/core/server.ts @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blend. + * + * blend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blend. If not, see <http://www.gnu.org/licenses/>. + */ + +import { Hash } from "../util/hash"; + +import { Source } from "./source"; +import { Transformer, ITransformerOptions } from "./transformer"; +import { Aggregate } from "./aggregate"; + +export class Server { + private sources: Map<string, Source>; + private transformers: Map<string, Transformer>; + private aggregates: Map<string, Aggregate>; + + constructor() { + this.sources = new Map(); + this.transformers = new Map(); + this.aggregates = new Map(); + } + + public source(name: string, options?: any) { + if (this.sources.has(name)) { + return this.sources.get(name); + } + else { + const source = new Source(name, options); + this.sources.set(name, source); + return source; + } + } + + public aggregate(metrics: string[], dimensions: string[], options?: any) { + const id = Hash.sha1(metrics.sort(), dimensions.sort()); + + if (this.aggregates.has(id)) { + return this.aggregates.get(id); + } + else { + const aggregate = new Aggregate(metrics, dimensions, options); + this.aggregates.set(id, aggregate); + return aggregate; + } + } + + public transformer(name: string, options?: ITransformerOptions) { + if (typeof options !== "undefined") { + if (this.transformers.has(name)) { + throw new Error("A transformer named '" + name + "' already exists"); + } + + const transformer = new Transformer(name, options); + this.transformers.set(name, transformer); + return transformer; + } + else { + if (!this.transformers.has(name)) { + throw new Error("A transformer named '" + name + "' does not exist"); + } + + return this.transformers.get(name); + } + } +} diff --git a/src/core/source.ts b/src/core/source.ts index bd8704f686a08c693472f236fe161a33d3f3ee98..f030c5660300275aeb7afc12b83ad5a5d159d603 100644 --- a/src/core/source.ts +++ b/src/core/source.ts @@ -18,139 +18,27 @@ * along with blendb. If not, see <http://www.gnu.org/licenses/>. */ -import { DataType } from "../common/types"; -import { EnumHandler } from "../util/enumHandler"; - -/** Attribute of a source. */ -export interface Field { - /** Field name. */ - name: string; - /** Brief description of what this field represent. */ - description?: string; - /* Field data type. */ - dataType: DataType; - /* Enumerable type name, used if data type is enumerable type. */ - enumType?: string; -} - -/** Field definition used in configuration file. */ -export interface FieldStr { - /** Field name. */ - name: string; - /** Brief description of what this field represent. */ - description?: string; - /* Field data type. */ - dataType: string; - /* Field enum type. */ - enumType?: string; -} - -/** Parameters used to create a source object. */ -export interface SourceOptions { - /** Source name. */ - name: string; - /** Brief description of what this source represent. */ - description?: string; - /** Set of fields that define the attributes of this source. */ - fields: Field[]; -} - -/** - * Parameters used to define source object in the configuration file. - * Also the string description of a source. - */ -export interface SourceStrOptions { - /** Source name. */ - name: string; - /** Brief description of what this field represent. */ - description?: string; - /** Set of fields that define the attributes of this source. */ - fields: FieldStr[]; -} - -/** - * A definition of a "object" that can be inserted into BlenDB. - * To perform a insertion in the database is required to know "what" - * is being inserted. This "what" is a source object that is - * nothing more than a set o attributes (called fields) and - * a identifier (called name). - */ export class Source { - /** Source name. */ - public readonly name: string; - /** Brief description of what this field represent. */ - public readonly description: string; - /** Set of fields that define the attributes of this source. */ - public readonly fields: Field[]; + public name: string; + private data: any[]; - /** - * Create a source. - * @param options - Parameters required to create a source. - */ - constructor(options: SourceOptions) { - this.name = options.name; - this.description = (options.description) ? options.description : ""; - this.fields = options.fields.map((item) => { - return { - name: item.name, - description: (item.description) ? item.description : "", - dataType: item.dataType, - enumType: (item.enumType) ? item.enumType : "" - }; - }); + constructor(name: string, options?: any) { + this.name = name; + + this.data = []; } - /** - * Created a object with the same options used to create this - * source as strings. Used to inform the API users. - */ - public strOptions(): SourceStrOptions { - return { - name: this.name, - description: this.description, - fields: Source.stringfyFieldDataType(this.fields), - }; + public push(doc: any) { + this.data.push(doc); } - /** - * Created a set of objects with the same options used to create the - * given fields as strings. Used to inform the API users. - * @param opts - Set of fields to be put in string struct. - */ - public static stringfyFieldDataType(opts: Field[]): FieldStr[] { - let str: FieldStr[]; - str = opts.map((i) => { - let o: FieldStr = { - name: i.name, - description: i.description, - dataType: EnumHandler.stringfyDataType(i.dataType) - }; - if (i.dataType === DataType.ENUMTYPE) { - o.enumType = i.enumType; - } - return o; + public forEach(callback: Function) { + this.data.forEach((value: any, index: number, array: any[]) => { + callback(value); }); - - return str; } - /** - * Created a set of fields given its options. - * @param opts - Set of fields in string struct. - */ - public static parseFieldDataType(opts: FieldStr[]): Field[] { - let str: Field[]; - str = opts.map((i) => { - let o: Field = { - name: i.name, - description: i.description, - dataType: EnumHandler.parseDataType(i.dataType), - }; - if (o.dataType === DataType.ENUMTYPE){ - o.enumType = i.enumType; - } - return o; - }); - return str; + public truncate() { + this.data = []; } } diff --git a/src/core/transformer.spec.ts b/src/core/transformer.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..003deec9c3f582199dc5d7ae15bcc49efe3eac12 --- /dev/null +++ b/src/core/transformer.spec.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blendb. + * + * blendb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blendb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blendb. If not, see <http://www.gnu.org/licenses/>. + */ + +import { expect } from "chai"; + +import { Hash } from "../util/hash"; + +import { Transformer } from "./transformer"; +import { Source } from "./source"; +import { Aggregate } from "./aggregate"; + +describe("transformer class", () => { + const source = new Source("testSource"); + const aggregate = new Aggregate(["met:one"], ["dim:one", "dim:two"]); + + it("should be able to aggregate data", () => { + source.truncate(); + + for (let i = 0; i < 1000; i++) { + source.push({ + id: i % 10, + seed: Math.random() + }); + } + + source.push({ id: 10, seed: 5 }); + source.push({ id: 10, seed: 5 }); + source.push({ id: 10, seed: 5 }); + source.push({ id: 10, seed: 5 }); + source.push({ id: 10, seed: 5 }); + + const transformer = new Transformer("processTransformer", { + source: source, + destination: aggregate, + functions: { + map: ((doc: any, emit: Function) => { + emit({ + "dim:one": doc.id, + "dim:two": Hash.sha1(doc.seed) + }, { + "met:one": Math.floor(doc.seed * 100000) / 100 + }); + }), + reduce: ((dimensions: any, metrics: any) => { + let tmp = 0; + metrics.forEach((met: any) => { + tmp += met["met:one"]; + }); + return { + "met:one": tmp + }; + }) + } + }); + + transformer.apply(); + + let result = aggregate.find({ + "dim:one": 10, + "dim:two": Hash.sha1(5) + }); + + expect(result).to.have.length(1); + expect(result[0]).to.have.property("metrics"); + expect(result[0].metrics).to.have.property("met:one"); + expect(result[0].metrics["met:one"]).to.be.equal(25000); + }); +}); diff --git a/src/core/transformer.ts b/src/core/transformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3c6734cde7b6939e72619d2e3f399dfa9613153 --- /dev/null +++ b/src/core/transformer.ts @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blendb. + * + * blendb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blendb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blendb. If not, see <http://www.gnu.org/licenses/>. + */ + +import { Hash } from "../util/hash"; + +import { Source } from "./source"; +import { Aggregate } from "./aggregate"; + +export interface ITransformerOptions { + source: Source; + destination: Aggregate; + functions: { + map: (doc: any, emit: Function) => void; + reduce: (dimensions: any, metrics: any) => any; + }; +} + +export class Transformer { + public name: string; + public source: Source; + public destination: Aggregate; + private functions: any; + + constructor(name: string, options: ITransformerOptions) { + this.name = name; + this.source = options.source; + this.destination = options.destination; + this.functions = { + map: options.functions.map, + reduce: options.functions.reduce + }; + } + + public apply() { + let temp = new Map(); + + this.destination.truncate(); + + this.source.forEach((doc: any) => { + let emit = (dimensions: any, metrics: any) => { + let key = Hash.sha1(dimensions); + let current = temp.get(key) || { dimensions, metrics: [] }; + temp.set(key, { + dimensions, + metrics: current.metrics.concat([metrics]) + }); + }; + + this.functions.map(doc, emit); + }); + + temp.forEach((value, key) => { + let dimensions = value.dimensions; + let metrics = value.metrics; + + if (metrics.length > 1) { + this.destination.push({ + dimensions: dimensions, + metrics: this.functions.reduce(dimensions, metrics) + }); + } + else { + this.destination.push({ + dimensions: dimensions, + metrics: metrics + }); + } + }); + } +} diff --git a/src/core/view.ts b/src/core/view.ts index 4f54013d24ad0bd2ee823cabd1f4ad4473b7da73..7634a8fe8e8548c520286a7185b37ead7f7a8942 100644 --- a/src/core/view.ts +++ b/src/core/view.ts @@ -22,78 +22,44 @@ import { Dimension } from "./dimension"; import { Metric } from "./metric"; import { Hash } from "../util/hash"; import { Clause } from "./clause"; -import { Operation, Opcode } from "../common/expression"; -/** Information required to load fixture data into the view. */ export interface LoadView { - /** View where the fixture data will be load. */ view: View; - /** Path to a file with fixture data. */ data: string; } -/** Parameters used to create a view object. */ export interface ViewOptions { - /** Set of metrics contained into the view. */ metrics: Metric[]; - /** Set of dimension contained into the view. */ dimensions: Dimension[]; - /** Inform if this view cannot be generated by other views. */ + keys?: Dimension[]; origin: boolean; - /** Set of clauses applied to the view. */ clauses?: Clause[]; - /** List with the sorting order of the attributes. */ - sort?: (Metric|Dimension)[]; - /** Definition of how to create this view using other views. */ - operation?: Operation; - /** Defines if views's name will be its alias or automatically generated. */ - aliasAsName?: boolean; - /** Fake identifier (human understandable) of the view. */ - alias?: string; + materialized?: boolean; + childViews?: View[]; } -/** - * Representation of data location in the BlenDB perspective. - * Readable data are represented by metrics and dimensions and - * these objects can only be found in views. - */ export class View { - /** Hash of components that unique identify the view. */ public readonly id: string; - /** Set of metrics contained into the view. */ public readonly metrics: Metric[]; - /** Set of dimension contained into the view. */ public readonly dimensions: Dimension[]; - /** Set of clauses applied to the view. */ + public readonly keys: Dimension[]; public readonly clauses: Clause[]; - /** List with the sorting order of the attributes. */ - public readonly sort: (Metric|Dimension)[]; - /** Inform if this view cannot be generated by other views. */ + public readonly materialized: boolean; public readonly origin: boolean; - /** Definition of how to create this view using other views. */ - public readonly operation: Operation; - /** View identifier, used on query generation as "table" name */ - public readonly name: string; + public childViews: View[]; - /** - * Create a view. - * @param options - Parameters required to create a view. - */ constructor (options: ViewOptions) { this.metrics = options.metrics.sort(); this.dimensions = options.dimensions.sort(); this.clauses = (options.clauses) ? options.clauses.sort() : []; - this.sort = (options.sort) ? options.sort : []; + this.materialized = options.materialized || false; this.origin = options.origin || false; - if (options.operation) { - this.operation = options.operation; + this.childViews = (options.childViews) ? options.childViews : []; + if (options.keys && options.keys.length > 0) { + this.keys = options.keys.sort(); } - else { - this.operation = { - opcode: Opcode.PUSH, - values: [] - }; + this.keys = this.dimensions; } // calculate the id of the view based on it's metrics and dimensions @@ -102,13 +68,5 @@ export class View { const clausesIds = this.clauses.map((clause) => clause.id); const join = metNames.concat(dimNames).concat(clausesIds).sort(); this.id = Hash.sha1(join); - - if ( options.aliasAsName ) { - this.name = "\"" + options.alias + "\""; - } else { - this.name = "view_" + this.id; - } - } - } diff --git a/src/main.ts b/src/main.ts index a9dd223ec936fd1f7d5c8276b201c48aac131a30..9839e1cc15741ea4c3d9e0a41bd40f80e22a1b45 100755 --- a/src/main.ts +++ b/src/main.ts @@ -21,57 +21,31 @@ // external libraries import express = require("express"); -/** @hidden */ const osprey = require("osprey"); -/** @hidden */ const ramlParser = require("raml-parser"); // load router import { router } from "./api/router-v1"; // create a new express app -/** @hidden */ const app = module.exports = express(); // Load configuration file import { ConfigParser } from "./util/configParser"; - -let configPath; - -/** @hidden */ -if (process.env.BLENDB_SCHEMA_FILE) { - configPath = process.env.BLENDB_SCHEMA_FILE; -} -else{ - throw new Error("BLENDB_SCHEMA_FILE wasn't informed"); -} - -/** @hidden */ +const configPath = (app.get("env") === "test") ? "config/test.yaml" : "config/config.yaml"; const config = ConfigParser.parse(configPath); // include middlewares +import * as cors from "cors"; + import { EngineMw } from "./api/middlewares/engine"; -import { PostgresMw, MonetMw } from "./api/middlewares/adapter"; +import { PostgresMw } from "./api/middlewares/adapter"; import { ErrorMw } from "./api/middlewares/error"; -import { CsvMw } from "./api/middlewares/csv"; -import { LogMw } from "./api/middlewares/log" +app.use(cors()); app.use(EngineMw(config)); -app.use(CsvMw()); -app.use(LogMw()); -if (config.adapters[0] === "postgres") { - app.use(PostgresMw(config.connections[0])); -} - -else if (config.adapters[0] === "monet") { - app.use(MonetMw(config.connections[0])); -} - -else { - console.error("Invalid adapter. Options available are: postgres and monet"); - process.exit(1); -} +app.use(PostgresMw(config.connection)); // parse the RAML spec and load osprey middleware ramlParser.loadFile("specs/blendb-api-v1.raml") diff --git a/src/util/configParser.spec.ts b/src/util/configParser.spec.ts index 48844895d53faa192bdb105bba05237888e612bc..973bad91619ac6d3f99fe340d36a7c598e1b072a 100644 --- a/src/util/configParser.spec.ts +++ b/src/util/configParser.spec.ts @@ -19,13 +19,10 @@ */ import { expect } from "chai"; + import { ConfigParser, ViewParsingOptions } from "./configParser"; import { Dimension, DimensionStrOptions } from "../core/dimension"; -import { RelationType , DataType} from "../common/types"; -import { EnumType } from "../core/enumType"; -import { EnumHandler } from "../util/enumHandler"; -import { MetricStrOptions } from "../core/metric"; -import { SourceStrOptions } from "../core/source"; +import { RelationType } from "../common/types"; function strToRelationType (str: string): RelationType { switch (str) { @@ -35,6 +32,8 @@ function strToRelationType (str: string): RelationType { return RelationType.MONTH; case "year": return RelationType.YEAR; + case "dayofweek": + return RelationType.DAYOFWEEK; default: return RelationType.NONE; } @@ -56,8 +55,7 @@ describe("configParser utility library", () => { catch (e) { error = true; expect(e.message).to.be - .equal("[Parsing error] Metric: 'met:-1' do not exist on view: Test." + - " Review configuration files."); + .equal("[Parsing error] Non exist metric set to view " + opts.alias); } expect(error).to.be.true; @@ -78,8 +76,7 @@ describe("configParser utility library", () => { catch (e) { error = true; expect(e.message).to.be - .equal("[Parsing error] Dimension: 'dim:-1' do not exist on view: Test." + - " Review configuration files."); + .equal("[Parsing error] Non exist dimension set to view " + opts.alias); } expect(error).to.be.true; @@ -97,13 +94,12 @@ describe("configParser utility library", () => { let error: boolean = false; try { - ConfigParser.parseDimOpts(opts, dims, null, null); + ConfigParser.parseDimOpts(opts, dims); } catch (e) { error = true; expect(e.message).to.be - .equal("[Parsing error] Dimension has been defined with invalid Parent for subdimension: 'dim:-1'." + - " Review Parent spelling in dimension and configuration files."); + .equal("[Parsing error] Parent for subdimension " + opts.name + " not found"); } expect(error).to.be.true; @@ -120,7 +116,7 @@ describe("configParser utility library", () => { }; let dimMap: {[key: string]: Dimension} = { - "dim:0" : new Dimension({name: "dim:0", dataType: DataType.INTEGER}) + "dim:0" : new Dimension({name: "dim:0", dataType: "integer"}) }; let error: boolean = false; @@ -148,7 +144,7 @@ describe("configParser utility library", () => { }; let dimMap: {[key: string]: Dimension} = { - "dim:0" : new Dimension({name: "dim:0", dataType: DataType.INTEGER}) + "dim:0" : new Dimension({name: "dim:0", dataType: "integer"}) }; let error: boolean = false; @@ -185,169 +181,32 @@ describe("configParser utility library", () => { parent: "dim:0", relation: "year" }, + { + name: "dim:dayofweek", + dataType: "integer", + parent: "dim:0", + relation: "dayofweek" + }, { name: "dim:none", dataType: "integer", parent: "dim:0", relation: "none" - } + }, ]; let dims: Dimension[] = [ - new Dimension({name: "dim:a", dataType: DataType.DATE}), - new Dimension({name: "dim:0", dataType: DataType.DATE}) + new Dimension({name: "dim:a", dataType: "date"}), + new Dimension({name: "dim:0", dataType: "date"}) ]; for (let i = 0; i < opts.length; ++i) { - let parsed = ConfigParser.parseDimOpts(opts[i], dims, null, null); + let parsed = ConfigParser.parseDimOpts(opts[i], dims); expect(parsed.name).to.be.equal(opts[i].name); - expect(EnumHandler.stringfyDataType(parsed.dataType)).to.be.equal(opts[i].dataType); + expect(parsed.dataType).to.be.equal(opts[i].dataType); expect(parsed.parent).to.be.equal(dims[1]); expect(parsed.relation).to.be.equal(strToRelationType(opts[i].relation)); } }); - it("should parse correctly enumType with dimension", () => { - - let opts: DimensionStrOptions = { - name: "dim:day", - dataType: "enumtype", - enumType: "enumtype:5", - parent: "dim:0", - relation: "day" - }; - let dims: Dimension[] = [ - new Dimension({name: "dim:0", dataType: DataType.DATE}) - ]; - let enumMap: {[key: string]: EnumType} = { - "enumtype:5" : new EnumType({name: "enumtype:5", values: ["nope", "test"]}) - }; - let parsed = ConfigParser.parseDimOpts(opts, dims, enumMap, null); - - expect(parsed.enumType).to.be.equal(enumMap["enumtype:5"].name); - }); - - it("should fail to parse enumType with dimension", () => { - - let opts: DimensionStrOptions = { - name: "dim:day", - dataType: "enumtype:4", - parent: "dim:0", - relation: "day" - }; - let dims: Dimension[] = [ - new Dimension({name: "dim:0", dataType: DataType.INTEGER}) - ]; - let enumMap: {[key: string]: EnumType} = { - "enumtype:5" : new EnumType({name: "enumtype:5", values: ["nope", "test"]}) - }; - let error: boolean = false; - try { - ConfigParser.parseDimOpts(opts, dims, enumMap, null); - } - catch (e) { - error = true; - expect(e.message).to.be - .equal("[Parsing error] Dimension has been defined with invalid DataType: 'enumtype:4'." + - " Review DataType spelling in dimension and configuration files."); - } - expect(error).to.be.true; - - }); - - it("should fail to parse dataType with Metrics", () => { - let met: MetricStrOptions; - met = { - name: "met:0", - aggregation: "sum", - dataType: "string", - description: "just for test" - }; - let error: boolean = false; - try { - ConfigParser.parseMetOpts(met, null); - } - catch (e) { - error = true; - expect(e.message).to.be - .equal("[Parsing error] Metrics has been defined with invalid DataType: 'string'." + - " Review DataType spelling in metrics and configuration files"); - } - expect(error).to.be.true; - - }); - it("should fail to parse enumType with Source", () => { - let sourc: SourceStrOptions; - sourc = { - name: "source_10", - description: "source used for test only", - fields: [ - {name: "fields:0", - description: "first entry", - dataType: "string"}, - {name: "fields:1", - description: "second entry", - dataType: "enumtype", - enumType: "enumtype:10"} - ] - }; - let enumMap: {[key: string]: EnumType} = { - "enumtype:5" : new EnumType({name: "enumtype:5", values: ["nope", "test"]}) - }; - let error: boolean = false; - try { - ConfigParser.parseSourceOpts(sourc, enumMap); - } - catch (e) { - error = true; - expect(e.message).to.be - .equal("[Parsing error] EnumType has been defined with invalid DataType: 'enumtype:10'." + - " Review EnumType spelling in source and configuration files"); - } - expect(error).to.be.true; - }); - - it("should throw expection for inexistent tag in a Dimension", () => { - let opts: DimensionStrOptions = { - name: "dim:0", - dataType: "integer", - tags: ["none"] - }; - - let dims: Dimension[] = []; - - let error: boolean = false; - try { - ConfigParser.parseDimOpts(opts, dims, null, {}); - } - catch (e) { - error = true; - expect(e.message).to.be - .equal("[Parsing error] Tag: 'none' used in dimension: '" + opts.name + "' was not defined. Check tag spelling and configuration files."); - } - - expect(error).to.be.true; - }); - - it("should throw expection for inexistent tag in a Metric", () => { - let opts: MetricStrOptions = { - name: "met:0", - dataType: "integer", - aggregation: "avg", - tags: ["none"] - }; - - let error: boolean = false; - try { - ConfigParser.parseMetOpts(opts, {}); - } - catch (e) { - error = true; - expect(e.message).to.be - .equal("[Parsing error] Tag: 'none' used in metric: '" + opts.name + "' was not defined. Check tag spelling and configuration files."); - } - - expect(error).to.be.true; - }); - }); diff --git a/src/util/configParser.ts b/src/util/configParser.ts index 6b2aeeafb4673903a97612cf638932409850dd7d..44acd872626919d3f8713ae6aa47121e9fe612ec 100644 --- a/src/util/configParser.ts +++ b/src/util/configParser.ts @@ -21,287 +21,99 @@ import { Metric, MetricOptions, MetricStrOptions } from "../core/metric"; import { Dimension, DimensionOptions, DimensionStrOptions } from "../core/dimension"; import { View, ViewOptions, LoadView } from "../core/view"; -import { EnumType, EnumTypeOptions } from "../core/enumType"; -import { RelationType, DataType } from "../common/types"; -import { Opcode } from "../common/expression"; -import { Tag, TagOptions } from "../common/tag"; +import { RelationType } from "../common/types"; import { Filter } from "../core/filter"; import { Clause } from "../core/clause"; -import { Source, SourceOptions, SourceStrOptions} from "../core/source"; -import { Tsort, TsortDep } from "./tsort"; +import { PoolConfig } from "pg"; import * as fs from "fs"; import * as yaml from "js-yaml"; -import { EnumHandler } from "./enumHandler"; -/** - * Parameters used to define view object in the configuration file. - */ export interface ViewParsingOptions { - /** Fake identifier (human understandable) of the view. */ alias: string; - /** Path to file with fixture data. */ - data?: string; - /** Path to file SQL view build code. */ + data: string; file?: string; - /** Inform if this view cannot be generated by other views. */ origin?: boolean; - /** Set of references (name) to dimension contained into the view. */ dimensions: string[]; - /** Set of references (name) to metrics contained into the view. */ metrics: string[]; - /** Set of (stringified) clauses applied to the view. */ clauses?: string[]; - /** Inform if the view's name will be it's alias or id. */ - aliasAsName?: boolean; + keys?: string[]; } -/** - * Representation of the configuration file. - */ interface ConfigSchema { - /** Options of all sources available */ - sources: { obj: SourceStrOptions[], - links: string[], - }; - /** Options of all views available */ - views: { obj: ViewParsingOptions[], - links: string[], - }; - /** Options of all metrics available */ - metrics: { obj: MetricStrOptions[], - links: string[], - }; - /** Options of all dimensions available */ - dimensions: { obj: DimensionStrOptions[], - links: string[], - }; - /** Options of all enumerable types available */ - enumTypes: { obj: EnumTypeOptions[], - links: string[], - }; - /** Options of all tags types available */ - tags: { obj: TagOptions[], - links: string[], - }; + views: ViewParsingOptions[]; + metrics: MetricStrOptions[]; + dimensions: DimensionStrOptions[]; +} + +interface ConfigFile { + connection: PoolConfig; + struct: LoadStruct; + schema: ConfigSchema; } -/** Information required to build a SQL view code. */ interface BuildView { - /** View to be built. */ view: View; - /** Path to file with SQL view code. */ file: string; - /** Human understandable identifier. */ alias: string; } +export interface LoadStruct{ + create: boolean; + insert: boolean; +} + export interface ParsedConfig { - /** What adapters are in use. */ - adapters: string[]; - /** Connections parameters to connect in the database. */ - connections: Connection[]; - /** Set of all views available. */ + connection: PoolConfig; views: View[]; - /** Set of all sources available. */ - sources: Source[]; - /** Set of all metrics available. */ metrics: Metric[]; - /** Set of all enumerable types available. */ - enumTypes: EnumType[]; - /** Set of all tags available. */ - tags: Tag[]; - /** Set of all dimensions available. */ dimensions: Dimension[]; + struct: LoadStruct; loadViews: LoadView[]; - /** SQL views build configuration. */ buildViews: BuildView[]; - /** Quantity of database */ - ndb: number; -} - -/** Required information to connect in a generic database. */ -export interface Connection { - /** Database user. */ - user: string; - /** Database name. */ - database: string; - /** Database password. */ - password: string; - /** Database hostname. */ - host: string; - /** Database port. */ - port: number; } -/** Dictonary indexed by dimension name, that returns the dimension object. */ interface DimensionMap { [key: string]: Dimension; } -/** Dictonary indexed by dimension name, that returns the dimension options. */ -interface DimensionOptsMap { - [key: string]: DimensionStrOptions; -} - -/** Dictonary indexed by metric name, that returns the metric object. */ interface MetricMap { [key: string]: Metric; } -/** Dictonary indexed by tag name, that returns the tag object. */ -interface TagMap { - [key: string]: Tag; -} - -/** - * Dictonary indexed by enumerable type name, - * that returns the enumerable type objetct. - */ -interface EnumTypeMap{ - [key: string]: EnumType; -} - -/** - * Dictonary indexed by source type name, - * that returns the source objetct. - */ -interface SourceMap { - [key: string]: Source; -} - -/** - * Responsable for reading the configuration file, parse its - * string structures in internal objects understable by BlenDB. - */ export class ConfigParser { - /** - * Parse the configuration file. - * @param configPath - Path to configuration file. - */ public static parse(configPath: string): ParsedConfig { - let config: ConfigSchema = yaml.safeLoad(fs.readFileSync(configPath, { + let config: ConfigFile = yaml.safeLoad(fs.readFileSync(configPath, { encoding: "utf-8" - })) as ConfigSchema; - - let connections: Connection[] = []; - - let ndb: number = parseInt(process.env.BLENDB_N_DB, 10) ? parseInt(process.env.BLENDB_N_DB, 10) : 1; - let adapters: string[] = []; - for ( let i = 0; i < ndb ; i++ ){ - adapters[i] = process.env["BLENDB_DB" + i + "_ADAPTER"]; - connections[i] = { - user: process.env["BLENDB_DB" + i + "_USER"], - database: process.env["BLENDB_DB" + i + "_NAME"], - password: process.env["BLENDB_DB" + i + "_PASSWORD"], - host: process.env["BLENDB_DB" + i + "_HOST"], - port: parseInt(process.env["BLENDB_DB" + i + "_PORT"], 10) - }; - } + })) as ConfigFile; - let metricsOpts = (config.metrics) ? config.metrics.obj : []; - let viewsOpts = (config.views) ? config.views.obj : []; - let dimensionsOpts = (config.dimensions) ? config.dimensions.obj : []; - let enumTypesOpts = (config.enumTypes) ? config.enumTypes.obj : []; - let sourcesOpts = (config.sources) ? config.sources.obj : []; - let tagOpts = (config.tags) ? config.tags.obj : []; + let metricsOpts = config.schema.metrics; + let viewsOpts = config.schema.views; + let dimensionsOpts = config.schema.dimensions; let parsed: ParsedConfig = { - adapters: adapters, - connections: connections, + connection: config.connection, views: [], metrics: [], - enumTypes: [], dimensions: [], + struct: config.struct, loadViews: [], - buildViews: [], - sources: [], - tags: [], - ndb: ndb - }; - - for (let i = 0; i < config.sources.links.length; i++) { - sourcesOpts = sourcesOpts.concat(yaml.safeLoad(fs.readFileSync( - config.sources.links[i], { encoding: "utf-8"})) as SourceStrOptions[]); - } - for (let i = 0; i < config.views.links.length; i++) { - viewsOpts = viewsOpts.concat(yaml.safeLoad(fs.readFileSync( - config.views.links[i], { encoding: "utf-8"})) as ViewParsingOptions[]); - } - for (let i = 0; i < config.metrics.links.length; i++) { - metricsOpts = metricsOpts.concat(yaml.safeLoad(fs.readFileSync( - config.metrics.links[i], { encoding: "utf-8"})) as MetricStrOptions[]); - } - for (let i = 0; i < config.dimensions.links.length; i++) { - dimensionsOpts = dimensionsOpts.concat(yaml.safeLoad(fs.readFileSync( - config.dimensions.links[i], { encoding: "utf-8"})) as DimensionStrOptions[]); - } - for (let i = 0; i < config.enumTypes.links.length; i++) { - enumTypesOpts = enumTypesOpts.concat(yaml.safeLoad(fs.readFileSync( - config.enumTypes.links[i], { encoding: "utf-8"})) as EnumTypeOptions[]); - } - for (let i = 0; i < config.tags.links.length; i++) { - tagOpts = tagOpts.concat(yaml.safeLoad(fs.readFileSync( - config.tags.links[i], { encoding: "utf-8"})) as TagOptions[]); - } + buildViews: [] + }; let metMap: MetricMap = {}; let dimMap: DimensionMap = {}; - let enumMap: EnumTypeMap = {}; - let sourcMap: SourceMap = {}; - let dimOptsMap: DimensionOptsMap = {}; - let tagMap: TagMap = {}; - - for (let i = 0; i < tagOpts.length; i++) { - let tag = new Tag((tagOpts[i])); - parsed.tags.push(tag); - tagMap[tag.name] = tag; - } - for (let i = 0; i < enumTypesOpts.length; i++) { - let enumT = new EnumType((enumTypesOpts[i])); - parsed.enumTypes.push(enumT); - enumMap[enumT.name] = enumT; - } + for (let i = 0; i < metricsOpts.length; ++i) { - let met = new Metric(this.parseMetOpts(metricsOpts[i], tagMap)); + let met = new Metric(this.parseMetOpts(metricsOpts[i])); parsed.metrics.push(met); metMap[met.name] = met; } - let toSort: TsortDep[] = []; - for (let i = 0; i < dimensionsOpts.length; ++i) { - if (dimensionsOpts[i].parent) { - toSort.push({ - value: dimensionsOpts[i].name, - dependOf: dimensionsOpts[i].parent - }); - } - - else { - toSort.push({ - value: dimensionsOpts[i].name - }); - } - - dimOptsMap[dimensionsOpts[i].name] = dimensionsOpts[i]; - } - - dimensionsOpts = Tsort.dependencies(toSort).filter((name) => { - return (dimOptsMap[name]) ? true : false; - }).map((name) => { - return dimOptsMap[name]; - }); - for (let i = 0; i < dimensionsOpts.length; ++i) { - let dim = new Dimension(this.parseDimOpts(dimensionsOpts[i], parsed.dimensions, enumMap, tagMap)); + let dim = new Dimension(this.parseDimOpts(dimensionsOpts[i], parsed.dimensions)); parsed.dimensions.push(dim); dimMap[dim.name] = dim; } - for (let i = 0; i < sourcesOpts.length; i++) { - let sourc = new Source(this.parseSourceOpts(sourcesOpts[i], enumMap)); - parsed.sources.push(sourc); - sourcMap[sourc.name] = sourc; - } - for (let i = 0; i < viewsOpts.length; ++i) { if (!viewsOpts[i].metrics) { viewsOpts[i].metrics = []; @@ -320,15 +132,8 @@ export class ConfigParser { } return parsed; - } - /** - * Parse a view struct in configuration file. - * @param opts - View struct in configuration file. - * @param metMap - Dictionary with available metrics. - * @param dimMap - Dictionary with available dimensions. - */ public static parseViewOpt(opts: ViewParsingOptions, metMap: MetricMap, dimMap: DimensionMap): ViewOptions { @@ -336,26 +141,23 @@ export class ConfigParser { let viewOpt: ViewOptions = { metrics: [], dimensions: [], + materialized: true, origin: opts.origin, - alias: (opts.alias) ? opts.alias : "", + childViews: [], clauses: [], - aliasAsName: (opts.aliasAsName) ? opts.aliasAsName : false, - operation: { - opcode: Opcode.PUSH, - values: [] - } + keys: [] }; + const keys = (opts.keys) ? opts.keys : []; + for (let i = 0; i < opts.metrics.length; ++i) { if (metMap[opts.metrics[i]]) { viewOpt.metrics.push(metMap[opts.metrics[i]]); } else { - throw new Error("[Parsing error] Metric: '" + opts.metrics[i] + "' do not exist on view: " + opts.alias + - ". Review configuration files."); + throw new Error("[Parsing error] Non exist metric set to view " + opts.alias); } - } for (let i = 0; i < opts.dimensions.length; ++i) { @@ -364,8 +166,17 @@ export class ConfigParser { } else { - throw new Error("[Parsing error] Dimension: '" + opts.dimensions[i] + "' do not exist on view: " + opts.alias + - ". Review configuration files."); + throw new Error("[Parsing error] Non exist dimension set to view " + opts.alias); + } + } + + for (let i = 0; i < keys.length; ++i) { + if (dimMap[keys[i]]) { + viewOpt.keys.push(dimMap[opts.keys[i]]); + } + + else { + throw new Error("[Parsing error] Non exist key set to view " + opts.alias); } } @@ -385,105 +196,40 @@ export class ConfigParser { return viewOpt; } - /** - * Parse a dimension struct in configuration file. - * @param opts - Dimension struct in configuration file. - * @param dims - Parsed dimensions. Parent candidates. - * @param map - Enumerable types available. - * @param tagMap - Tags available. - */ - public static parseDimOpts (opts: DimensionStrOptions, dims: Dimension[], map: EnumTypeMap, tagMap: TagMap): DimensionOptions { - let type = EnumHandler.parseDataType(opts.dataType); - if (type === DataType.NONE) { - throw new Error("[Parsing error] Dimension has been defined with invalid DataType: '" + opts.dataType + - "'. Review DataType spelling in dimension and configuration files."); - } - else if (type === DataType.ENUMTYPE) { - if (!(map[opts.enumType])) { - throw new Error("[Parsing error] Dimension has been defined with invalid EnumType: '" + opts.enumType + - "'. Review Enumtype spelling in dimension and configuration files."); - } - } - let tags: Tag[] = []; - - if (opts.tags) { - tags = opts.tags.map((i) => { - if (!(tagMap[i])) { - throw new Error("[Parsing error] Tag: '" + i + "' used in dimension: '" + opts.name + "' was not defined. Check tag spelling and configuration files."); - } - - return tagMap[i]; - }); - } + public static parseDimOpts (opts: DimensionStrOptions, dims: Dimension[]): DimensionOptions { if (opts.parent || opts.relation) { for (let i = 0; i < dims.length; ++i) { if (dims[i].name === opts.parent) { return { name: opts.name, - dataType: EnumHandler.parseDataType(opts.dataType), + dataType: opts.dataType, description: opts.description, parent: dims[i], - relation: EnumHandler.parseRelationType(opts.relation), - enumType: opts.enumType, - tags: tags + relation: Dimension.parseRelationType(opts.relation) }; } } - throw new Error("[Parsing error] Dimension has been defined with invalid Parent for subdimension: '" + opts.name + - "'. Review Parent spelling in dimension and configuration files."); + throw new Error("[Parsing error] Parent for subdimension " + opts.name + " not found"); } return { name: opts.name, - dataType: EnumHandler.parseDataType(opts.dataType), + dataType: opts.dataType, description: opts.description, parent: null, - relation: RelationType.NONE, - enumType: opts.enumType, - tags: tags + relation: RelationType.NONE }; } - /** - * Parse a metric struct in configuration file. - * @param opts - Metric struct in configuration file. - * @param tagMap - Tags available. - */ - public static parseMetOpts (opts: MetricStrOptions, tagMap: TagMap): MetricOptions { - let type = EnumHandler.parseDataType(opts.dataType); - if (!(type === DataType.FLOAT || type === DataType.INTEGER)){ - - throw new Error("[Parsing error] Metrics has been defined with invalid DataType: '" + opts.dataType + - "'. Review DataType spelling in metrics and configuration files"); - - } - - let tags: Tag[] = []; - - if (opts.tags) { - tags = opts.tags.map((i) => { - if (!(tagMap[i])) { - throw new Error("[Parsing error] Tag: '" + i + "' used in metric: '" + opts.name + "' was not defined. Check tag spelling and configuration files."); - } - - return tagMap[i]; - }); - } + private static parseMetOpts (opts: MetricStrOptions): MetricOptions { return { name: opts.name, - aggregation: EnumHandler.parseAggrType(opts.aggregation), - dataType : EnumHandler.parseDataType(opts.dataType), - description: opts.description, - tags: tags + aggregation: Metric.parseAggrType(opts.aggregation), + dataType : opts.dataType, + description: opts.description }; } - /** - * Parse a clause struct in configuration file. - * @param opts - Clause struct in configuration file. - * @param metMap - Dictionary with available metrics. - * @param dimMap - Dictionary with available dimensions. - */ private static parseClause (opts: string, metMap: MetricMap, dimMap: DimensionMap): Clause { const strFilters = opts.split(","); const filters: Filter[] = strFilters.map((item) => { @@ -499,38 +245,6 @@ export class ConfigParser { return new Clause ({filters: filters}); } - /** - * Parse a source struct in configuration file. - * @param opts - Source struct in configuration file. - * @param map - Dictionary with available enumerable types. - */ - public static parseSourceOpts (opts: SourceStrOptions , map: EnumTypeMap): SourceOptions { - for ( let k = 0; k < opts.fields.length ; k++) { - let type = EnumHandler.parseDataType(opts.fields[k].dataType); - if (type === DataType.NONE) { - throw new Error("[Parsing error] Source has been defined with invalid DataType: '" + opts.fields[k].dataType + - "'. Review DataType spelling in source and configuration files"); - } - else if (type === DataType.ENUMTYPE){ - if (!(map[opts.fields[k].enumType])){ - throw new Error("[Parsing error] EnumType has been defined with invalid DataType: '" + opts.fields[k].enumType + - "'. Review EnumType spelling in source and configuration files"); - } - } - } - return { - name: opts.name, - description: opts.description, - fields : Source.parseFieldDataType(opts.fields), - }; - } - - /** - * Parse a filter struct in configuration file. - * @param opts - Filter struct in configuration file. - * @param metMap - Dictionary with available metrics. - * @param dimMap - Dictionary with available dimensions. - */ private static parseFilter (opts: string, metMap: MetricMap, dimMap: DimensionMap): Filter { const strFilter = Filter.segment(opts); if (!strFilter) { @@ -552,4 +266,5 @@ export class ConfigParser { value: strFilter.value }); } + } diff --git a/src/util/enumHandler.ts b/src/util/enumHandler.ts deleted file mode 100644 index d7a9c245bcbde23874023170922faebd2128a4fc..0000000000000000000000000000000000000000 --- a/src/util/enumHandler.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import {RelationType, DataType , AggregationType} from "../common/types"; - -/** - * Enum's handler. Manage parse through the project. - */ -export class EnumHandler { - - /** - * Parse an enum(Data type) to string. - * @param a - Data type to be stringified. - */ - public static stringfyDataType(a: DataType): string { - switch (a) { - case DataType.INTEGER: - return "integer"; - case DataType.FLOAT: - return "float"; - case DataType.STRING: - return "string"; - case DataType.DATE: - return "date"; - case DataType.BOOLEAN: - return "boolean"; - case DataType.ENUMTYPE: - return "enumtype"; - default: - return ""; - } - } - - /** - * Parse a string to enum(Data Type). - * @param str - Data type in string format. - */ - public static parseDataType (str: string): DataType { - str = str.toLocaleLowerCase(); - switch (str) { - case "integer": - return DataType.INTEGER; - case "float": - return DataType.FLOAT; - case "string": - return DataType.STRING; - case "date": - return DataType.DATE; - case "boolean": - return DataType.BOOLEAN; - case "enumtype": - return DataType.ENUMTYPE; - default: - return DataType.NONE; - } - } - - /** - * Parse a string to enum(Relation Type). - * @param r - Relation in string format. - */ - public static parseRelationType(r: string): RelationType { - switch (r) { - case "day": - return RelationType.DAY; - case "month": - return RelationType.MONTH; - case "year": - return RelationType.YEAR; - default: - return RelationType.NONE; - } - } - - /** - * Parse an enum(Relation Type) to string. - * @param r - Relation to be stringified. - */ - public static stringifyRelationType(r: RelationType): string { - switch (r) { - case RelationType.DAY: - return "day"; - case RelationType.MONTH: - return "month"; - case RelationType.YEAR: - return "year"; - default: - return ""; - } - } - - /** - * Parse an enum(Aggregation Type) to string. - * @param a - Aggregation function to be stringified. - */ - public static stringifyAggrType(a: AggregationType): string { - switch (a) { - case AggregationType.SUM: - return "sum"; - case AggregationType.AVG: - return "avg"; - case AggregationType.COUNT: - return "count"; - case AggregationType.MAX: - return "max"; - case AggregationType.MIN: - return "min"; - default: - return ""; - } - } - - /** - * Parse a string to enum(Aggregation Type). - * @param str - Aggregation function in string format. - */ - public static parseAggrType (str: string): AggregationType { - switch (str) { - case "sum": - return AggregationType.SUM; - case "avg": - return AggregationType.AVG; - case "count": - return AggregationType.COUNT; - case "min": - return AggregationType.MIN; - case "max": - return AggregationType.MAX; - default: - return AggregationType.NONE; - } - } - -} diff --git a/src/util/graph.spec.ts b/src/util/graph.spec.ts index 34f1e18db4e2bebe263cf7f83e5354d62ade3bc3..464dd1dc5ee244f77f9fc4c69b639db04f1c0e91 100644 --- a/src/util/graph.spec.ts +++ b/src/util/graph.spec.ts @@ -26,14 +26,14 @@ import { View } from "../core/view"; import { Filter, FilterOperator } from "../core/filter"; import { Clause } from "../core/clause"; import { Graph } from "./graph"; -import { AggregationType, RelationType, DataType } from "../common/types"; -import { Query, QueryOpts } from "../common/query"; +import { AggregationType, RelationType } from "../common/types"; +import { Query } from "../common/query"; describe("graph class", () => { it("should not create 2 vertices with the same dimension", () => { let g = new Graph(); - let dim = new Dimension({name: "dim:test", dataType: DataType.STRING}); + let dim = new Dimension({name: "dim:test", dataType: "string"}); expect(g.addDimension(dim)).to.be.true; expect(g.addDimension(dim)).to.be.false; @@ -44,7 +44,7 @@ describe("graph class", () => { let met = new Metric({ name: "met:test", aggregation: AggregationType.SUM, - dataType: DataType.STRING + dataType: "string" }); expect(g.addMetric(met)).to.be.true; @@ -67,10 +67,10 @@ describe("graph class", () => { it("should not create a vertex with a subdimension when parent is not a vertex", () => { let g = new Graph(); - let dim = new Dimension({name: "dim:test", dataType: DataType.STRING}); + let dim = new Dimension({name: "dim:test", dataType: "string"}); let subdim = new Dimension({ name: "dim:sub_test", - dataType: DataType.STRING, + dataType: "string", relation: RelationType.MONTH, parent: dim }); @@ -80,10 +80,10 @@ describe("graph class", () => { it("should add a set of views", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.STRING}), - new Dimension({name: "dim:1", dataType: DataType.STRING}), - new Dimension({name: "dim:2", dataType: DataType.STRING}), - new Dimension({name: "dim:3", dataType: DataType.STRING}) + new Dimension({name: "dim:0", dataType: "string"}), + new Dimension({name: "dim:1", dataType: "string"}), + new Dimension({name: "dim:2", dataType: "string"}), + new Dimension({name: "dim:3", dataType: "string"}) ]; let g = new Graph(); @@ -96,17 +96,20 @@ describe("graph class", () => { new View({ metrics: [], dimensions: [dims[0], dims[1]], - origin: true + origin: true, + materialized: true }), new View({ metrics: [], dimensions: [dims[2], dims[3]], - origin: true + origin: true, + materialized: true }), new View({ metrics: [], dimensions: dims, - origin: true + origin: true, + materialized: true }) ]; @@ -117,8 +120,8 @@ describe("graph class", () => { it("should not add a view twice", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.STRING}), - new Dimension({name: "dim:1", dataType: DataType.STRING}), + new Dimension({name: "dim:0", dataType: "string"}), + new Dimension({name: "dim:1", dataType: "string"}), ]; let g = new Graph(); @@ -130,7 +133,8 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0], dims[1]], - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.true; @@ -139,9 +143,9 @@ describe("graph class", () => { it("should not add views when metrics and dimensions are not vertices", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.STRING}), - new Dimension({name: "dim:1", dataType: DataType.STRING}), - new Dimension({name: "dim:2", dataType: DataType.STRING}) + new Dimension({name: "dim:0", dataType: "string"}), + new Dimension({name: "dim:1", dataType: "string"}), + new Dimension({name: "dim:2", dataType: "string"}) ]; let g = new Graph(); @@ -151,7 +155,8 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: dims, - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.false; @@ -163,7 +168,7 @@ describe("graph class", () => { }); it("should add only once a view with only one vertex", () => { - let dim = new Dimension({name: "dim:0", dataType: DataType.STRING}); + let dim = new Dimension({name: "dim:0", dataType: "string"}); let g = new Graph(); @@ -172,7 +177,8 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dim], - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.true; @@ -180,7 +186,7 @@ describe("graph class", () => { }); it("should create a cover for a single vertex", () => { - let dim = new Dimension({name: "dim:0", dataType: DataType.STRING}); + let dim = new Dimension({name: "dim:0", dataType: "string"}); let g = new Graph(); @@ -189,12 +195,12 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dim], - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.true; - const qOpts: QueryOpts = {metrics: [], dimensions: [dim]}; - const query = new Query (qOpts); + const query: Query = { metrics: [], dimensions: [dim] }; let children = g.cover(query); expect(children).to.be.an("array"); expect(children).to.have.length(1); @@ -203,15 +209,15 @@ describe("graph class", () => { it("should create a cover for several vertices", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.STRING}), - new Dimension({name: "dim:1", dataType: DataType.STRING}), - new Dimension({name: "dim:2", dataType: DataType.STRING}) + new Dimension({name: "dim:0", dataType: "string"}), + new Dimension({name: "dim:1", dataType: "string"}), + new Dimension({name: "dim:2", dataType: "string"}) ]; let mets = [ - new Metric({name: "met:0", dataType: DataType.INTEGER, aggregation: AggregationType.SUM}), - new Metric({name: "met:1", dataType: DataType.INTEGER, aggregation: AggregationType.AVG}), - new Metric({name: "met:2", dataType: DataType.INTEGER, aggregation: AggregationType.AVG}) + new Metric({name: "met:0", dataType: "integer", aggregation: AggregationType.SUM}), + new Metric({name: "met:1", dataType: "integer", aggregation: AggregationType.AVG}), + new Metric({name: "met:2", dataType: "integer", aggregation: AggregationType.AVG}) ]; let g = new Graph(); @@ -225,40 +231,46 @@ describe("graph class", () => { new View({ metrics: [mets[0]], dimensions: [dims[0]], - origin: true + origin: true, + materialized: true }), new View({ metrics: [mets[1]], dimensions: [dims[1]], - origin: true + origin: true, + materialized: true }), new View({ metrics: [mets[2]], dimensions: [dims[2]], - origin: true + origin: true, + materialized: true }), new View({ metrics: [], dimensions: dims, - origin: true + origin: true, + materialized: true }), new View({ metrics: mets, dimensions: dims, - origin: true + origin: true, + materialized: true }), new View({ metrics: [mets[0], mets[1]], dimensions: [dims[0], dims[1]], - origin: true + origin: true, + materialized: true }), ]; for (let i = 0; i < views.length; ++i) { expect(g.addView(views[i])).to.be.true; } - const qOpts: QueryOpts = { metrics: [mets[0], mets[1]], dimensions: [dims[0], dims[1]]}; - const query = new Query(qOpts); + + const query: Query = { metrics: [mets[0], mets[1]], dimensions: [dims[0], dims[1]] }; let children = g.cover(query); expect(children).to.be.an("array"); expect(children).to.have.length(1); @@ -266,18 +278,18 @@ describe("graph class", () => { }); it("should create a cover with sub dimensions", () => { - let dim = new Dimension({name: "dim:0", dataType: DataType.DATE}); + let dim = new Dimension({name: "dim:0", dataType: "date"}); let dims = [ dim, new Dimension({ name: "subdim:0", - dataType: DataType.STRING, + dataType: "string", parent: dim, relation: RelationType.MONTH }), new Dimension({ name: "subdim:1", - dataType: DataType.STRING, + dataType: "string", parent: dim, relation: RelationType.DAY }), @@ -292,12 +304,13 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0]], - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.true; - const qOpts: QueryOpts = { metrics: [], dimensions: [dims[1], dims[2]]}; - const query = new Query(qOpts); + + const query: Query = { metrics: [], dimensions: [dims[1], dims[2]] }; let children = g.cover(query); expect(children).to.be.an("array"); expect(children).to.have.length(1); @@ -305,18 +318,18 @@ describe("graph class", () => { }); it("should return empty when try to cover a empty list", () => { - let dim = new Dimension({name: "dim:0", dataType: DataType.DATE}); + let dim = new Dimension({name: "dim:0", dataType: "date"}); let dims = [ dim, new Dimension({ name: "subdim:0", - dataType: DataType.STRING, + dataType: "string", parent: dim, relation: RelationType.MONTH }), new Dimension({ name: "subdim:1", - dataType: DataType.STRING, + dataType: "string", parent: dim, relation: RelationType.DAY }), @@ -331,12 +344,13 @@ describe("graph class", () => { let view = new View({ metrics: [], dimensions: [dims[0]], - origin: true + origin: true, + materialized: true }); expect(g.addView(view)).to.be.true; - const qOpts: QueryOpts = { metrics: [], dimensions: []}; - const query = new Query(qOpts); + + const query: Query = { metrics: [], dimensions: [] }; let children = g.cover(query); expect(children).to.be.an("array"); expect(children).to.be.empty; @@ -344,9 +358,9 @@ describe("graph class", () => { it("should cover the graph, even when a constraint edge can not be used", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.DATE}), - new Dimension({name: "dim:1", dataType: DataType.DATE}), - new Dimension({name: "dim:2", dataType: DataType.DATE}), + new Dimension({name: "dim:0", dataType: "date"}), + new Dimension({name: "dim:1", dataType: "date"}), + new Dimension({name: "dim:2", dataType: "date"}), ]; let filter1 = new Filter({ @@ -371,27 +385,31 @@ describe("graph class", () => { let view1 = new View({ metrics: [], dimensions: [dims[0], dims[1]], - origin: true + origin: true, + materialized: true }); let view2 = new View({ metrics: [], dimensions: [dims[1], dims[2]], - origin: true + origin: true, + materialized: true }); let view3 = new View({ metrics: [], dimensions: dims, origin: false, + materialized: false, + childViews: [view1, view2], clauses: [clause1] }); expect(g.addView(view1)).to.be.true; expect(g.addView(view2)).to.be.true; expect(g.addView(view3)).to.be.true; - const qOpts: QueryOpts = { metrics: [], dimensions: dims, clauses: [clause2]}; - const query = new Query(qOpts); + + const query: Query = { metrics: [], dimensions: dims, clauses: [clause2] }; let children = g.cover(query); expect(children).to.be.an("array"); expect(children).to.have.length(2); @@ -400,9 +418,9 @@ describe("graph class", () => { it("should cover the query, using filters of intervals", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.FLOAT}), - new Dimension({name: "dim:1", dataType: DataType.FLOAT}), - new Dimension({name: "dim:2", dataType: DataType.DATE}), + new Dimension({name: "dim:0", dataType: "float"}), + new Dimension({name: "dim:1", dataType: "float"}), + new Dimension({name: "dim:2", dataType: "date"}), ]; const filters = [ @@ -499,12 +517,13 @@ describe("graph class", () => { metrics: [], dimensions: dims, origin: false, + materialized: true, clauses: clauses }); expect(g.addView(view0)).to.be.true; - const qOpts: QueryOpts = { metrics: [], dimensions: dims, clauses: testClauses}; - const query = new Query(qOpts); + + const query: Query = { metrics: [], dimensions: dims, clauses: testClauses }; let children = g.cover(query); expect(children).to.have.length(1); expect(children[0].id === view0.id).to.be.true; @@ -512,9 +531,9 @@ describe("graph class", () => { it("should cover the query, not using filters of intervals", () => { let dims = [ - new Dimension({name: "dim:0", dataType: DataType.FLOAT}), - new Dimension({name: "dim:1", dataType: DataType.FLOAT}), - new Dimension({name: "dim:2", dataType: DataType.DATE}), + new Dimension({name: "dim:0", dataType: "float"}), + new Dimension({name: "dim:1", dataType: "float"}), + new Dimension({name: "dim:2", dataType: "date"}), ]; const filters = [ @@ -611,7 +630,8 @@ describe("graph class", () => { new View({ metrics: [], dimensions: dims, - origin: false + origin: false, + materialized: true }) ]; @@ -620,6 +640,7 @@ describe("graph class", () => { metrics: [], dimensions: dims, origin: false, + materialized: true, clauses: [clauses[i]] })); } @@ -627,8 +648,8 @@ describe("graph class", () => { for (let i = 0; i < views.length; ++i) { expect(g.addView(views[i])).to.be.true; } - const qOpts: QueryOpts = { metrics: [], dimensions: dims, clauses: testClauses}; - const query = new Query(qOpts); + + const query: Query = { metrics: [], dimensions: dims, clauses: testClauses }; let children = g.cover(query); expect(children).to.have.length(1); expect(children[0].id === views[0].id).to.be.true; diff --git a/src/util/graph.ts b/src/util/graph.ts index 0d57cf35106818cd8ccada197464d069f295fca7..2b020701c24e6e3f656ba02188c114080236657a 100644 --- a/src/util/graph.ts +++ b/src/util/graph.ts @@ -24,88 +24,81 @@ import { Dimension } from "../core/dimension"; import { Query } from "../common/query"; import { Clause } from "../core/clause"; import { FilterOperator } from "../core/filter"; -import { DataType } from "../common/types"; enum State { UNVISITED, VISITED } -/** - * A vertex of a Graph. - * Created using a dimension or metric. - */ +/* + Class (interface) for a vertex in the graph + Created using a dimension or metric + Several of the attributes are used just for + search proposes like parent and state. +*/ + interface Vertex { - /** Name of vertex. */ - id: string; - /** Adjacent vertices. */ + id: string; // Name of vertex neighbors: { [key: string]: Edge[] }; - /** Vextex state while a search process is performed. */ - state: State; - /** Which vertex "find" this one while a search process is performed. */ - parent: Vertex; - /** Represents a sub-dimension ? */ - isSubDimension: boolean; - /** The parent vertex if this vertex is a sub-dimension vertex. */ - dimensionParent: Vertex; - /** The dimension which this vertex represent. */ - dimension: Dimension; - /** The metric which this vertex represent. */ - metric: Metric; + state: State; // During the search the vertex has a state + parent: Vertex; // During the search, what vertex "find" this + isSubDimension: boolean; // During insertion, was subdimension + dimensionParent: Vertex; // If is a subdimension, the vertex for that + dimension: Dimension; // If is a dimension, tha dimension that the vertex represents + metric: Metric; // If is a metric, the metric that the vertexrepresents } -/** - * A graph's edge. - * Edges represent views or parent relationship with - * dimensions and subdimensions. - */ +/* + Class (interface) dor a edge of the Graph + Normaly is possible to use a list of vertices + to represent the edges, however this edges have some + information different from the vertex, so a class + is needed. + + Edges represent views or parent relationship with + dimensions and subdimensions. +*/ interface Edge { - /** True if edge represent view. */ - isView: boolean; - /** The view which this edge represents. */ - view: View; - /** The sub-dimension which this edge represents. */ - subDimension: Dimension; + isView: boolean; // True if edge represent view + view: View; // The view if isView is True + subDimension: Dimension; // The subDimension if isView is False } /* - * A graph to represent the database schema. - * Used to convert the Views Representation (Tables/Relations) - * into a graph representation of the database schema. - * Is not generic Graph, is not possible create vertex and - * edges at will, only with metrics, dimensions and views. - * Struct: - * There is a vertex for each Metric and Dimension inserted - * in the graph. - * The graph is directed, but mostly vertices has edges in - * both directions. - * There is a edge between 2 vertices i and j in 3 cases: - * I) if i and j are in the same view, there is a edge (i, j) - * and (j, i) - * II) if i is parent of the subdimention j , there is a - * edge (i, j) - * III) If a view has only one vertex, there is a loop (i, i) - * So there is a edge if vertices are in the same view or - * there is a parent relationship between vertices. - */ + Graph Class + Used to convert the Views Representation (Tables/Relations) + into a graph representation of the database schema. + Is not generic Graph, is not possible create vertex and + edges at will, only with metrics, dimensions and views. + + Struct: + There is a vertex for each Metric and Dimension inserted + in the graph. + The graph is directed, but mostly vertices has edges in + both directions. + There is a edge between 2 vertices i and j in 3 cases: + I) if i and j are in the same view, there is a edge (i, j) + and (j, i) + II) if i is parent of the subdimention j , there is a + edge (i, j) + III) If a view has only one vertex, there is a loop (i, i) + + So there is a edge if vertices are in the same view or + there is a parent relationship between vertices. +*/ export class Graph { - /** Graph's set of vertices. */ - private vertices: Vertex[]; - /** - * Graph's set of vertices in dictonary form. - * Indexed by vertex name. Returns the vertex object. - */ + private vertices: Vertex[]; // vertices of the graph private verticeMap: { [key: string]: Vertex }; + // Map where key is the vertex id and the value is the vertex - /** Creates a graph. */ public constructor () { this.vertices = []; this.verticeMap = {}; } - /** - * Adds a metric and inform if the inserion was a success. - * @param met - Metric to be inserted. - */ + /* + Adds a metric + returns true if the metric was inserted in the graph + */ public addMetric(met: Metric): boolean { if (!met) { return false; @@ -132,10 +125,10 @@ export class Graph { } } - /** - * Adds a dimension and inform if the inserion was a success. - * @param dim - Dimension to be inserted. - */ + /* + Adds a dimension + returns true if the dimension was inserted in the graph + */ public addDimension(dim: Dimension): boolean { if (!dim) { return false; @@ -197,15 +190,15 @@ export class Graph { } } - /** - * Add a View - * Get the metrics and dimensions of this view - * and create edges between then - * returns true when the view in inserted (create all the - * edges needed) and false otherwise - * If false is returned any edge is created. - * @param view - View to be inserted. - */ + /* + Add a View + Get the metrics and dimensions of this view + and create edges between then + returns true when the view in inserted (create all the + edges needed) and false otherwise + If returns false any edge was created, if true all edges + were created. + */ public addView (view: View): boolean { if (!view) { return false; @@ -251,15 +244,12 @@ export class Graph { } - /** - * Check if a edge can be create. - * return false when at least one vertex does not exist in the graph - * or the edge already exists - * returns true otherwise - * @param idV - Identifier of one edge's vertex. - * @param idV - Identifier of the other edge's vertex. - * @param value - View represented by this edge. - */ + /* + Check if a edge can be create + return false when at least one vertex does not exist in the graph + or the edge already exists + returns true otherwise + */ private checkEdge(idV: string, idU: string, value: View): boolean { let v: Vertex = this.verticeMap[idV]; let u: Vertex = this.verticeMap[idU]; @@ -280,19 +270,19 @@ export class Graph { } } - /** - * Create a edge between 2 vertices - * Edges are a kind of special, when say create a edge is - * in fact put a index on the array of a edge. - * The edges have a array of ids, when you try to create a edge - * and the edge doen not exist, create the edge and a array with - * a lonely index in it. If the edge exist but the id is not in - * the array, adds the id. - * @param idV - Identifier of one edge's vertex. - * @param idV - Identifier of the other edge's vertex. - * @param value - View represented by this edge. - */ - private edge(idV: string, idU: string, value: View): void { + /* + Create a edge between 2 vertices + + Edges are a kind of special, when say create a edge is + in fact put a index on the array of a edge. + + The edges have a array of ids, when you try to create a edge + and the edge doen not exist, create the edge and a array with + a lonely index in it. If the edge exist but the id is not in + the array, adds the id and checkEdge would return true, + if the id already exists return false + */ + private edge(idV: string, idU: string, value: View) { // Assuming that checkEdge is called first let v: Vertex = this.verticeMap[idV]; let u: Vertex = this.verticeMap[idU]; @@ -311,17 +301,17 @@ export class Graph { } } - /** - * Given a list of metrics and dimensions returns a set - * of Views (children) that can be used as "locations" to - * perform the query. - * If this set cannot be created, throws a error. - * @param q - Query to be "localized"(covered). - */ + /* + Given a list of metrics and dimensions returns a set + of Views (children) that can be used to create a query that + returns the data asked. + + If this set cannot be created, throws a error + */ public cover(q: Query): View[] { const metrics = q.metrics; const dimensions = q.dimensions; - const clauses = q.clauses; + const clauses = (q.clauses) ? q.clauses : []; let output: View[] = []; let verticesIds = this.verticesInQuery(q); @@ -349,7 +339,7 @@ export class Graph { let queue: Vertex[] = [root]; while (queue.length > 0) { let v: Vertex = queue.shift(); - for (let key of Object.keys(v.neighbors)) { + for (let key in v.neighbors) { let u: Vertex = this.verticeMap[key]; if (this.canVisit(u, v.neighbors[key], clauses)) { // Mark all vertices visited by the search @@ -424,7 +414,7 @@ export class Graph { let views: View[] = []; // Pick all views that contain the root vertex - for (let i of Object.keys(root.neighbors)) { + for (let i in root.neighbors) { views = views.concat(root.neighbors[i].filter((item) => { return item.isView && this.passConstraints(clauses, item.view.clauses); @@ -447,15 +437,13 @@ export class Graph { return output; } - /** - * Choose the "best" view in a edge. - * The algorithm chooses the view that covers more metrics and dimensions - * that are not covered yet, if there is a tie chooses the one with - * less dimensions, if tie again, the earliest in the list. - * @param views - Cadidates for best view. - * @param metToCover - Uncovered metrics. - * @param dimToCover - Uncovered dimensions. - */ + /* + From a edge, coohse the best view, based on the metric and dimensions + that are not cover yet, return a View. + The algorithm chooses the view that covers more metrics and dimensions + that are not covered yet, if there is a tie chooses the one with + less dimensions, if tie again, the earliest in the list. + */ private pickEdge (views: View[], metToCover: Metric[], dimToCover: Dimension[]): View { // Picks the first option as the best one until now let bestView = views[0]; @@ -506,14 +494,11 @@ export class Graph { return bestView; } - /** - * Check if a vertex is can be visited from another vertex. - * Basically checks if the vertex is unvisited, if is a sub dimension - * or view edge and if is a view, check the constraints. - * @param v - Vertex to be visited. - * @param neighbors - Possible choises to reach the vertex v. - * @param clauses - Query clauses. Used as constraints. - */ + /* + Check if a vertex is can be visited from another vertex. + Basically checks if the vertex is unvisited, if is a sub dimension + or view edge and if is a view, chech the constraints. + */ private canVisit(v: Vertex, neighbors: Edge[], clauses: Clause[] ): boolean { if (v.state !== State.UNVISITED) { return false; @@ -534,12 +519,10 @@ export class Graph { return false; } - /** - * Check if a set of filters/clauses of a view suits for the query - * @param queryClauses - Clauses used in the query. - * @param viewVlauses - Clauses applied to a view. - */ - private passConstraints(queryClauses: Clause[], viewClauses: Clause[]): boolean { + /* + Check if a set of filter/clauses of a view suits for the query + */ + private passConstraints(queryClauses: Clause[], viewClauses: Clause[]) { /* TODO: Enhance constraint check. @@ -565,7 +548,7 @@ export class Graph { let queryValue: number; let viewValue: number; - if (queryFilter.target.dataType === DataType.DATE) { + if (queryFilter.target.dataType === "date") { queryValue = new Date(queryFilter.value).getTime(); viewValue = new Date(viewFilter.value).getTime(); } @@ -613,15 +596,10 @@ export class Graph { } - /** - * Find all metrics and dimension in a query - * and get its correspondent vertex identifiers. - * @param q - Query which contains vertices. - */ private verticesInQuery(q: Query): string[] { const metrics = q.metrics; const dimensions = q.dimensions; - const clauses = q.clauses; + const clauses = (q.clauses) ? q.clauses : []; let verticesIds = metrics.map((met) => met.name); verticesIds = verticesIds.concat(dimensions.map((dim) => dim.name)); for (let i = 0; i < clauses.length; ++i) { diff --git a/src/util/hash.ts b/src/util/hash.ts index 6f7b4e8b722872cb739dde4e255279a97c435b33..0ca3c606ad88c7d5531fcf525cc80a3129eb31c8 100644 --- a/src/util/hash.ts +++ b/src/util/hash.ts @@ -21,10 +21,6 @@ import crypto = require("crypto"); export class Hash { - /** - * Perform a sha1 encryption. - * @param objects - Set of objects to be used to create the hash. - */ public static sha1(...objects: any[]): string { let hash = crypto.createHash("sha1"); diff --git a/src/util/log.spec.ts b/src/util/log.spec.ts deleted file mode 100644 index 404f6bb98a8836acf82269ca8a58e5128adde60f..0000000000000000000000000000000000000000 --- a/src/util/log.spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import { expect } from "chai"; -import { Log } from "./log"; - -describe("log class", () => { - - it("should modifiy loglevel to error if wrong level", () => { - process.env.BLENDB_LOG_LEVEL = "test"; - const logLevelWrong = new Log(); - expect(logLevelWrong.getLogLevel()).to.be.equals("error"); - }); - - it("should modifiy loglevel to error if empty level", () => { - process.env.BLENDB_LOG_LEVEL = ""; - const logLevelEmpty = new Log(); - expect(logLevelEmpty.getLogLevel()).to.be.equals("error"); - }); - - it("should modifiy logFile to stderr if empty file", () => { - process.env.BLENDB_LOG_FILE = ""; - const LogFileEmpty = new Log(); - expect(LogFileEmpty.getLogFile()).to.be.equals("stderr"); - }); - - it("should modifiy logFile to stderr if file does not exist", () => { - process.env.BLENDB_LOG_FILE = "norepo/test/shalnotexist"; - const LogFileEmpty = new Log(); - expect(LogFileEmpty.getLogFile()).to.be.equals("stderr"); - }); - -}); diff --git a/src/util/log.ts b/src/util/log.ts deleted file mode 100644 index c98b287d52781484e68d60b26a9cb21ce72d3120..0000000000000000000000000000000000000000 --- a/src/util/log.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import { configure, getLogger } from "log4js"; -import * as fs from "fs"; -/** - * Define the levels that BlenDB log must have - */ -interface LogInterface { - debug(msg: string, ...additionalInfo: any[]): void; - info(msg: string, ...additionalInfo: any[]): void; - warn(msg: string, ...additionalInfo: any[]): void; - error(msg: string, ...additionalInfo: any[]): void; -} -/** - * Logging for BlenDB using the framework log4js, - * using debug, info, warn and error as levels. - * Hierarchy of levels for showing messages are: - * debug > info > warn > error - */ -export class Log implements LogInterface { - - private levels = ["debug" , "info" , "warn" , "error"]; - private file: string; - private level: string; - private logger: any; - /** - * Definitions to use log4js, such as file destination, - * level of log and configure log4js. - */ - constructor(){ - this.file = (process.env["BLENDB_LOG_FILE"]) ? process.env["BLENDB_LOG_FILE"] : "stderr"; - this.level = (process.env["BLENDB_LOG_LEVEL"]) ? process.env["BLENDB_LOG_LEVEL"] : "error"; - - let find = this.levels.some( element => { - return element === this.level; - }); - if (!find) { - this.level = "error"; - } - - if (!(this.file === "stderr")) { - try { - fs.appendFileSync(this.file, ""); - } - catch (e) { - this.file = "stderr"; - } - } - - /** - * The reason for the duplication of configure, - * is because the filename flag from appenders it start - * the empty file if doesn't exist, even if it's not - * called from getLogger. Then it won't create an empty - * file called stderr. - */ - if (this.file === "stderr") { - configure({ - appenders: { defaultLog: { type : "stderr" } - }, - categories: { - default: { appenders: ["defaultLog"], level: this.level }, - } - }); - this.logger = getLogger("defaultLog"); - }else{ - configure({ - appenders: { blendb: { type: "file", layout: { - type: "pattern", - pattern: "%d [%p] host: [%h] user: [%x{user}] %n %[%m%n%]", - tokens: { - user: function(logEvent) { - return process.env.USER; - } - } - }, - filename: this.file } - }, - categories: { - default: { appenders: ["blendb"], level: this.level } - } - }); - this.logger = getLogger("blendb"); - } - this.logger.level = this.level; - } - /** - * Get log level - */ - public getLogLevel(){ - return this.level; - } - /** - * Get lof filename - */ - public getLogFile(){ - return this.file; - } - /** - * Log level debug - * @param msg description of log - * @param additionalInfo useful additional information - */ - public debug(msg: string, ...additionalInfo: any[]){ - this.emtigLogMessage("debug", msg, additionalInfo); - } - /** - * Log level info - * @param msg description of log - * @param additionalInfo useful additional information - */ - public info(msg: string, ...additionalInfo: any[]){ - this.emtigLogMessage("info", msg, additionalInfo); - } - /** - * Log level warning - * @param msg description of log - * @param additionalInfo useful additional information - */ - public warn(msg: string, ...additionalInfo: any[]){ - this.emtigLogMessage("warn", msg, additionalInfo); - } - /** - * Log level error - * @param msg description of log - * @param additionalInfo useful additional information - */ - public error(msg: string, ...additionalInfo: any[]){ - this.emtigLogMessage("error", msg, additionalInfo); - } - /** - * Handle data between log class and log4js framework - * @param msgType level of log being use - * @param msg description of log - * @param additionalInfo useful additional information - */ - private emtigLogMessage(logLevel: "debug" | "info" | "warn" | "error" , msg: string, additionalInfo: any[]){ - if (additionalInfo.length){ - this.logger[logLevel](msg, additionalInfo); - }else{ - this.logger[logLevel](msg); - } - } -} diff --git a/src/util/scenarioHandler.ts b/src/util/scenarioHandler.ts deleted file mode 100644 index bb2de85715ff1e36320035cfd58071ec05f3b9d7..0000000000000000000000000000000000000000 --- a/src/util/scenarioHandler.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. -*/ - -import { View } from "../core/view"; -import { Metric } from "../core/metric"; -import { Dimension } from "../core/dimension"; -import { Query } from "../common/query"; -import { ParsedConfig } from "./configParser"; - -export interface EngineScenario { - /** - * subDimensions from scenario - */ - subDimensions: {[key: string]: Dimension}; - /** - * Metric that does not exist on /config/* - */ - wrongMet: Metric; - /** - * Dimension that does not exist on /config/* - */ - wrongDim: Dimension; - /** - * Query that have all metrics and dimensions - */ - queryMetsDims: Query; - /** - * Query with an invalid metric - */ - queryNoMets: Query; - /** - * Query with an invalid dimension - */ - queryNoDims: Query; - /** - * Query that matches Product - */ - queryProduct: Query; - /** - * Product View - */ - viewProduct: View; - /** - * Query that matches ActiveSeller - */ - queryActive: Query; - /** - * ActiveSeller View - */ - viewActiveSeller: View; - /** - * Query with no metrics and dimensions formed of subdimensions - */ - querySubDim: Query; - /** - * A query that contains a subdimentions without a parent - */ - queryNoParent: Query; - /** - * ParsedConfig that is load in scenario - */ - config: ParsedConfig; -} - -export interface AdapterScenario { - /** - * Product View - */ - materializedView: View; - /** - * View that contains client name and it's sum quantity, and is - * sorted based on quantity - */ - sortView: View; - /** - * View that contains subDimensions based on date, such as day, - * month and year - */ - subDimensionView: View; - /** - * View that contains itself, which is product's View - */ - joinWithOneView: View; - /** - * View that contains sold items on the day that is equals the last - * day of validity - */ - filterWithEqual: View; - /** - * View that contains metrics and dimensions from View Sell and dimensions - * from View Client - */ - reduceAsView: View; - /** - * View that contains the avererage product's bought with client's name - */ - filterAverageBought: View; - /** - * View that contains the data from operation AND between clauses, - * which is product's that was sold expired and have a value higher than - * ten - */ - multipleClause: View; - /** - * View that represent's the same data as multipleClause however with, - * the operation OR between the filteres , since we use only one clause - */ - singleClause: View; - /** - * View that contais the name of the client and the name of the product, - * that the client has bought - */ - joinWithNoMetrics: View; - /** - * View that contains the name,sex and age from View Seller - */ - growOneView: View; - /** - * View that contains the seller id and how many sell's he has done - */ - JoinWithAncestors: View; - /** - * View with false origin - */ - viewSumCount: View; - /** - * ParsedConfig that is load in scenario - */ - config: ParsedConfig; -} - -export interface DataCtrlScenario { - /** - * Dimension that does not exist on /config/* - */ - wrongMet: Query; - /** - * Dimension that does not exist on /config/* - */ - wrongDim: Query; - /** - * A query that returns the average quantity of buyouts related - * from provider - */ - correct: Query; - /** - * A query that returns the average pricein related from it's name - * and it's id - */ - clausal: Query; - /** - * A query that returns the seller's that are registered - */ - seller: Query; - /** - * The products that are the most expensive - */ - expensive: Query; - /** - * The sellers average age by cpf and sex - */ - csv: Query; -} diff --git a/src/util/tsort.ts b/src/util/tsort.ts deleted file mode 100644 index 2bff0690c82d2128c3623214472737c925bb11ab..0000000000000000000000000000000000000000 --- a/src/util/tsort.ts +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -/** - * A representation of a dependency relation. - * Equivalent to a edge in a dependency graph. - */ - -import { View } from "../core/view"; - -export interface TsortDep { - /** The value (vertex). */ - value: string; - /** The value which this depends of. */ - dependOf?: string; -} - -/** - * A dependency graph. - */ -interface Graph { - /** - * Dictionary indexed by vertices which - * returns a list of the adjacent vertex. - */ - [key: string]: string[]; -} - -interface VertexMark { - /** - * Dictionary indexed by vertices which - * checks if the vertex is already sorted. - */ - [key: string]: boolean; -} - -/** - * Dependency sorting methods. Creates a dependency - * graph and use the topological sorting algorithm - * putting all the dependencies before the dependent. - */ -export class Tsort { - /** - * Topologicaly sort strings in the TSortDep format. - * @param deps - Dependency relations (edges in the - * dependency graph). - */ - public static dependencies(deps: TsortDep[]): string[]{ - // Graph Creation - let graph: Graph = {}; - let mark: VertexMark = {}; - for (let i = 0; i < deps.length; ++i) { - let vertex = deps[i].dependOf; - if (!graph[deps[i].value]) { - graph[deps[i].value] = []; - mark[deps[i].value] = false; - } - - if (vertex) { - if (!graph[vertex]) { - graph[vertex] = [deps[i].value]; - mark[vertex] = false; - } - - else { - graph[vertex].push(deps[i].value); - } - } - - } - - // Topological Sort - let output: string[] = []; - for (let vertex of Object.keys(graph)) { - if (!mark[vertex]) { - Tsort.markVertex(vertex, graph, mark, output); - } - } - return output; - } - - /** - * Topologicaly sort view descendents names. - * @param view - View to construct dependency tree(graph) and sort it - */ - public static view(view: View): string[] { - // Graph creation - const graph: Graph = {}; - const mark: VertexMark = {}; - - let queue = [view]; - - while (queue.length > 0) { - const partial = queue.shift(); - - // If the dependent vertex does not exist, create it - // with a empty dependent list - if (!graph[partial.name]) { - graph[partial.name] = []; - mark[partial.name] = false; - } - for (let i = 0; i < partial.operation.values.length; ++i) { - const dep = partial.operation.values[i]; - - // If the required vertex does not exists create it - // and put the dependent vertex in the dependent list - if (!graph[dep.name]) { - graph[dep.name] = [partial.name]; - mark[dep.name] = false; - } - - // If the vertex already exists, add it in the dependent list - else { - graph[dep.name].push(partial.name); - } - - // Add the other view. Could create replicated edges. - queue = queue.concat(partial.operation.values); - } - } - - // Topological Sort - let output: string[] = []; - for (let vertex of Object.keys(graph)) { - if (!mark[vertex]) { - Tsort.markVertex(vertex, graph, mark, output); - } - } - return output; - } - - /** - * Recursive topological sorting algorithm strarting from - * a given vertex - * @param vertex - Topological sorting root. - * @param graph - Dependency graph. - * @param mark - Mark indicatiing if the vertex is already sorted. - * @param output - The topological sorting. - */ - private static markVertex(vertex: string, graph: Graph, - mark: VertexMark, output: string[]): void { - if (mark[vertex]) { - return; - } - - mark[vertex] = true; - for (let i = 0; i < graph[vertex].length; ++i) { - Tsort.markVertex(graph[vertex][i], graph, mark, output); - } - output.unshift(vertex); - return; - } -} diff --git a/src/util/viewHandler.ts b/src/util/viewHandler.ts deleted file mode 100644 index 4c875c6a49b471765a5ad6ae3b43d846e9051452..0000000000000000000000000000000000000000 --- a/src/util/viewHandler.ts +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blendb. - * - * blendb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blendb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blendb. If not, see <http://www.gnu.org/licenses/>. - */ - -import { Opcode } from "../common/expression"; -import { View } from "../core/view"; -import { Clause } from "../core/clause"; -import { Query, QueryOpts } from "../common/query"; -import { Dimension } from "../core/dimension"; -import { Metric } from "../core/metric"; - -/** - * Dictionary with relevancy for each dimension. - * Indexed by dimention name and returns the score. - */ -interface Score { - [key: string]: number; -} - -/** Result of a join/reduction view operation. */ -interface ViewsAndClauses { - /** Set of views returned after operation. */ - views: View[]; - /** Set of clauses not applied yet. */ - clauses: Clause[]; -} - -/** - * View's handler. Perform several operations with - * views and used to manipulate and create new views - * in a safe way. - */ -export class ViewHandler { - /** - * Perform the JOIN operation to create a new View - * @param q - Query with the parameters of the view - * to be created. - * @param views - Set of views required to create - * this view with the JOIN operation. - */ - public static queryJoin(q: Query, views: View[]): View { - if (views.length > 1) { - return new View({ - metrics: q.metrics, - dimensions: q.dimensions, - origin: false, - clauses: q.clauses, - sort: q.sort, - operation: { - opcode: Opcode.JOIN, - values: views.map((i) => i) - } - }); - } - - else { - return views[0]; - } - } - - /** - * Perform the REDUCE operation to create a new View - * @param q - Query with the parameters of the view - * to be created. - * @param view - View which the REDUCE was applied. - */ - public static queryReduce(q: Query, view: View): View { - const v = new View({ - metrics: q.metrics, - dimensions: q.dimensions, - origin: false, - clauses: q.clauses, - sort: q.sort, - operation: { - opcode: Opcode.REDUCE, - values: [view] - } - }); - - return (v.id !== view.id) ? v : view; - } - - /** - * Constructs one view which represents a query. - * Given a set of views that cover the query - * combines its elements using JOIN and REDUCE - * operations to create a unique view. - * @param q - Query which represents the view to be created - * @param views - Views which cover the query. - */ - public static growView(q: Query, views: View[]): View { - let clausesToCover = q.clauses.map((i) => i); - let metView: View = null; - let partialJoin: View[] = null; - let reduced: ViewsAndClauses = null; - let qOpt: QueryOpts; - - let partialQuery = new Query(q); - - partialJoin = views.map((i) => (i)); - - if (q.metrics.length === 0) { // ignore metView if there are 0 metrics - if (partialJoin.length > 0) { - qOpt = {metrics: partialQuery.metrics, dimensions: partialQuery.dimensions, clauses: clausesToCover}; - partialQuery = new Query(qOpt); - reduced = ViewHandler.applyReduce(partialJoin, partialQuery); - clausesToCover = reduced.clauses; - partialJoin = ViewHandler.applyJoin(reduced.views); - } - - return ViewHandler.applyReduce(partialJoin, partialQuery).views[0]; - } - - else { - const metViewId = partialJoin.findIndex((i) => i.metrics.some((j) => { - return j.name === q.metrics[0].name; - })); - - metView = partialJoin[metViewId]; - partialJoin.splice(metViewId, 1); - if (partialJoin.length > 0) { - partialJoin.push(metView); // MetView is now the last view - qOpt = {metrics: partialQuery.metrics, dimensions: partialQuery.dimensions, clauses: clausesToCover}; - partialQuery = new Query(qOpt); - reduced = ViewHandler.applyReduce(partialJoin, partialQuery); - clausesToCover = reduced.clauses; - metView = reduced.views.pop(); - partialJoin = ViewHandler.applyJoin(reduced.views); - } - - if (partialJoin.length === 0) { - return ViewHandler.applyReduce([metView], partialQuery).views[0]; - } - - else { - partialJoin.push(metView); - // In this case, there are exactly 2 views - reduced = ViewHandler.applyReduce(partialJoin, partialQuery); - partialJoin = ViewHandler.applyJoin(reduced.views); - qOpt = {metrics: partialQuery.metrics, dimensions: partialQuery.dimensions, clauses: reduced.clauses}; - partialQuery = new Query(qOpt); - return ViewHandler.applyReduce(partialJoin, partialQuery).views[0]; - } - } - } - - /** - * Calculate the score of a set of dimensions. - * @param views - Views which contain the dimensions to be scored. - * @param clauses - Clauses which contain the dimensions to be scored. - * @param dimensions - Dimensions in a query. These receives a extra score. - */ - private static dimensionsScore(views: View[], clauses: Clause[], dimensions: Dimension[]): Score { - let map: { [key: string]: number } = {}; - for (let i = 0; i < views.length; ++i) { - const dims = views[i].dimensions; - for (let k = 0; k < dims.length; ++k) { - if (map[dims[k].name]) { - ++map[dims[k].name]; - } - - else { - map[dims[k].name] = 1; - } - } - } - - for (let i = 0; i < dimensions.length; ++i) { - let dim = dimensions[i]; - if (map[dim.name]) { - ++map[dim.name]; - } - - else { // Necessary for sub dimensions - map[dim.name] = 1; - } - } - - /* - Also mark scores for dimensions inside clauses - */ - for (let i = 0; i < clauses.length; ++i) { - for (let j = 0; j < clauses[i].targets.length; ++j) { - if (map[clauses[i].targets[j].name]) { - ++map[clauses[i].targets[j].name]; - } - } - } - return map; - } - - /** - * Apply the reduce operation in a set of views. - * Returns the reduced views and the set of clauses which could - * not be applied. - * @param v - Set of views to be reduced. - * @param q - Target query. Used to know which dimentions ca be removed - * and which clauses must be applied. - */ - private static applyReduce(v: View[], q: Query): ViewsAndClauses { - let changed = true; - const views = v.map((i) => i); - /* - Check if the view have already a clause , so that it won't - cover it twice. - */ - let clausesToCover = q.clauses.filter((clause) => { - return !views.some((view) => view.clauses.some((c) => c.id === clause.id)); - }); - while (changed) { - changed = false; - let map = ViewHandler.dimensionsScore(views, clausesToCover, q.dimensions); - const unfilledSubDims = q.dimensions.filter((item) => { - return map[item.name] < 2; - }); - let ancestors: { [key: string]: Dimension[] } = {}; - for (let i = 0; i < unfilledSubDims.length; ++i) { - let dim = unfilledSubDims[i]; - ancestors[dim.name] = [dim]; - dim = dim.parent; - while (dim !== null) { - ancestors[unfilledSubDims[i].name].push(dim); - dim = dim.parent; - } - } - for (let i = 0; i < views.length; ++i) { - const dims = views[i].dimensions.filter((item) => { - return map[item.name] > 1; - }); - /* - At this point the dimensions with less than score 2 - are removed, if this happens the view is agreggated - again, with less dimensions, removing this dimension - from the view. - */ - - for (let key of Object.keys(ancestors)) { - const intersection = (ancestors[key].some((anc) => { - return views[i].dimensions.some((dim) => { - return dim.name === anc.name; - }); - })); - - if (intersection) { - // The first item is always the sub dimension - dims.push(ancestors[key][0]); - } - } - - let coveredClauses: Clause[] = []; - let notCoveredClauses: Clause[] = []; - /* - If all dimensions in a clause are a sub set of the - dimensions of a view, this clause is apllied now, - propagating the clause to this point. - - Then this clause is removed from the set of clauses - */ - for (let j = 0; j < clausesToCover.length; ++j) { - if (clausesToCover[j].isCovered(views[i].dimensions)) { - coveredClauses.push(clausesToCover[j]); - } - else { - notCoveredClauses.push(clausesToCover[j]); - } - } - - clausesToCover = notCoveredClauses.map((clause) => clause); - - // Intersection between query metrics and view metrics - const mets = q.metrics.filter((met) => { - return views[i].metrics.some((m) => m.name === met.name); - }); - - if (dims.length < views[i].dimensions.length || coveredClauses.length > 0) { - const partial = ViewHandler.queryReduce({ - metrics: mets, - dimensions: dims, - clauses: coveredClauses.concat(views[i].clauses), - sort: q.sort - }, views[i]); - - views[i] = partial; - changed = true; - } - } - } - - return { - views: views, - clauses: clausesToCover - }; - } - - /** - * Apply JOIN operation in a set of views. - * Returns a set with the joined view. - * @param v - Set of candidated views to be joined. - */ - private static applyJoin(v: View[]): View[] { - - const views = v.map((i) => i); - - let dims: Dimension[] = []; - let mets: Metric[] = []; - let clauses: Clause[] = []; - - for (let i = 0; i < views.length; ++i) { - mets = mets.concat(views[i].metrics); - dims = dims.concat(views[i].dimensions); - clauses = clauses.concat(views[i].clauses); - } - - dims = ViewHandler.removeDuplicatedDimensions(dims); - mets = ViewHandler.removeDuplicatedMetrics(mets); - clauses = ViewHandler.removeDuplicatedClauses(clauses); - - const qOpts: QueryOpts = {metrics: mets, dimensions: dims, clauses: clauses}; - const partialQuery = new Query(qOpts); - - const partial = ViewHandler.queryJoin(partialQuery, views); - return [partial]; - } - - /** - * Removes repeated dimensions in a list of dimensions. - * @param candiateDims - A list of dimensions. - */ - private static removeDuplicatedDimensions(candidateDims: Dimension[]): Dimension[] { - let filterDims: { [key: string]: boolean } = {}; - const dims = []; - for (let i = 0; i < candidateDims.length; ++i) { - if (!filterDims[candidateDims[i].name]) { - dims.push(candidateDims[i]); - filterDims[candidateDims[i].name] = true; - } - } - return dims; - } - - /** - * Removes repeated dimensions in a list of metrics. - * @param candiateMets - A list of metrics. - */ - private static removeDuplicatedMetrics(candidateMets: Metric[]): Metric[] { - let filterMets: { [key: string]: boolean } = {}; - const mets = []; - for (let i = 0; i < candidateMets.length; ++i) { - if (!filterMets[candidateMets[i].name]) { - mets.push(candidateMets[i]); - filterMets[candidateMets[i].name] = true; - } - } - return mets; - } - - /** - * Removes repeated dimensions in a list of clauses. - * @param candiateClauses - A list of clauses. - */ - private static removeDuplicatedClauses(candidateClauses: Clause[]): Clause[] { - let filterClauses: { [key: string]: boolean } = {}; - const clauses = []; - for (let i = 0; i < candidateClauses.length; ++i) { - if (!filterClauses[candidateClauses[i].id]) { - clauses.push(candidateClauses[i]); - filterClauses[candidateClauses[i].id] = true; - } - } - return clauses; - } - } diff --git a/test/files/data.csv b/test/files/data.csv deleted file mode 100644 index 47783fd0ee7db1c1425741032efe42f9605048e0..0000000000000000000000000000000000000000 --- a/test/files/data.csv +++ /dev/null @@ -1,6 +0,0 @@ -dim:seller:sex,dim:seller:cpf,met:seller:avg:age -male,604.424.718-07,27 -female,575.657.111-60,26 -nonbinary,977.221.375-39,24 -undecided,344.805.128-45,23 -female,885.517.020-17,25 \ No newline at end of file diff --git a/test/files/data.ssv b/test/files/data.ssv deleted file mode 100644 index fa76b7ef2d198c5031c824bfd2c3d91aad9d68e9..0000000000000000000000000000000000000000 --- a/test/files/data.ssv +++ /dev/null @@ -1,6 +0,0 @@ -dim:seller:sex;dim:seller:cpf;met:seller:avg:age -male;604.424.718-07;27 -female;575.657.111-60;26 -nonbinary;977.221.375-39;24 -undecided;344.805.128-45;23 -female;885.517.020-17;25 \ No newline at end of file diff --git a/test/files/data.tsv b/test/files/data.tsv deleted file mode 100644 index 70d90f86559c0d52b753065211101ec9f914b8f3..0000000000000000000000000000000000000000 --- a/test/files/data.tsv +++ /dev/null @@ -1,6 +0,0 @@ -dim:seller:sex dim:seller:cpf met:seller:avg:age -male 604.424.718-07 27 -female 575.657.111-60 26 -nonbinary 977.221.375-39 24 -undecided 344.805.128-45 23 -female 885.517.020-17 25 \ No newline at end of file diff --git a/test/files/metrics.csv b/test/files/metrics.csv deleted file mode 100644 index 321a243d96a79c36266cf565974c951c74bb26f6..0000000000000000000000000000000000000000 --- a/test/files/metrics.csv +++ /dev/null @@ -1,17 +0,0 @@ -name;aggregation;dataType;description;tags -met:seller:avg:age;avg;float;The seller average age;"[""seller"",""age""]" -met:seller:max:age;max;integer;The seller highest age;"[""seller"",""age"",""max""]" -met:seller:min:age;min;integer;The seller lowest age;"[""seller"",""age""]" -met:seller:count:age;count;integer;The number of seller's;"[""seller"",""age""]" -met:product:avg:pricein;avg;float;The average product pricein;"[""product""]" -met:product:max:pricein;max;float;The highest product pricein;"[""product"",""max""]" -met:product:min:pricein;min;float;The lowest product pricein;"[""product""]" -met:product:avg:priceout;avg;float;The average product priceout;"[""product""]" -met:product:max:priceout;max;float;The highest product priceout;"[""product"",""max""]" -met:product:min:priceout;min;float;The lowest product priceout;"[""product""]" -met:sell:sum:quantity;sum;integer;The sum of sales quantity;[] -met:sell:avg:quantity;avg;float;The average of sales quantity;[] -met:sell:count:quantity;count;integer;The total number of sales;[] -met:buyout:avg:quantity;avg;float;The average of quantity bought;"[""buyout""]" -met:buyout:max:quantity;max;integer;The highest quantity bought;"[""buyout"",""max""]" -met:buyout:min:quantity;min;integer;The lowest quantity bought;"[""buyout""]" \ No newline at end of file diff --git a/test/mocha.opts b/test/mocha.opts index a7cd43ac3c0e25969dd0273f331d7169746b6efe..a77aa39d8340d7ebfdee336b6ad5585c46125f13 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -8,4 +8,3 @@ --check-leaks --globals expect ./src/**/*.spec.ts ---exit \ No newline at end of file diff --git a/test/monet/fixture.ts b/test/monet/fixture.ts deleted file mode 100644 index 835763bf4b33cf6197830dcd325f24edabcb2bf4..0000000000000000000000000000000000000000 --- a/test/monet/fixture.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre - * Departamento de Informatica - Universidade Federal do Parana - * - * This file is part of blend. - * - * blend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * blend is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with blend. If not, see <http://www.gnu.org/licenses/>. - */ - -const MDB = require("monetdb")(); -import { View, LoadView } from "../../src/core/view"; -import { Source } from "../../src/core/source"; -import { each, series } from "async"; -import { Connection } from "../../src/util/configParser"; -import * as fs from "fs"; -import { DataType } from "../../src/common/types"; - -export interface Schema { - alias?: string; - query?: string; - data?: string; - fields: any[]; -} - -export class Fixture { - private database: string; - private config: Connection; - - constructor(config: Connection) { - this.config = config; - this.database = config.database; - } - - public load(schemas: LoadView[], cb: (err: Error) => void): void { - let client = new MDB({ - user: this.config.user, - dbname: this.config.database, - password: this.config.password, - host: this.config.host, - port: this.config.port, - }); - - /* - Loading data has 2 steps: - 1 - Create a table or truncate a existing one. - 2 - Insert data. - */ - let data: string[] = []; - for (let i = 0; i < schemas.length; ++i) { - data = data.concat(this.extractDataView(schemas[i].view, schemas[i].data)); - } - client.connect(); - /* - Tables must be creates before data could be inserted, so the - queries that create and insert are splited in 2 arrays. - To garantee that tables exists before start insert data, series - is used. Inside series each query is executed, using each; - */ - - series([(callback: (err: Error) => void) => { - each(schemas, (query, cback) => { - client.query(this.createTransSet(query.view, query.data, true)).then((result: any) => cback()) - .fail((errCreate: Error) => { - if (errCreate){ - let regex = new RegExp(/42s01!create table: name \'.*\' already in use/); - if (regex.test(errCreate.message.toLocaleLowerCase())){ - return client.query(this.createTransSet(query.view, query.data, false)).then((result: any) => cback()) - .fail((errTrunc: Error) => (cback(errTrunc))); - } - } - return cback(errCreate); - }); - }, (errQuery: Error) => callback(errQuery)); - }, (callback: (err: Error) => void) => { - each(data, (query, cback) => { - return client.query(query).then((result: any) => cback()) - .fail((err: Error) => (cback(err))); - }, (errQuery: Error) => callback(errQuery)); - }], (errQuery: Error) => { - client.close(); - cb(errQuery); - }); - - } - - private typeConvertion(t: DataType): string { - switch (t) { - case DataType.INTEGER: - return "INTEGER"; - case DataType.DATE: - return "TIMESTAMP"; - case DataType.STRING: - return "TEXT"; - case DataType.BOOLEAN: - return "BOOLEAN"; - case DataType.FLOAT: - return "DOUBLE PRECISION"; - default: - return "TEXT"; - } - } - - private extractDataView(view: View, filePath: string): string[]{ - let name = view.name; - let data: string[] = []; - let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"})); - for (let i = 0; i < rows.length; ++i) { - let values = []; - let keys = []; - for (let key of Object.keys(rows[i])) { - keys.push("\"" + key + "\""); - values.push("'" + this.boolCast(rows[i][key]) + "'"); - } - data.push("INSERT INTO " + name + - "(" + keys.join(", ") + ") " + - "VALUES (" + values.join(", ") + ")"); - } - - return data; - - } - - private createTransSet(view: View, filePath: string, create: boolean): string { - let name = view.name; - let init: string = ""; - let props = []; - for (let i = 0; i < view.metrics.length; ++i) { - let met = view.metrics[i]; - props.push("\"" + met.name + "\" " + this.typeConvertion(met.dataType)); - } - for (let i = 0; i < view.dimensions.length; ++i) { - let dim = view.dimensions[i]; - props.push("\"" + dim.name + "\" " + this.typeConvertion(dim.dataType)); - } - if (create) { - init = "CREATE TABLE " + name + "(" + props.join(", ") + ")"; - } - else { - init = "DELETE FROM " + name; - } - return init; - } - - private boolCast(text: string): string { - if (text === "t") { - return "true"; - } - - else if (text === "f") { - return "false"; - } - - else { - return text; - } - } - - public loadSource(source: Source[] , cb: (err: Error) => void): void { - - let client = new MDB({ - user: this.config.user, - dbname: this.config.database, - password: this.config.password, - host: this.config.host, - port: this.config.port, - }); - - client.connect(); - - series([(callback: (err: Error) => void) => { - each(source, (insere, cback) => { - client.query(this.extractData(insere, true)).then((result: any) => cback()) - .fail((errCreate: Error) => { - if (errCreate) { - let regex = new RegExp(/42s01!create table: name \'.*\' already in use/); - if (regex.test(errCreate.message.toLocaleLowerCase())){ - return client.query(this.extractData(insere, false)).then((result: any) => cback()) - .fail((errTrunc: Error) => (cback(errTrunc))); - } - } - return cback(errCreate); - }); - }, (errQuery: Error) => callback(errQuery)); - }], (errQuery: Error) => { - client.close(); - cb(errQuery); - }); - } - - private extractData(data: Source, create: boolean): string{ - let name: string; - let type: DataType[]; - let fields: string[]; - let consult: string; - - name = data.name; - type = data.fields.map((item) => item.dataType); - fields = data.fields.map((item) => item.name); - - if (create){ - consult = "CREATE TABLE " + name + " (" + '"'; - for (let i = 0; i < fields.length; i++){ - fields[i] = fields[i].concat('"' + " " + this.typeConvertion(type[i])); - } - consult = consult.concat(fields.join(", " + '"')); - consult = consult.concat(");"); - } - else{ - consult = "DELETE FROM " + name + ";"; - } - - return consult; - - } -} diff --git a/test/monet/fixtures b/test/monet/fixtures deleted file mode 120000 index 410001b097c384463e158a7a38376382c18a0e41..0000000000000000000000000000000000000000 --- a/test/monet/fixtures +++ /dev/null @@ -1 +0,0 @@ -../postgres/fixtures/ \ No newline at end of file diff --git a/test/postgres/fixture.ts b/test/postgres/fixture.ts index 57e761a4d026c0c8551f94b5148c5493ab689c77..1f7b892d37bade3b7a3f012d93c2fab198088eb2 100644 --- a/test/postgres/fixture.ts +++ b/test/postgres/fixture.ts @@ -20,22 +20,14 @@ import { Client, PoolConfig } from "pg"; import { View, LoadView } from "../../src/core/view"; -import { Source } from "../../src/core/source"; import { each, series } from "async"; import * as fs from "fs"; -import { DataType } from "../../src/common/types"; interface TransSet { init: string; data: string[]; } -interface SoucerParse{ - name: string; - type: string[]; - fields: string[]; -} - export interface Schema { alias?: string; query?: string; @@ -52,23 +44,31 @@ export class Fixture { this.database = config.database; } - public load(schemas: LoadView[], cb: (err: Error) => void): void { + public load(schemas: LoadView[], create: boolean, cb: (err: Error) => void) { let client = new Client(this.config); /* Loading data has 2 steps: 1 - Create a table or truncate a existing one. + Create or truncate dependes from a parameter in the configure + file, this parameter reaches this function as the create + parameter. 2 - Insert data. */ + let init: string[] = []; let data: string[] = []; for (let i = 0; i < schemas.length; ++i) { - data = data.concat(this.extractDataView(schemas[i].view, schemas[i].data)); + let table: TransSet = this.createTransSet(schemas[i].view, schemas[i].data, create); + init.push(table.init); + data = data.concat(table.data); } + client.connect((error) => { if (error) { cb(error); return; } + /* Tables must be creates before data could be inserted, so the queries that create and insert are splited in 2 arrays. @@ -76,20 +76,12 @@ export class Fixture { is used. Inside series each query is executed, using each; */ series([(callback: (err: Error) => void) => { - each(schemas, (query, cback) => { - client.query(this.createTransSet(query.view, query.data, true), [], (errCreate: Error) => { - if (errCreate) { - let regex = new RegExp(/relation \".*\" already exists/); - if (regex.test(errCreate.message.toLowerCase())){ - return client.query(this.createTransSet(query.view, query.data, false), [], (errTrunc: Error) => cback(errTrunc)); - } - } - return cback(errCreate); - }); + each(init, (query, cback) => { + return client.query(query, [], (err: Error) => cback(err)); }, (errQuery: Error) => callback(errQuery)); }, (callback: (err: Error) => void) => { each(data, (query, cback) => { - return client.query( query, [], (err: Error) => cback(err)); + return client.query(query, [], (err: Error) => cback(err)); }, (errQuery: Error) => callback(errQuery)); }], (errQuery: Error) => { if (errQuery) { @@ -104,119 +96,56 @@ export class Fixture { }); } - private typeConvertion(t: DataType): string { + private typeConvertion(t: string) { switch (t) { - case DataType.INTEGER: + case "integer": return "INTEGER"; - case DataType.DATE: + case "date": return "DATE"; - case DataType.STRING: + case "string": return "TEXT"; - case DataType.BOOLEAN: + case "boolean": return "BOOLEAN"; - case DataType.FLOAT: - return "DOUBLE PRECISION"; default: - return "TEXT"; + return ""; } } - private extractDataView(view: View, filePath: string): string[]{ - let name = view.name; - let data: string[] = []; - let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"})); - for (let i = 0; i < rows.length; ++i) { - let values = []; - let keys = []; - for (let key of Object.keys(rows[i])) { - keys.push("\"" + key + "\""); - values.push("'" + rows[i][key] + "'"); - } - data.push("INSERT INTO " + name + - "(" + keys.join(", ") + ") " + - "VALUES (" + values.join(", ") + ")"); - } - - return data; - - } - - private createTransSet(view: View, filePath: string, create: boolean): string { - let name = view.name; - let init: string = ""; + private createTransSet(view: View, filePath: string, create: boolean) { let props = []; + for (let i = 0; i < view.metrics.length; ++i) { let met = view.metrics[i]; props.push("\"" + met.name + "\" " + this.typeConvertion(met.dataType)); } + for (let i = 0; i < view.dimensions.length; ++i) { let dim = view.dimensions[i]; props.push("\"" + dim.name + "\" " + this.typeConvertion(dim.dataType)); } + + let name = "view_" + view.id; + let transaction: TransSet = {init: "", data: []}; if (create) { - init = "CREATE TABLE " + name + "(" + props.join(", ") + ")"; + transaction.init = "CREATE TABLE " + name + "(" + props.join(", ") + ")"; } else { - init = "TRUNCATE TABLE " + name; + transaction.init = "TRUNCATE TABLE " + name; } - return init; - } - public loadSource(source: Source[] , cb: (err: Error) => void): void { - let client = new Client(this.config); - - client.connect((error) => { - if (error) { - cb(error); - return; + transaction.data = []; + let rows = JSON.parse(fs.readFileSync(filePath, {encoding : "utf8"})); + for (let i = 0; i < rows.length; ++i) { + let values = []; + let keys = []; + for (let key in rows[i]) { + keys.push("\"" + key + "\""); + values.push("'" + rows[i][key] + "'"); } - series([(callback: (err: Error) => void) => { - each(source, (insere, cback) => { - client.query ( this.extractData(insere, true), [], (errCreate: Error) => { - if (errCreate) { - let regex = new RegExp(/relation \".*\" already exists/); - if (regex.test(errCreate.message.toLowerCase())){ - return client.query ( this.extractData(insere, false), [], (errTrunc: Error) => cback(errTrunc)); - } - } - return cback(errCreate); - }); - }, (errQuery: Error) => callback(errQuery)); - }], (errQuery: Error) => { - if (errQuery) { - client.end(); - cb(errQuery); - } - client.end((err) => { - cb(err); - }); - }); - - }); - } - private extractData(data: Source, create: boolean): string{ - let name: string; - let type: DataType[]; - let fields: string[]; - let consult: string; - - name = data.name; - type = data.fields.map((item) => item.dataType); - fields = data.fields.map((item) => item.name); - - if (create){ - consult = "CREATE TABLE " + name + " (" + '"'; - for (let i = 0; i < fields.length; i++){ - fields[i] = fields[i].concat('"' + " " + this.typeConvertion(type[i])); - } - consult = consult.concat(fields.join(", " + '"')); - consult = consult.concat(");"); - } - else{ - consult = "TRUNCATE TABLE " + name + ";"; + transaction.data.push("INSERT INTO " + name + + "(" + keys.join(", ") + ") " + + "VALUES (" + values.join(", ") + ")"); } - - return consult; - + return transaction; } } diff --git a/test/postgres/fixtures/activeseller.json b/test/postgres/fixtures/activeseller.json deleted file mode 100644 index a4681a2cc0fc721166f9a17bfc32f81ed8df8ab5..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/activeseller.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - {"met:seller:max:age": 23, "dim:seller:name": "Ade", "dim:seller:status": "active"} - ,{"met:seller:max:age": 24, "dim:seller:name": "Luanne", "dim:seller:status": "active"} - ,{"met:seller:max:age": 25, "dim:seller:name": "Florinda", "dim:seller:status": "active"} - ,{"met:seller:max:age": 26, "dim:seller:name": "Bryanna", "dim:seller:status": "active"} - ,{"met:seller:max:age": 27, "dim:seller:name": "Salvatore", "dim:seller:status": "sick leave"} -] diff --git a/test/postgres/fixtures/buyout.json b/test/postgres/fixtures/buyout.json deleted file mode 100644 index 5423c86bacd6c34d654781e361fb461ace4d49be..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/buyout.json +++ /dev/null @@ -1,12 +0,0 @@ -[ -{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 20, "dim:product:id": 53 -, "met:buyout:avg:quantity": 100,"met:buyout:max:quantity": 100,"met:buyout:min:quantity": 100}, -{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 21, "dim:product:id": 54 -, "met:buyout:avg:quantity": 120,"met:buyout:max:quantity": 120,"met:buyout:min:quantity": 120}, -{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 22, "dim:product:id": 55 -, "met:buyout:avg:quantity": 130,"met:buyout:max:quantity": 130,"met:buyout:min:quantity": 130}, -{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 23, "dim:product:id": 56 -, "met:buyout:avg:quantity": 140,"met:buyout:max:quantity": 140,"met:buyout:min:quantity": 140}, -{ "dim:buyout:datein": "2018-01-01", "dim:provider:id": 24, "dim:product:id": 57 -, "met:buyout:avg:quantity": 200,"met:buyout:max:quantity": 200,"met:buyout:min:quantity": 200} -] diff --git a/test/postgres/fixtures/client.json b/test/postgres/fixtures/client.json deleted file mode 100644 index e575b647d1aac590bbaaaa2ca2917056934fa36e..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/client.json +++ /dev/null @@ -1,7 +0,0 @@ -[ -{"dim:client:name": "Somboom", "dim:client:cpf": "500.345.583-65","dim:client:id": "7"}, -{"dim:client:name": "Laci", "dim:client:cpf": "787.785.521-41","dim:client:id": "8"}, -{"dim:client:name": "Rosalin", "dim:client:cpf": "463.478.120-45","dim:client:id": "9"}, -{"dim:client:name": "Firoz", "dim:client:cpf": "352.324.206-15","dim:client:id": "10"}, -{"dim:client:name": "Ravindra", "dim:client:cpf": "944.189.449-40","dim:client:id": "11"} -] diff --git a/test/postgres/fixtures/distribute.json b/test/postgres/fixtures/distribute.json deleted file mode 100644 index b1aa029f1a6d4521ddb5014ba9eafa6f09cf5c46..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/distribute.json +++ /dev/null @@ -1,7 +0,0 @@ -[ -{"dim:provider:id": 1,"dim:product:id": 53}, -{"dim:provider:id": 2,"dim:product:id": 54}, -{"dim:provider:id": 3,"dim:product:id": 55}, -{"dim:provider:id": 4,"dim:product:id": 56}, -{"dim:provider:id": 5,"dim:product:id": 57} -] \ No newline at end of file diff --git a/test/postgres/fixtures/product.json b/test/postgres/fixtures/product.json deleted file mode 100644 index d053e57cb31e6983ba339b04deb55de58d225f59..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/product.json +++ /dev/null @@ -1,17 +0,0 @@ -[ -{"dim:product:name": "Bacon", "dim:product:validity": "2018-03-01", "dim:product:id":53, -"met:product:avg:pricein": 10.20, "met:product:max:pricein": 10.20, "met:product:min:pricein":10.20, -"met:product:avg:priceout": 10.20, "met:product:max:priceout": 10.20, "met:product:min:priceout":10.20}, -{"dim:product:name": "Coal", "dim:product:validity": "2018-05-10", "dim:product:id": 54, -"met:product:avg:pricein": 8.20, "met:product:max:pricein": 8.20, "met:product:min:pricein":8.20, -"met:product:avg:priceout": 8.20, "met:product:max:priceout": 8.20, "met:product:min:priceout": 8.20}, -{"dim:product:name": "Meat", "dim:product:validity": "2018-02-17", "dim:product:id": 55 , -"met:product:avg:pricein": 17.50, "met:product:max:pricein": 17.50, "met:product:min:pricein":17.50, -"met:product:avg:priceout": 17.50, "met:product:max:priceout": 17.50, "met:product:min:priceout": 17.50}, -{"dim:product:name": "Beer", "dim:product:validity": "2018-06-10", "dim:product:id": 56 , -"met:product:avg:pricein": 6.50 , "met:product:max:pricein": 6.50, "met:product:min:pricein":6.50, -"met:product:avg:priceout": 6.50, "met:product:max:priceout": 6.50, "met:product:min:priceout":6.50}, -{"dim:product:name": "Trento", "dim:product:validity": "2018-08-23" , "dim:product:id": 57 , -"met:product:avg:pricein": 2.50, "met:product:max:pricein": 2.50, "met:product:min:pricein": 2.50, -"met:product:avg:priceout": 2.50, "met:product:max:priceout": 2.50, "met:product:min:priceout": 2.50} -] diff --git a/test/postgres/fixtures/provider.json b/test/postgres/fixtures/provider.json deleted file mode 100644 index 2b1819d275ec972c4a7db655fe09b08d19c82b75..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/provider.json +++ /dev/null @@ -1,7 +0,0 @@ -[ -{"dim:provider:name": "ProviderA","dim:provider:id": 1 }, -{"dim:provider:name": "ProviderB","dim:provider:id": 2 }, -{"dim:provider:name": "ProviderC","dim:provider:id": 3 }, -{"dim:provider:name": "ProviderD","dim:provider:id": 4 }, -{"dim:provider:name": "ProviderE","dim:provider:id": 5 } -] diff --git a/test/postgres/fixtures/sell.json b/test/postgres/fixtures/sell.json deleted file mode 100644 index 3f84218bd08ec64d3149dab9643a538dd92ccde9..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/sell.json +++ /dev/null @@ -1,17 +0,0 @@ -[ -{ "dim:sell:registered": true, "dim:product:id": 53, "dim:seller:id": 1 -, "dim:client:id": 7, "dim:sell:datein": "2018-02-17", "met:sell:sum:quantity": 10 -, "met:sell:avg:quantity": 10 , "met:sell:count:quantity": 1}, -{ "dim:sell:registered": true, "dim:product:id": 54, "dim:seller:id": 2 -, "dim:client:id": 8, "dim:sell:datein": "2018-01-23", "met:sell:sum:quantity": 12 -, "met:sell:avg:quantity": 12, "met:sell:count:quantity": 1}, -{ "dim:sell:registered": false, "dim:product:id": 55, "dim:seller:id": 3 -, "dim:client:id": 0, "dim:sell:datein": "2018-01-25", "met:sell:sum:quantity": 5 -, "met:sell:avg:quantity": 5, "met:sell:count:quantity": 1}, -{ "dim:sell:registered": true, "dim:product:id": 56, "dim:seller:id": 4 -, "dim:client:id": 9, "dim:sell:datein": "2018-03-22", "met:sell:sum:quantity": 2 -, "met:sell:avg:quantity": 2, "met:sell:count:quantity": 1}, -{ "dim:sell:registered": true, "dim:product:id": 57, "dim:seller:id": 5 -, "dim:client:id": 10, "dim:sell:datein": "2018-02-21", "met:sell:sum:quantity": 10 -, "met:sell:avg:quantity": 10, "met:sell:count:quantity": 1} -] diff --git a/test/postgres/fixtures/seller.json b/test/postgres/fixtures/seller.json deleted file mode 100644 index 7408e7e6275b3c69edc935c7e051d72161f71fc6..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/seller.json +++ /dev/null @@ -1,17 +0,0 @@ -[ -{"dim:seller:name": "Ade", "dim:seller:sex": "undecided", "dim:seller:cpf":"344.805.128-45" -, "dim:seller:id": 1 , "dim:seller:status": "active", "met:seller:avg:age": 23 -, "met:seller:max:age": 23, "met:seller:min:age":23, "met:seller:count:age": 1}, -{"dim:seller:name": "Luanne", "dim:seller:sex": "nonbinary", "dim:seller:cpf":"977.221.375-39" - , "dim:seller:id": 2 , "dim:seller:status": "active", "met:seller:avg:age": 24 - , "met:seller:max:age": 24, "met:seller:min:age":24, "met:seller:count:age": 1}, -{"dim:seller:name": "Florinda", "dim:seller:sex": "female", "dim:seller:cpf":"885.517.020-17" - , "dim:seller:id": 3 , "dim:seller:status": "active", "met:seller:avg:age": 25 - , "met:seller:max:age": 25, "met:seller:min:age":25, "met:seller:count:age": 1}, -{"dim:seller:name": "Bryanna", "dim:seller:sex": "female", "dim:seller:cpf":"575.657.111-60" - , "dim:seller:id": 4 , "dim:seller:status": "active", "met:seller:avg:age": 26 - , "met:seller:max:age": 26, "met:seller:min:age":26, "met:seller:count:age": 1}, -{"dim:seller:name": "Salvatore", "dim:seller:sex": "male", "dim:seller:cpf":"604.424.718-07" - , "dim:seller:id": 5 , "dim:seller:status": "sick leave", "met:seller:avg:age": 27 - , "met:seller:max:age": 27, "met:seller:min:age":27, "met:seller:count:age": 1} -] diff --git a/test/postgres/fixtures/sellerstatus.json b/test/postgres/fixtures/sellerstatus.json deleted file mode 100644 index c9d05e0acd2ccd3cdd3913dd8f4e05a21894d4bc..0000000000000000000000000000000000000000 --- a/test/postgres/fixtures/sellerstatus.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"met:seller:count:age" : 4, "dim:seller:status" : "active"}, - {"met:seller:count:age" : 1, "dim:seller:status" : "sick leave"} -] diff --git a/test/scenario.ts b/test/scenario.ts index d598f79ecd548b1ea24b87d8cf42048bede546b8..1fb2fac343ffd0ecc5596a7466ccfab1aa3ee0a1 100644 --- a/test/scenario.ts +++ b/test/scenario.ts @@ -24,422 +24,390 @@ import { Dimension } from "../src/core/dimension"; import { View } from "../src/core/view"; import { Filter, FilterOperator } from "../src/core/filter"; import { Clause } from "../src/core/clause"; -import { AggregationType, RelationType , DataType} from "../src/common/types"; -import { ViewHandler } from "../src/util/viewHandler"; -import { EngineScenario, AdapterScenario, DataCtrlScenario } from "../src/util/scenarioHandler"; -import { Query, QueryOpts } from "../src/common/query"; - -let configPath; - -if(process.env.BLENDB_SCHEMA_FILE){ - configPath = process.env.BLENDB_SCHEMA_FILE; -} -else{ - throw new Error("BLENDB_SCHEMA_FILE wasn't informed"); +import { AggregationType, RelationType } from "../src/common/types"; +import { Query} from "../src/common/query"; + +interface EngineScenario { + metrics: Metric[]; + dimensions: Dimension[]; + subDimensions: Dimension[]; + wrongMet: Metric; + wrongDim: Dimension; + views: View[]; } -const config = ConfigParser.parse(configPath); - -const mets : {[key: string]: Metric} = {}; -for (let i in config.metrics) { - let met = config.metrics[i]; - mets[met.name] = met; +interface AdapterScenario { + materializedView: View; + noSelectionView: View; + withSelectionView: View; + subDimensionView: View; + join4View: View; + dateView: View; + aggrView: View; + clauseView: View; + multiFilterView: View; + multiClauseView: View; + notEqualView: View; + gtltView: View; + geleView: View; + notMatchFilterView: View; + notOriginCount: View; + unMaterializebleView: View; + partialJoinView: View; + propagatedClauseView: View; + propagatedClauseAggrView: View; } -const dims : {[key:string]: Dimension} = {}; -for (let i in config.dimensions) { - let dim = config.dimensions[i]; - dims[dim.name] = dim; +interface DataCtrlScenario { + wrongMet: Query; + wrongDim: Query; + correct: Query; + clausal: Query; } -const views : {[key:string]: View} = {}; -for (let i in config.buildViews){ - let view = config.buildViews[i]; - views[view.alias] = view.view; -} +const config = ConfigParser.parse("config/test.yaml"); -const wrongMet = new Metric({ - name: "met:this:is:just:a:test", - aggregation: AggregationType.COUNT, - dataType: DataType.INTEGER +const mets = config.metrics.sort((a, b) => { + const aValue = parseInt(a.name.split(":")[1], 10); + const bValue = parseInt(b.name.split(":")[1], 10); + return aValue - bValue; }); +const dims = config.dimensions.sort((a, b) => { + const aValue = parseInt(a.name.split(":")[1], 10); + const bValue = parseInt(b.name.split(":")[1], 10); + return aValue - bValue; +}); +const views = config.buildViews.sort((a, b) => { + const aValue = parseInt(a.alias.split(" ")[1], 10); + const bValue = parseInt(b.alias.split(" ")[1], 10); + return aValue - bValue; +}).map((item) => item.view); -const wrongDim = new Dimension({ name: "dim:this:is:just:a:test", dataType: DataType.INTEGER }); - -/** - * Create new filters to use in clause and test - * the clauses - */ const filters: { [key: string]: Filter } = { - "equal" : new Filter({ - target : dims["dim:product:validity"], - operator : FilterOperator.EQUAL, - value: "2018-05-10" + "dim:0:0" : new Filter({ + target: dims[0], + operator: FilterOperator.EQUAL, + value: "2017-01-02" }), - "lower" : new Filter({ - target : dims["dim:product:validity"], - operator : FilterOperator.LOWER, - value: "2018-05-10" + "dim:0:1" : new Filter({ + target: dims[0], + operator: FilterOperator.EQUAL, + value: "2017-01-03" }), - "greater" : new Filter({ - target : dims["dim:product:validity"], - operator : FilterOperator.GREATER, - value: "2018-05-10" + "dim:0:gt" : new Filter({ + target: dims[0], + operator: FilterOperator.GREATER, + value: "2017-01-02" }), - "greaterq" : new Filter({ - target : dims["dim:product:validity"], - operator : FilterOperator.GREATEREQ, - value: "2018-06-10" + "dim:0:lt" : new Filter({ + target: dims[0], + operator: FilterOperator.LOWER, + value: "2017-01-04" + }), + "dim:0:ge" : new Filter({ + target: dims[0], + operator: FilterOperator.GREATEREQ, + value: "2017-01-02" }), - "lowerq" : new Filter({ - target : dims["dim:product:validity"], - operator : FilterOperator.LOWEREQ, - value: "2018-06-10" + "dim:0:le" : new Filter({ + target: dims[0], + operator: FilterOperator.LOWEREQ, + value: "2017-01-04" }), - "noteq" : new Filter({ - target: dims["dim:product:validity"], + "dim:2" : new Filter({ + target: dims[2], operator: FilterOperator.NOTEQUAL, - value: "2018-08-23" + value: "1" }), - "clientRegistered" : new Filter({ - target: dims["dim:sell:registered"], - operator: FilterOperator.EQUAL, - value: "false" + "dim:4" : new Filter({ + target: dims[4], + operator: FilterOperator.NOTEQUAL, + value: "dim:4:1" }), - "averageBought": new Filter({ - target: mets["met:sell:avg:quantity"], - operator: FilterOperator.GREATEREQ, - value: "10" + "dim:5" : new Filter({ + target: dims[5], + operator: FilterOperator.NOTEQUAL, + value: "true" }), - "equalFilterView": new Filter({ - target: dims["dim:seller:status"], + "dim:7" : new Filter({ + target: dims[7], operator: FilterOperator.EQUAL, - value: "active" - }), - "noneFilter": new Filter({ - target: dims["dim:seller:status"], - operator: FilterOperator.NONE, - value: "active" + value: "1" }) -} +}; -const subdims : {[key:string]: Dimension} = { - "subdims_day" : new Dimension({ - name: "subdims_day", - dataType: DataType.INTEGER, - parent: dims["dim:sell:datein"], +const clauses: { [key: string]: Clause } = { + "view0dim7": new Clause({filters: [filters["dim:7"]]}), + "view0gt": new Clause({filters: [filters["dim:0:gt"]]}), + "view0lt": new Clause({filters: [filters["dim:0:lt"]]}), + "view0ge": new Clause({filters: [filters["dim:0:ge"]]}), + "view0le": new Clause({filters: [filters["dim:0:le"]]}), + "view0dim0": new Clause({filters: [filters["dim:0:0"], filters["dim:0:1"]]}), + "view9dim2": new Clause({filters: [filters["dim:2"]]}), + "view6dim4": new Clause({filters: [filters["dim:4"]]}), + "view7dim5": new Clause({filters: [filters["dim:5"]]}) +}; + +const wrongMet = new Metric({ + name: "met:-1", + aggregation: AggregationType.COUNT, + dataType: "integer" +}); +const wrongDim = new Dimension({ name: "dim:-1", dataType: "integer" }); + +const subdimAux = new Dimension({ + name: "sub:0", + dataType: "integer", + parent: dims[0], + relation: RelationType.DAY +}); + +const subdims = [ + subdimAux, + new Dimension({ + name: "sub:1", + dataType: "integer", + parent: dims[1], relation: RelationType.DAY }), - "subdims_month" : new Dimension({ - name: "subdims_month", - dataType: DataType.INTEGER, - parent: dims["dim:sell:datein"], - relation: RelationType.MONTH - }), - "subdims_year" : new Dimension({ - name: "subdims_year", - dataType: DataType.INTEGER, - parent: dims["dim:sell:datein"], - relation: RelationType.YEAR + new Dimension({ + name: "sub:2", + dataType: "integer", + parent: subdimAux, + relation: RelationType.DAY }), - "subdims_none" : new Dimension({ - name: "subdims_none", - dataType: DataType.INTEGER, + new Dimension({ + name: "sub:3", + dataType: "integer", parent: null, - relation: RelationType.NONE + relation: RelationType.DAY + }), + new Dimension({ + name: "sub:4", + dataType: "integer", + parent: dims[1], + relation: RelationType.DAY }) -} - -const clauses: { [key: string]: Clause } = { - "lastDay": - new Clause({filters: [filters["equal"]]}), - "undefined": - new Clause({filters: [filters["noteq"]]}), - "unexpired": - new Clause({filters: [filters["greater"]]}), - "expired": - new Clause({filters: [filters["lower"]]}), - "unexpiredLastDay": - new Clause({filters: [filters["greaterq"]]}), - "expiredlastDay": - new Clause({filters: [filters["lowerq"]]}), - "clientRegistered": - new Clause({filters: [filters["clientRegistered"]]}), - "averageBought": - new Clause({filters: [filters["averageBought"]]}), - "expiredAndAverage": - // or between filteres => (A) || (B) - new Clause ({filters: [filters["lower"],filters["averageBought"]]}), - "equalClauseView": - new Clause ({filters: [filters["equalFilterView"]]}), - "emptyClause": - new Clause ({filters: []}) -} +].sort((a, b) => { + const aValue = parseInt(a.name.split(":")[1], 10); + const bValue = parseInt(b.name.split(":")[1], 10); + return aValue - bValue; +}); +const dateSubDim = [ + new Dimension ({ + name: "dim:0:month", + dataType: "integer", + parent: dims[0], + relation: RelationType.MONTH + }), + new Dimension ({ + name: "dim:0:day", + dataType: "integer", + parent: dims[0], + relation: RelationType.DAY + }), + new Dimension ({ + name: "dim:0:year", + dataType: "integer", + parent: dims[0], + relation: RelationType.YEAR + }), + new Dimension ({ + name: "dim:0:dow", + dataType: "integer", + parent: dims[0], + relation: RelationType.DAYOFWEEK + }), +]; + +const dateView = new View({ + metrics: [], + dimensions: dateSubDim, + materialized: false, + origin: false, + childViews: [views[0]] +}); -let qOpts : {[key: string]: QueryOpts} = { - "JoinWithAncestors": - { - metrics: [mets["met:sell:count:quantity"]], - dimensions: [dims["dim:seller:id"],dims["dim:provider:id"]] - }, - "joinWithNoMetrics": - { - metrics: [], - dimensions: [dims["dim:product:name"],dims["dim:seller:name"]] - }, - "growOneView": - { - metrics: [mets["met:seller:min:age"]], - dimensions: [dims["dim:seller:name"],dims["dim:seller:sex"]] - }, - "multipleClause": - { - metrics: [mets["met:sell:avg:quantity"]], - dimensions: [dims["dim:sell:datein"],dims["dim:seller:name"], - dims["dim:client:name"]], - // and between filters => (A) and (B) - clauses: [clauses["expired"],clauses["averageBought"]], - }, - "singleClause": - { - metrics: [mets["met:sell:avg:quantity"]], - dimensions: [dims["dim:sell:datein"],dims["dim:seller:name"], - dims["dim:client:name"]], - clauses: [clauses["expiredAndAverage"]], - }, - "equalfilter": - { - metrics: [], - dimensions: [dims["dim:client:name"],dims["dim:product:validity"]], - clauses: [clauses["lastDay"]], - }, - "withSortView:0": - { - metrics: [mets["met:sell:sum:quantity"]], - dimensions: [dims["dim:client:name"]], - sort: [mets["met:sell:sum:quantity"]] - }, - "withSortView:1": - { - metrics: [mets["met:sell:sum:quantity"]], - dimensions: [dims["dim:client:id"]] - }, - "subDimView:0": - { - metrics: [], - dimensions : [dims["dim:sell:datein"],subdims["subdims_day"], - subdims["subdims_month"],subdims["subdims_year"]] - }, - "subDimView:1": - { - metrics: [], - dimensions: [dims["dim:sell:datein"]] - }, - "joinOneView": - { - metrics: [mets["met:product:avg:pricein"]], - dimensions: [], - }, - "reduceAsView": - { - metrics: [mets["met:sell:sum:quantity"],mets["met:sell:avg:quantity"], - mets["met:sell:count:quantity"]], - dimensions: [dims["dim:sell:registered"], dims["dim:product:id"], - dims["dim:seller:id"], dims["dim:client:id"],dims["dim:sell:datein"]], - sort: [mets["met:sell:sum:quantity"]] - }, - "clientAverageBought:0": - { - metrics: [mets["met:sell:avg:quantity"]], - dimensions: [dims["dim:client:name"]], - clauses: [clauses["averageBought"]] - }, - "clientAverageBought:1": - { - metrics: [mets["met:sell:avg:quantity"]], - dimensions: [dims["dim:client:name"], dims["dim:seller:id"]] - }, - "queryNoParent": - { - metrics: [mets["met:sell:count:quantity"]], - dimensions: [subdims["subdims_none"]] - }, - "queryMetsDims": - { - metrics : Object.keys(mets).map((key) => mets[key]), - dimensions : Object.keys(dims).map((key) => dims[key]) - }, - "queryNoMets": - { - metrics: [wrongMet], - dimensions: [dims["dim:product:name"]] - }, - "queryNoDims": - { - metrics: [mets["met:buyout:min:quantity"]], - dimensions: [wrongDim] - }, - "queryProduct": - { - metrics: [mets["met:product:avg:pricein"], mets["met:product:max:pricein"], mets["met:product:min:pricein"], - mets["met:product:avg:priceout"],mets["met:product:max:priceout"],mets["met:product:min:priceout"]], - dimensions: [dims["dim:product:name"], dims["dim:product:validity"],dims["dim:product:id"]] - }, - "queryActive": - { - metrics: [mets["met:seller:max:age"]], - dimensions: [dims["dim:seller:name"],dims["dim:seller:status"]], - clauses: [clauses["equalClauseView"]] - }, - "querySubDim": - { - metrics : [], - dimensions : [subdims["subdims_day"],subdims["subdims_month"]] - }, - "wrongMet": - { - metrics: [wrongMet], - dimensions: [dims["dim:product:id"]] - }, - "seller": - { - metrics:[mets["met:sell:sum:quantity"]], - dimensions:[dims["dim:sell:registered"],dims["dim:product:id"]] - }, - "wrongDim": - { - metrics: [mets["met:sell:avg:quantity"]], - dimensions: [wrongDim] - }, - "correct": - { - metrics: [mets["met:buyout:avg:quantity"]], - dimensions: [dims["dim:provider:id"]] - }, - "clausal": - { - metrics: [mets["met:product:avg:pricein"]], - dimensions: [dims["dim:product:name"], - dims["dim:product:id"]] - }, - "expensive": - { - metrics: [mets["met:product:max:pricein"]], - dimensions: [dims["dim:product:name"], - dims["dim:product:id"]] - }, - "originfalse": - { - metrics: [mets["met:seller:count:age"]], - dimensions: [] - }, - "csv": { - metrics: [mets["met:seller:avg:age"]], - dimensions: [dims["dim:seller:cpf"], dims["dim:seller:sex"]] - } -} +const aggrView = new View({ + metrics: [mets[0], mets[1], mets[6], mets[10], mets[11]], + dimensions: [], + materialized: false, + origin: false, + childViews: [views[0], views[2], views[3]] +}); -const queries : {[key: string]: Query} = {}; -for(let i in qOpts){ - queries[i] = new Query(qOpts[i]); -} +const clauseView = new View({ + metrics: [mets[0], mets[1], mets[2]], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view0dim7] +}); -const JoinWithAncestors = ViewHandler.growView(queries["JoinWithAncestors"], - [views["view:Sell"]]); +const multiFilterView = new View({ + metrics: [mets[0], mets[1]], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view0dim0] +}); -const joinWithNoMetrics = ViewHandler.growView(queries["joinWithNoMetrics"], - [views["view:Product"], - views["view:Sell"], - views["view:Seller"]]); +const multiClauseView = new View({ + metrics: [mets[0], mets[1]], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view0dim0, clauses.view0dim7] +}); -const growOneView = ViewHandler.growView(queries["growOneView"], - [views["view:Seller"]]); +const notEqualView = new View({ + metrics: [], + dimensions: [dims[4], dims[5]], + materialized: false, + origin: false, + childViews: [views[7]], + clauses: [clauses.view7dim5] +}); -const multipleClause = ViewHandler.growView(queries["multipleClause"], - [views["view:Sell"], - views["view:Seller"], - views["view:Client"], - views["view:Product"]]); +const gtltView = new View({ + metrics: [], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view0gt, clauses.view0lt] +}); -const singleClause = ViewHandler.growView(queries["singleClause"], - [views["view:Sell"], - views["view:Seller"], - views["view:Client"], - views["view:Product"]]); +const geleView = new View({ + metrics: [], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view0ge, clauses.view0le] +}); -const equalfilter = ViewHandler.queryJoin(queries["equalfilter"], - [views["view:Sell"], - views["view:Client"], - views["view:Product"]]); +const notMatchFilterView = new View({ + metrics: [mets[0]], + dimensions: [dims[0]], + materialized: false, + origin: false, + childViews: [views[0]], + clauses: [clauses.view7dim5] +}); -const withSortView = ViewHandler.queryJoin(queries["withSortView:0"], - [ViewHandler.queryReduce(queries["withSortView:1"], - views["view:Sell"]), - views["view:Client"]]); +const subDimView = new View({ + metrics: [mets[0]], + dimensions: [subdims[0], subdims[1], dims[7], dims[8]], + materialized: false, + origin: false, + childViews: [views[0], views[1], views[4]] +}); -const subDimView = ViewHandler.queryJoin(queries["subDimView:0"], - [ViewHandler.queryReduce(queries["subDimView:1"], - views["view:Sell"]), - views["view:Sell"]]); +const join4View = new View({ + metrics: [mets[0], mets[1], mets[2], mets[3], mets[4], mets[5]], + dimensions: [dims[2], dims[7], dims[8]], + materialized: false, + origin: false, + childViews: [views[0], views[1], views[2], views[4]] +}); -const joinOneView = ViewHandler.queryJoin(queries["joinOneView"], - [views["view:Product"]]); +const noSelView = new View({ + metrics: [mets[0], mets[3]], + dimensions: [], + materialized: false, + origin: false, + childViews: [views[0], views[1]] +}); -const reduceAsView = ViewHandler.queryReduce(queries["reduceAsView"], - views["view:Sell"]); +const withSelView = new View({ + metrics: [mets[0], mets[1]], + dimensions: [dims[7], dims[8]], + materialized: false, + origin: false, + childViews: [views[0], views[4]] +}); -const clientAverageBought = ViewHandler.queryReduce(queries["clientAverageBought:0"], - ViewHandler.queryJoin(queries["clientAverageBought:1"], - [views["view:Sell"],views["view:Client"]])); +const notOriginCount = new View({ + metrics: [mets[5], mets[6], mets[7]], + dimensions: [dims[2]], + materialized: true, + origin: false, + clauses: [clauses.view9dim2] +}); -const viewProduct = views["view:Product"]; +const unMaterializebleView = new View({ + metrics: [mets[7], mets[9]], + dimensions: [dims[5]], + materialized: false, + origin: false, + childViews: [views[3], views[5], views[7], views[8]] +}); -const viewActiveSeller = views["view:ActiveSeller"]; +const partialJoinView = new View({ + metrics: [mets[7], mets[8]], + dimensions: [], + materialized: false, + origin: false, + childViews: [views[3], views[5], views[6]] +}); -const viewSumCount = ViewHandler.queryReduce(queries["originfalse"],views["view:SellerStatus"]); +const propagatedClauseView = new View({ + metrics: [mets[8]], + dimensions: [dims[4]], + materialized: false, + origin: false, + childViews: [views[6], views[7]], + clauses: [clauses.view7dim5, clauses.view6dim4] +}); -// Exports +const propagatedClauseAggrView = new View({ + metrics: [mets[8], mets[5]], + dimensions: [dims[2]], + materialized: false, + origin: false, + childViews: [views[9], views[6], views[7]], + clauses: [clauses.view7dim5, clauses.view6dim4, clauses.view9dim2] +}); export const engineScenario: EngineScenario = { + metrics: mets, + dimensions: dims, wrongMet: wrongMet, wrongDim: wrongDim, subDimensions: subdims, - queryMetsDims: queries["queryMetsDims"], - queryNoMets: queries["queryNoMets"], - queryNoDims: queries["queryNoDims"], - queryProduct: queries["queryProduct"], - viewProduct: viewProduct, - queryActive: queries["queryActive"], - viewActiveSeller: viewActiveSeller, - querySubDim: queries["querySubDim"], - queryNoParent: queries["queryNoParent"], - config: config + views: views }; export const adapterScenario: AdapterScenario = { - materializedView: views["view:Product"], - sortView: withSortView, - joinWithOneView: joinOneView, - singleClause: singleClause, - multipleClause: multipleClause, - filterAverageBought: clientAverageBought, - reduceAsView: reduceAsView, - filterWithEqual: equalfilter, + materializedView: views[0], + noSelectionView: noSelView, + withSelectionView: withSelView, subDimensionView: subDimView, - joinWithNoMetrics: joinWithNoMetrics, - growOneView: growOneView, - JoinWithAncestors:JoinWithAncestors, - viewSumCount: viewSumCount, - config: config + join4View: join4View, + dateView: dateView, + aggrView: aggrView, + clauseView: clauseView, + multiFilterView: multiFilterView, + multiClauseView: multiClauseView, + notEqualView: notEqualView, + gtltView: gtltView, + geleView: geleView, + notMatchFilterView: notMatchFilterView, + notOriginCount: notOriginCount, + unMaterializebleView: unMaterializebleView, + partialJoinView: partialJoinView, + propagatedClauseView: propagatedClauseView, + propagatedClauseAggrView: propagatedClauseAggrView }; export const dataCtrlScenario: DataCtrlScenario = { - seller: queries["seller"], - wrongMet: queries["wrongMet"], - wrongDim: queries["wrongDim"], - correct: queries["correct"], - clausal: queries["clausal"], - expensive: queries["expensive"], - csv: queries["csv"], + wrongMet: { metrics: [wrongMet], dimensions: [dims[0]] }, + wrongDim: { metrics: [mets[0]], dimensions: [wrongDim] }, + correct: { metrics: [mets[0]], dimensions: [dims[0]] }, + clausal: { metrics: [mets[0]], dimensions: [dims[7]] } }; diff --git a/tslint.json b/tslint.json index 9e9bb16cf4291c32f2951d3a27cefd0042b9399d..27a0066a639f25ed005d32ec7364e3e29bb8cb76 100644 --- a/tslint.json +++ b/tslint.json @@ -1,24 +1,10 @@ { "extends": "tslint:recommended", "rules": { - "no-string-literal" : false, "no-var-requires": false, "object-literal-sort-keys": false, "one-line": false, "trailing-comma": false, - "interface-name": false, - "max-line-length": false, - "member-ordering": false, - "ordered-imports": false, - "prefer-const": false, - "prefer-for-of": false, - "only-arrow-functions": false, - "no-unused-expression": false, - "space-before-function-paren": false, - "object-literal-shorthand":false, - "array-type": false, - "arrow-parens": false, - "callable-types": false, - "no-shadowed-variable": false + "interface-name": false } } diff --git a/typescript b/typescript new file mode 100644 index 0000000000000000000000000000000000000000..2ea15177e7c37241077a36733a7a1629418c2d21 --- /dev/null +++ b/typescript @@ -0,0 +1,146 @@ +Script started on 2021-11-22 12:20:53-02:00 [TERM="xterm-256color" TTY="/dev/pts/1" COLUMNS="235" LINES="62"] +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# l[Kcd scripts/ +]0;root@simmcprod: /home/simmc/blendb/scriptsroot@simmcprod:/home/simmc/blendb/scripts# ls +[0m[01;32mservice.sh[0m +]0;root@simmcprod: /home/simmc/blendb/scriptsroot@simmcprod:/home/simmc/blendb/scripts# cd .. +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# [H[2J]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# ls +[0m[01;34martwork[0m [01;34mdatabase[0m index.js [01;34mnode_modules[0m npm-debug.log package.json [01;34mscripts[0m [01;34mspecs[0m [01;34mtest[0m tslint.json typescript +[01;34mconfig[0m [01;34mdoc[0m LICENSE nodemon.json npm-debug.log.3267702380 README.md [01;34mservice[0m [01;34msrc[0m tsconfig.json [01;34mts-node-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb[0m +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# cd test/ +]0;root@simmcprod: /home/simmc/blendb/testroot@simmcprod:/home/simmc/blendb/test# ls +global.ts mocha.opts [0m[01;34mpostgres[0m scenario.ts +]0;root@simmcprod: /home/simmc/blendb/testroot@simmcprod:/home/simmc/blendb/test# cd .. +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# [H[2J]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# ls +[0m[01;34martwork[0m [01;34mdatabase[0m index.js [01;34mnode_modules[0m npm-debug.log package.json [01;34mscripts[0m [01;34mspecs[0m [01;34mtest[0m tslint.json typescript +[01;34mconfig[0m [01;34mdoc[0m LICENSE nodemon.json npm-debug.log.3267702380 README.md [01;34mservice[0m [01;34msrc[0m tsconfig.json [01;34mts-node-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb[0m +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# cd database/ +]0;root@simmcprod: /home/simmc/blendb/databaseroot@simmcprod:/home/simmc/blendb/database# ls +[0m[01;32mcreateSchema.ts[0m +]0;root@simmcprod: /home/simmc/blendb/databaseroot@simmcprod:/home/simmc/blendb/database# cat createSchema.ts +#!/usr/bin/env node + +/* + * Copyright (C) 2017 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana + * + * This file is part of blendb. + * + * blendb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * blendb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with blendb. If not, see <http://www.gnu.org/licenses/>. + */ + +import { Engine } from "../src/core/engine"; +import { PostgresAdapter } from "../src/adapter/postgres"; +import { ConfigParser } from "../src/util/configParser"; +import * as path from "path"; +import * as fs from "fs"; + +if (process.argv.length !== 4) { + console.log("Wrong arguments number."); + console.log("Arguments: <configFile> <outputFile>"); + process.exitCode = 1; + process.exit(); +} + +const configFile = process.argv[2]; +const schemaFile = process.argv[3]; +const config = ConfigParser.parse(configFile); +const referencePath = path.dirname(configFile); +const engine = new Engine(); +const adapter = new PostgresAdapter(config.connection); + +let schema = ""; + +config.metrics.forEach ((met) => engine.addMetric(met)); +config.dimensions.forEach ((dim) => engine.addDimension(dim)); + +for (let i = 0; i < config.buildViews.length; ++i) { + const view = config.buildViews[i].view; + const filePath = config.buildViews[i].file; + const alias = config.buildViews[i].alias; + if (view.origin) { + // Cria uma tabela + let output = "-- View: " + alias + "\n"; + output += "DROP VIEW IF EXISTS view_" + view.id + " CASCADE;\n"; + output += "CREATE OR REPLACE VIEW view_" + view.id + " AS\n"; + output += fs.readFileSync(referencePath + "/" + filePath, {encoding: "utf-8" }); + schema += output + "\n"; + engine.addView(view); + } + +} + +for (let i = 0; i < config.buildViews.length; ++i) { + const view = config.buildViews[i].view; + const alias = config.buildViews[i].alias; + if (!view.origin) { + const materializedView = engine.query({ + metrics: view.metrics, + dimensions: view.dimensions, + clauses: view.clauses + }); + + const table = adapter.getQueryFromView(materializedView); + const query = "-- View: " + alias + "\n" + + "DROP MATERIALIZED VIEW IF EXISTS view_" + view.id + " CASCADE;\n" + + "CREATE MATERIALIZED VIEW view_" + materializedView.id + + " AS " + table + "\n\n"; + + schema += query; + engine.addView(materializedView); + + } +} +fs.writeFile(schemaFile, schema, (error) => { + if (error) { + console.log("The schema file could not be written. Abort"); + process.exitCode = 1; + return; + } +}); +]0;root@simmcprod: /home/simmc/blendb/databaseroot@simmcprod:/home/simmc/blendb/database# l[Kls +[0m[01;32mcreateSchema.ts[0m +]0;root@simmcprod: /home/simmc/blendb/databaseroot@simmcprod:/home/simmc/blendb/database# [H[2J]0;root@simmcprod: /home/simmc/blendb/databaseroot@simmcprod:/home/simmc/blendb/database# cd .. +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# [H[2J]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# ls +[0m[01;34martwork[0m [01;34mdatabase[0m index.js [01;34mnode_modules[0m npm-debug.log package.json [01;34mscripts[0m [01;34mspecs[0m [01;34mtest[0m tslint.json typescript +[01;34mconfig[0m [01;34mdoc[0m LICENSE nodemon.json npm-debug.log.3267702380 README.md [01;34mservice[0m [01;34msrc[0m tsconfig.json [01;34mts-node-94a6b447580330f9f2b609422537b04239ff3a39df9137e32efd559f1a2935cb[0m +]0;root@simmcprod: /home/simmc/blendbroot@simmcprod:/home/simmc/blendb# cat npm-debug.log +0 info it worked if it ends with ok +1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ] +2 info using npm@2.14.7 +3 info using node@v4.2.2 +4 verbose run-script [ 'prestart', 'start', 'poststart' ] +5 info prestart blendb@0.0.1 +6 info start blendb@0.0.1 +7 verbose unsafe-perm in lifecycle true +8 info blendb@0.0.1 Failed to exec start script +9 verbose stack Error: blendb@0.0.1 start: `node index` +9 verbose stack Exit status 1 +9 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:214:16) +9 verbose stack at emitTwo (events.js:87:13) +9 verbose stack at EventEmitter.emit (events.js:172:7) +9 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14) +9 verbose stack at emitTwo (events.js:87:13) +9 verbose stack at ChildProcess.emit (events.js:172:7) +9 verbose stack at maybeClose (internal/child_process.js:818:16) +9 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5) +10 verbose pkgid blendb@0.0.1 +11 verbose cwd /home/simmc/blendb +12 error Linux 5.10.77-minmvs +13 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "start" +14 error node v4.2.2 +15 error npm v2.14.7 +16 error code ELIFECYCLE +17 error blendb@0.0.1 start: `node index` +17 error Exit status 1 +18 error Failed at the blendb@0 \ No newline at end of file diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index e8b9a11b0cb9a88e34bf7c4bf68525a60792650c..0000000000000000000000000000000000000000 --- a/yarn.lock +++ /dev/null @@ -1,5178 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/generator@^7.4.0", "@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== - dependencies: - "@babel/types" "^7.5.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== - -"@babel/template@^7.1.0", "@babel/template@^7.4.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/traverse@^7.4.3": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@types/async@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/async/-/async-3.0.1.tgz#eb33247ffc23d904f9069a292c260c6324cb652c" - integrity sha512-fBq+1+btw/4CPGCpp3B05vUsslyikLUSUoZmFEjjHrUEPOisIVxUzGJFg1k43iWq9y0lC2UDqWAlg5ynUCwwSA== - -"@types/body-parser@*": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.1.tgz#18fcf61768fb5c30ccc508c21d6fd2e8b3bf7897" - integrity sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/chai@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.0.tgz#2478260021408dec32c123a7cad3414beb811a07" - integrity sha512-zw8UvoBEImn392tLjxoavuonblX/4Yb9ha4KBU10FirCfwgzhKO0dvyJSF9ByxV1xK1r2AgnAi/tvQaLgxQqxA== - -"@types/connect@*": - version "3.4.32" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" - integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg== - dependencies: - "@types/node" "*" - -"@types/cookiejar@*": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.1.tgz#90b68446364baf9efd8e8349bb36bd3852b75b80" - integrity sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw== - -"@types/express-serve-static-core@*": - version "4.16.9" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.9.tgz#69e00643b0819b024bdede95ced3ff239bb54558" - integrity sha512-GqpaVWR0DM8FnRUJYKlWgyARoBUAVfRIeVDZQKOttLFp5SmhhF9YFIYeTPwMd/AXfxlP7xVO2dj1fGu0Q+krKQ== - dependencies: - "@types/node" "*" - "@types/range-parser" "*" - -"@types/express@^4.17.1": - version "4.17.1" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.1.tgz#4cf7849ae3b47125a567dfee18bfca4254b88c5c" - integrity sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "*" - "@types/serve-static" "*" - -"@types/js-yaml@^3.12.1": - version "3.12.1" - resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656" - integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA== - -"@types/mime@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" - integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== - -"@types/minimatch@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/mocha@^5.2.7": - version "5.2.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" - integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== - -"@types/node@*": - version "12.7.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" - integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== - -"@types/node@^10.0.3": - version "10.14.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.16.tgz#4d690c96cbb7b2728afea0e260d680501b3da5cf" - integrity sha512-/opXIbfn0P+VLt+N8DE4l8Mn8rbhiJgabU96ZJ0p9mxOkIks5gh6RUnpHak7Yh0SFkyjO/ODbxsQQPV2bpMmyA== - -"@types/pg-types@*": - version "1.11.4" - resolved "https://registry.yarnpkg.com/@types/pg-types/-/pg-types-1.11.4.tgz#8d7c59fb509ce3dca3f8bae589252051c639a9a8" - integrity sha512-WdIiQmE347LGc1Vq3Ki8sk3iyCuLgnccqVzgxek6gEHp2H0p3MQ3jniIHt+bRODXKju4kNQ+mp53lmP5+/9moQ== - dependencies: - moment ">=2.14.0" - -"@types/pg@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-7.11.0.tgz#11dddc4d54f9b3a8c6dc7e6a6e58a71a033db9ad" - integrity sha512-wXduaNIDQp7w9ediwIRAH+FpdgtOlOwFVlYe9DtBPDczxcHgfb0blLNR7yYVNUMhspC0xOLykOvMDHavbO0Sxg== - dependencies: - "@types/node" "*" - "@types/pg-types" "*" - -"@types/range-parser@*": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" - integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== - -"@types/serve-static@*": - version "1.13.3" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" - integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== - dependencies: - "@types/express-serve-static-core" "*" - "@types/mime" "*" - -"@types/superagent@*": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.3.tgz#52566ddd8957273b477c3e187c930fd791a95b2e" - integrity sha512-vy2licJQwOXrTAe+yz9SCyUVXAkMgCeDq9VHzS5CWJyDU1g6CI4xKb4d5sCEmyucjw5sG0y4k2/afS0iv/1D0Q== - dependencies: - "@types/cookiejar" "*" - "@types/node" "*" - -"@types/supertest@^2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.8.tgz#23801236e2b85204ed771a8e7c40febba7da2bda" - integrity sha512-wcax7/ip4XSSJRLbNzEIUVy2xjcBIZZAuSd2vtltQfRK7kxhx5WMHbLHkYdxN3wuQCrwpYrg86/9byDjPXoGMA== - dependencies: - "@types/superagent" "*" - -a-sync-waterfall@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" - integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -ajv@^4.0.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -amdefine@~0.0.4: - version "0.0.8" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-0.0.8.tgz#34dc8c981e6acb3be1853bef8f0ec94a39d55ba0" - integrity sha1-NNyMmB5qyzvhhTvvjw7JSjnVW6A= - -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - -ansi-regex@^2.0.0, ansi-regex@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== - dependencies: - default-require-extensions "^2.0.0" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -arg@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.1.tgz#485f8e7c390ce4c5f78257dbea80d4be11feda4c" - integrity sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw== - -argh@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/argh/-/argh-0.1.4.tgz#3eb4d612973fc6b6dc6ef338f56f759f2ac5c3a6" - integrity sha1-PrTWEpc/xrbcbvM49W91nyrFw6Y= - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.0.0.tgz#24dd98b38b9194b59b2087ba40c21384d6b8a8dc" - integrity sha1-JN2Ys4uRlLWbIIe6QMIThNa4qNw= - -array-flatten@^2.0.0, array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asap@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async@^2.0.1, async@^2.1.5: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -async@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772" - integrity sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -backbone@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12" - integrity sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ== - dependencies: - underscore ">=1.8.3" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bignumber.js@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" - integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -body-parser@1.19.0, body-parser@^1.10.2, body-parser@^1.13.3: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - 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" - -brace-expansion@^1.0.0, brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - -busboy@^0.2.9: - version "0.2.14" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" - integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM= - dependencies: - dicer "0.2.5" - readable-stream "1.1.x" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -caching-transform@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" - integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== - dependencies: - hasha "^3.0.0" - make-dir "^2.0.0" - package-hash "^3.0.0" - write-file-atomic "^2.4.2" - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - -camel-case@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - -camelcase@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" - -chalk@^1.0.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -change-case@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e" - integrity sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw== - dependencies: - camel-case "^3.0.0" - constant-case "^2.0.0" - dot-case "^2.1.0" - header-case "^1.0.0" - is-lower-case "^1.1.0" - is-upper-case "^1.1.0" - lower-case "^1.1.1" - lower-case-first "^1.0.0" - no-case "^2.3.2" - param-case "^2.1.0" - pascal-case "^2.0.0" - path-case "^2.1.0" - sentence-case "^2.1.0" - snake-case "^2.1.0" - swap-case "^1.1.0" - title-case "^2.1.0" - upper-case "^1.1.1" - upper-case-first "^1.1.0" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -chokidar@^2.0.0: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cli-color@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f" - integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w== - dependencies: - ansi-regex "^2.1.1" - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - memoizee "^0.4.14" - timers-ext "^0.1.5" - -cliui@^3.0.3, cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" - integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - -colornames@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96" - integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y= - -colorspace@1.1.x: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" - integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ== - dependencies: - color "3.0.x" - text-hex "1.0.x" - -combined-stream@^1.0.5, combined-stream@^1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^2.12.1, commander@^2.19.0, commander@^2.7.1, commander@~2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.0, component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -compose-middleware@^2.0.0, compose-middleware@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/compose-middleware/-/compose-middleware-2.2.0.tgz#6e830b1c5c168d3bf1fec62e3a964c2dd361cec3" - integrity sha1-boMLHFwWjTvx/sYuOpZMLdNhzsM= - dependencies: - array-flatten "^2.1.0" - -compressible@~2.0.16: - version "2.0.17" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" - integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== - dependencies: - mime-db ">= 1.40.0 < 2" - -compression@^1.5.2: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -condense-newlines@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f" - integrity sha1-PemFVTE5R10yUCyDsC9gaE0kxV8= - dependencies: - extend-shallow "^2.0.1" - is-whitespace "^0.3.0" - kind-of "^3.0.2" - -config-chain@^1.1.12: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -constant-case@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" - integrity sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY= - dependencies: - snake-case "^2.1.0" - upper-case "^1.1.1" - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -cookie-session@^1.2.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/cookie-session/-/cookie-session-1.3.3.tgz#54fa63881bf87c4961863f7c059670be7517fdae" - integrity sha512-GrMdrU1YTQWtmVTo0Rj3peeZRMc2xJrBslFYtZcYTo+hrSLmrcf69OrRkDi84xTfylgCy2wgpRHyY4le6lE5+A== - dependencies: - cookies "0.7.3" - debug "2.6.9" - on-headers "~1.0.2" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -cookiejar@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== - -cookies@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.3.tgz#7912ce21fbf2e8c2da70cf1c3f351aecf59dadfa" - integrity sha512-+gixgxYSgQLTaTIilDHAdlNPZDENDQernEMiIcZpYYP14zgHsCt4Ce1FEjFtcp6GefhozebB6orvhAAWx/IS0A== - dependencies: - depd "~1.1.2" - keygrip "~1.0.3" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js@^2.5.7: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cors@^2.7.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -cp-file@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" - integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA== - dependencies: - graceful-fs "^4.1.2" - make-dir "^2.0.0" - nested-error-stacks "^2.0.0" - pify "^4.0.1" - safe-buffer "^5.0.1" - -cross-spawn@^4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -d@1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -datatype-expansion@^0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/datatype-expansion/-/datatype-expansion-0.3.8.tgz#671e81262f773898dc77fa87e40188edabc0faf2" - integrity sha512-Z9n5YQqr3hOSPgm9nqQflCk+yW4LU0Ei9lB4AAguHU9HBL+of5uz0FmIScreZGHSLDP/H1gTIsKq8PFHHffstw== - dependencies: - lodash "^4.17.4" - -date-and-time@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.7.0.tgz#26273355558877799f9c95888293fccee92fdb94" - integrity sha512-qPHBPG0AQqbjP7wVf7vLv25/0bZRjYPiJiJtE0t6RqTswJR/6ExCXQLDnL5w4986j7i6470TMtalJxC8/UHrww== - -date-format@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf" - integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA== - -debug@2.6.9, debug@2.x.x, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= - dependencies: - ms "0.7.1" - -decamelize@^1.1.1, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deeks@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/deeks/-/deeks-2.2.1.tgz#4de360652998fd0a681153a9ffde5dcc6c983f4a" - integrity sha512-D2Qu3Fv5zBtBzXjXIUgWPRYn30d/IG6SCPOKIz42+LVTwhPeRI5+DAxdzap0vI2zYheiErIpVLwaUQBoA/iENw== - dependencies: - underscore "1.9.1" - -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= - dependencies: - strip-bom "^3.0.0" - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -diagnostics@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a" - integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ== - dependencies: - colorspace "1.1.x" - enabled "1.0.x" - kuler "1.0.x" - -dicer@0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" - integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8= - dependencies: - readable-stream "1.1.x" - streamsearch "0.1.2" - -diff@3.5.0, diff@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -diff@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" - integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== - -doc-path@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/doc-path/-/doc-path-2.0.1.tgz#d2adb8bcd31c895b17b92f61eff39aaec04430d2" - integrity sha512-/CCG157H//3l513omROUzaREChY/OYpxqYXvQcv7gsrwGfjVOh5d/1gJigHJ6iTnO77pA8rMLZ63CgEPEM6+9Q== - -dom-serializer@0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" - integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee" - integrity sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4= - dependencies: - no-case "^2.2.0" - -duplexify@^3.2.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -editorconfig@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" - integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== - dependencies: - commander "^2.19.0" - lru-cache "^4.1.5" - semver "^5.6.0" - sigmund "^1.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -emits@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emits/-/emits-3.0.0.tgz#32752bba95e1707b219562384ab9bb8b1fd62f70" - integrity sha1-MnUrupXhcHshlWI4Srm7ix/WL3A= - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -enabled@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" - integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M= - dependencies: - env-variable "0.0.x" - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -entities@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - -env-variable@0.0.x: - version "0.0.5" - resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88" - integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA== - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.5.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: - version "0.10.50" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.50.tgz#6d0e23a0abdb27018e5ac4fd09b412bc5517a778" - integrity sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "^1.0.0" - -es6-error@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" - integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== - -es6-iterator@^2.0.3, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-promise@^4.1.1: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -escape-html@1.0.3, escape-html@^1.0.2, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= - dependencies: - d "1" - es5-ext "~0.10.14" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - 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" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.1.tgz#85a17c6c59a94717d262d61230d4b0ebe3d4a14d" - integrity sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0= - dependencies: - debug "~2.2.0" - escape-html "~1.0.3" - on-finished "~2.3.0" - unpipe "~1.0.0" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - 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" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -findup-sync@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.2.1.tgz#e0a90a450075c49466ee513732057514b81e878c" - integrity sha1-4KkKRQB1xJRm7lE3MgV1FLgeh4w= - dependencies: - glob "~4.3.0" - -flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== - dependencies: - is-buffer "~2.0.3" - -flatted@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= - dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" - -form-data@^1.0.0-rc3: - version "1.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" - integrity sha1-rjFduaSQf6BlUCMEpm13M0de43w= - dependencies: - async "^2.0.1" - combined-stream "^1.0.5" - mime-types "^2.1.11" - -form-data@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.0.tgz#094ec359dc4b55e7d62e0db4acd76e89fe874d37" - integrity sha512-WXieX3G/8side6VIqx44ablyULoGruSde5PNTxoUyo5CeyAMX6nVWUd0rgist/EuX655cjhUhTo1Fo3tRYqbcA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -format-util@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.3.tgz#032dca4a116262a12c43f4c3ec8566416c5b2d95" - integrity sha1-Ay3KShFiYqEsQ/TD7IVmQWxbLZU= - -formidable@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659" - integrity sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg== - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@8.1.0, fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== - dependencies: - minipass "^2.2.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.1.1, glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@~4.3.0: - version "4.3.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.3.5.tgz#80fbb08ca540f238acce5d11d1e9bc41e75173d3" - integrity sha1-gPuwjKVA8jiszl0R0em8QedRc9M= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -got@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/got/-/got-2.4.0.tgz#e4087a2cd59b5d20f2d169dc85d2169ed9e89f56" - integrity sha1-5Ah6LNWbXSDy0WnchdIWntnon1Y= - dependencies: - duplexify "^3.2.0" - infinity-agent "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - object-assign "^2.0.0" - prepend-http "^1.0.0" - read-all-stream "^1.0.0" - statuses "^1.2.1" - timed-out "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -handlebars@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" - integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hasha@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" - integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk= - dependencies: - is-stream "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -header-case@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" - integrity sha1-lTWXMZfBRLCWE81l0xfvGZY70C0= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.3" - -highlight.js@^9.15.8: - version "9.15.10" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" - integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== - -hosted-git-info@^2.1.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" - integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== - -htmlparser2@^3.9.2: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@^1.2.8, http-errors@^1.3.1, http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-response-object@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" - integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== - dependencies: - "@types/node" "^10.0.3" - -iconv-lite@0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -infinity-agent@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-1.0.2.tgz#2e9da2c070b9864a8bc66c0194e1791ed8058025" - integrity sha1-Lp2iwHC5hkqLxmwBlOF5HtgFgCU= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -interpret@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== - -invariant@2.2.4, invariant@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== - -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-buffer@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== - -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-lower-case@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" - integrity sha1-fhR75HaNxGbbO/shzGCzHmrWk5M= - dependencies: - lower-case "^1.1.0" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-promise@^2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -is-upper-case@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" - integrity sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8= - dependencies: - upper-case "^1.1.0" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-whitespace@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" - integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38= - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== - -istanbul-lib-hook@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" - integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== - dependencies: - append-transform "^1.0.0" - -istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - -istanbul-lib-report@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" - integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== - dependencies: - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - supports-color "^6.1.0" - -istanbul-lib-source-maps@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" - integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - rimraf "^2.6.3" - source-map "^0.6.1" - -istanbul-reports@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" - integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== - dependencies: - handlebars "^4.1.2" - -jju@~1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.2.1.tgz#edf6ec20d5d668c80c2c00cea63f8a9422a4b528" - integrity sha1-7fbsINXWaMgMLADOpj+KlCKktSg= - -jquery@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" - integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== - -js-beautify@^1.6.12: - version "1.10.2" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" - integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ== - dependencies: - config-chain "^1.1.12" - editorconfig "^0.15.3" - glob "^7.1.3" - mkdirp "~0.5.1" - nopt "~4.0.1" - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@3.13.1, js-yaml@^3.13.1, js-yaml@^3.9.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-2-csv@^3.5.6: - version "3.5.6" - resolved "https://registry.yarnpkg.com/json-2-csv/-/json-2-csv-3.5.6.tgz#ec1f50f490301c10f2bacad3ad756aef904327e6" - integrity sha512-83aq/tlPGKX9qVT53bYYi7IrFoFhsW/CXI4JHeXXDO9YQ8xHCuHH5YSfT0e4ThkbKr34Yq5zDa1VJqkQGCY1pw== - dependencies: - deeks "2.2.1" - doc-path "2.0.1" - underscore "1.9.1" - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-path@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/json-path/-/json-path-0.1.3.tgz#dce61357b3b281b28ac647ec0a709bc58a155bf8" - integrity sha1-3OYTV7OygbKKxkfsCnCbxYoVW/g= - dependencies: - json-ptr "~0.1.1" - -json-ptr@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/json-ptr/-/json-ptr-0.1.1.tgz#bab82a31e292ce7af9e3fc7fd65acd1bbb9248e8" - integrity sha1-urgqMeKSznr54/x/1lrNG7uSSOg= - -json-schema-compatibility@1.1.0, json-schema-compatibility@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/json-schema-compatibility/-/json-schema-compatibility-1.1.0.tgz#1a8981778cda0c38187298d999d089e51af282df" - integrity sha1-GomBd4zaDDgYcpjZmdCJ5Rrygt8= - -json-schema-ref-parser@^3.1.2: - version "3.3.1" - resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-3.3.1.tgz#86e751b8099357bf601a7cfe42d10123ee906a32" - integrity sha512-stQTMhec2R/p2L9dH4XXRlpNCP0mY8QrLd/9Kl+8SHJQmwHtE1nDfXH4wbsSM+GkJMl8t92yZbI0OIol432CIQ== - dependencies: - call-me-maybe "^1.0.1" - debug "^3.0.0" - es6-promise "^4.1.1" - js-yaml "^3.9.1" - ono "^4.0.2" - z-schema "^3.18.2" - -json-stable-stringify@1.0.1, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-to-ast@2.0.0-alpha1.3: - version "2.0.0-alpha1.3" - resolved "https://registry.yarnpkg.com/json-to-ast/-/json-to-ast-2.0.0-alpha1.3.tgz#690aa78035d3a7b72d5193f1b4c08f9bb0d7e2c8" - integrity sha1-aQqngDXTp7ctUZPxtMCPm7DX4sg= - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -keygrip@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc" - integrity sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -know-your-http-well@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/know-your-http-well/-/know-your-http-well-0.5.0.tgz#5d039003104799a9d77fc2998cfd539675b256be" - integrity sha1-XQOQAxBHmanXf8KZjP1TlnWyVr4= - dependencies: - amdefine "~0.0.4" - -kuler@1.0.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6" - integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ== - dependencies: - colornames "^1.1.1" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== - dependencies: - invert-kv "^2.0.0" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= - -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - -lodash.get@^4.0.0, lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.isequal@^4.0.0, lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash@^3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= - -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= - dependencies: - chalk "^1.0.0" - -log4js@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-5.1.0.tgz#3fa5372055a4c2611ab92d80496bffc100841508" - integrity sha512-QtXrBGZiIwfwBrH9zF2uQarvBuJ5+Icqx9fW+nQL4pnmPITJw8n6kh3bck5IkcTDBQatDeKqUMXXX41fp0TIqw== - dependencies: - date-format "^2.1.0" - debug "^4.1.1" - flatted "^2.0.1" - rfdc "^1.1.4" - streamroller "^2.1.0" - -loophole@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loophole/-/loophole-1.1.0.tgz#37949fea453b6256acc725c320ce0c5a7f70a2bd" - integrity sha1-N5Sf6kU7YlasxyXDIM4MWn9wor0= - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case-first@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" - integrity sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E= - dependencies: - lower-case "^1.1.2" - -lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lru-cache@^4.0.1, lru-cache@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-queue@0.1: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= - dependencies: - es5-ext "~0.10.2" - -lrucache@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/lrucache/-/lrucache-1.0.3.tgz#3b1ded0d1ba82e188b9bdaba9eee6486f864a434" - integrity sha1-Ox3tDRuoLhiLm9q6nu5khvhkpDQ= - -lunr@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.6.tgz#f278beee7ffd56ad86e6e478ce02ab2b98c78dd5" - integrity sha512-swStvEyDqQ85MGpABCMBclZcLI/pBIlu8FFDtmX197+oEgKloJ67QnB+Tidh0340HmLMs39c4GrkPY3cmkXp6Q== - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-error@^1.1.1: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" - integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== - -map-age-cleaner@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -marked@^0.6.1: - version "0.6.3" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.3.tgz#79babad78af638ba4d522a9e715cdfdd2429e946" - integrity sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ== - -marked@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" - integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -media-typer@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" - integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - -mem@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" - integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== - dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^2.0.0" - p-is-promise "^2.0.0" - -memoizee@^0.4.14: - version "0.4.14" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" - integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== - dependencies: - d "1" - es5-ext "^0.10.45" - es6-weak-map "^2.0.2" - event-emitter "^0.3.5" - is-promise "^2.1" - lru-queue "0.1" - next-tick "1" - timers-ext "^0.1.5" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - -methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -mime-db@1.40.0, "mime-db@>= 1.40.0 < 2": - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== - -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.24: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== - dependencies: - mime-db "1.40.0" - -mime@1.6.0, mime@^1.4.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - integrity sha1-jQh8OcazjAAbl/ynzm0OHoCvusc= - dependencies: - brace-expansion "^1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minimize@2.1.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/minimize/-/minimize-2.1.0.tgz#fa277647fc5f9a21524bfde62814ca7ce1ffd7a2" - integrity sha1-+id2R/xfmiFSS/3mKBTKfOH/16I= - dependencies: - argh "^0.1.4" - async "^2.1.5" - cli-color "^1.2.0" - diagnostics "^1.1.0" - emits "^3.0.0" - htmlparser2 "^3.9.2" - uuid "^3.0.0" - -minipass@^2.2.1, minipass@^2.3.5: - version "2.4.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.4.0.tgz#38f0af94f42fb6f34d3d7d82a90e2c99cd3ff485" - integrity sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.0.tgz#f896b642843445d1bb8bca60eabd9206b8916e56" - integrity sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "2.2.0" - minimatch "3.0.4" - mkdirp "0.5.1" - ms "2.1.1" - node-environment-flags "1.0.5" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.2.2" - yargs-parser "13.0.0" - yargs-unparser "1.5.0" - -moment@>=2.14.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== - -monetdb@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/monetdb/-/monetdb-1.1.4.tgz#f1cc27e73cbd55f04de1f23e93ac2ab0c4b0aa41" - integrity sha1-8cwn5zy9VfBN4fI+k6wqsMSwqkE= - dependencies: - q "^1.4.1" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -mustache@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.3.tgz#ee4fb971887fa6cc1b6b6d219a74b5e3c7535f32" - integrity sha512-vM5FkMHamTYmVYeAujypihuPrJQDtaUIlKeeVb1AMJ73OZLtWiF7GprqrjxD0gJWT53W9JfqXxf97nXQjMQkqA== - -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.2, negotiator@^0.6.0, negotiator@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -nested-error-stacks@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" - integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== - -next-tick@1, next-tick@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^2.2.0, no-case@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - -node-environment-flags@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -nopt@^4.0.1, nopt@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -nunjucks-markdown@2.0.x: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nunjucks-markdown/-/nunjucks-markdown-2.0.1.tgz#d55e75433a35850e2c345651fe3f931ed9b156a2" - integrity sha1-1V51Qzo1hQ4sNFZR/j+THtmxVqI= - -nunjucks@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.0.tgz#53e95f43c9555e822e8950008a201b1002d49933" - integrity sha512-YS/qEQ6N7qCnUdm6EoYRBfJUdWNT0PpKbbRnogV2XyXbBm2STIP1O6yrdZHgwMVK7fIYUx7i8+yatEixnXSB1w== - dependencies: - a-sync-waterfall "^1.0.0" - asap "^2.0.3" - yargs "^3.32.0" - optionalDependencies: - chokidar "^2.0.0" - -nyc@^14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb" - integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw== - dependencies: - archy "^1.0.0" - caching-transform "^3.0.2" - convert-source-map "^1.6.0" - cp-file "^6.2.0" - find-cache-dir "^2.1.0" - find-up "^3.0.0" - foreground-child "^1.5.6" - glob "^7.1.3" - istanbul-lib-coverage "^2.0.5" - istanbul-lib-hook "^2.0.7" - istanbul-lib-instrument "^3.3.0" - istanbul-lib-report "^2.0.8" - istanbul-lib-source-maps "^3.0.6" - istanbul-reports "^2.2.4" - js-yaml "^3.13.1" - make-dir "^2.1.0" - merge-source-map "^1.1.0" - resolve-from "^4.0.0" - rimraf "^2.6.3" - signal-exit "^3.0.2" - spawn-wrap "^1.4.2" - test-exclude "^5.2.3" - uuid "^3.3.2" - yargs "^13.2.2" - yargs-parser "^13.0.0" - -oauth2orize@^1.0.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/oauth2orize/-/oauth2orize-1.11.0.tgz#793cef251d45ebdeac32ae40a8b6814faab1d483" - integrity sha1-eTzvJR1F696sMq5AqLaBT6qx1IM= - dependencies: - debug "2.x.x" - uid2 "0.0.x" - utils-merge "1.x.x" - -object-assign@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" - integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo= - -object-assign@^4, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-keys@^1.0.11, object-keys@^1.0.12: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/object-values/-/object-values-1.0.0.tgz#72af839630119e5b98c3b02bb8c27e3237158105" - integrity sha1-cq+DljARnluYw7AruMJ+MjcVgQU= - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -ono@^4.0.2: - version "4.0.11" - resolved "https://registry.yarnpkg.com/ono/-/ono-4.0.11.tgz#c7f4209b3e396e8a44ef43b9cedc7f5d791d221d" - integrity sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g== - dependencies: - format-util "^1.0.3" - -optimist@^0.6.1, optimist@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-locale@^3.0.0, os-locale@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -osprey-method-handler@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/osprey-method-handler/-/osprey-method-handler-0.10.3.tgz#f4a11b83e19cd8c8921e6a3d3a9ad1147445c808" - integrity sha1-9KEbg+Gc2MiSHmo9OprRFHRFyAg= - dependencies: - ajv "^4.0.0" - body-parser "^1.10.2" - busboy "^0.2.9" - compose-middleware "^2.0.0" - debug "^2.2.0" - http-errors "^1.2.8" - is-stream "^1.0.1" - json-schema-compatibility "^1.0.1" - lowercase-keys "^1.0.0" - negotiator "^0.6.0" - object-values "^1.0.0" - parseurl "^1.3.0" - raml-sanitize "^1.1.2" - raml-validate "^1.0.6" - standard-headers "^0.1.0" - stream-equal "^0.1.5" - type-is "^1.5.5" - xtend "^4.0.0" - -osprey-resources@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/osprey-resources/-/osprey-resources-0.7.1.tgz#a51c3d5d3f7c21d443ec565b44566823f3d05cd0" - integrity sha1-pRw9XT98IdRD7FZbRFZoI/PQXNA= - dependencies: - osprey-router "^0.5.1" - xtend "^4.0.1" - -osprey-router@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/osprey-router/-/osprey-router-0.4.0.tgz#132c4dc1595f1d282b202064d43fb4f1818390bb" - integrity sha1-EyxNwVlfHSgrICBk1D+08YGDkLs= - dependencies: - array-flatten "^2.0.0" - methods "^1.1.1" - raml-path-match "^2.0.0" - router blakeembrey/router#router-engine - xtend "^4.0.1" - -osprey-router@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/osprey-router/-/osprey-router-0.5.1.tgz#a8d1bc81762049e911011e41bbaf774928c33045" - integrity sha1-qNG8gXYgSekRAR5Bu693SSjDMEU= - dependencies: - array-flatten "^2.0.0" - methods "^1.1.1" - raml-path-match "^2.1.2" - router blakeembrey/router#router-engine - xtend "^4.0.1" - -osprey@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/osprey/-/osprey-0.3.2.tgz#bbde78f2a213e4b8a11f71fddffa8f351cb8973c" - integrity sha1-u9548qIT5LihH3H93/qPNRy4lzw= - dependencies: - arrify "^1.0.0" - body-parser "^1.13.3" - compose-middleware "^2.0.1" - compression "^1.5.2" - cookie-session "^1.2.0" - cors "^2.7.1" - debug "^2.2.0" - finalhandler "^0.4.0" - form-data "^1.0.0-rc3" - http-errors "^1.3.1" - invariant "^2.1.0" - oauth2orize "^1.0.1" - osprey-method-handler "^0.10.0" - osprey-resources "^0.7.0" - osprey-router "^0.4.0" - parseurl "^1.3.0" - passport "^0.3.0" - passport-http "^0.3.0" - passport-http-bearer "^1.0.1" - passport-oauth2-client-password "^0.1.2" - raml-parser "^0.8.10" - request-error-handler "^1.0.0" - type-is "^1.5.5" - xtend "^4.0.0" - yargs "^4.1.0" - -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-is-promise@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" - integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" - integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== - dependencies: - graceful-fs "^4.1.15" - hasha "^3.0.0" - lodash.flattendeep "^4.4.0" - release-zalgo "^1.0.0" - -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - -param-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parseurl@^1.3.0, parseurl@~1.3.1, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" - integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4= - dependencies: - camel-case "^3.0.0" - upper-case-first "^1.1.0" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -passport-http-bearer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz#147469ea3669e2a84c6167ef99dbb77e1f0098a8" - integrity sha1-FHRp6jZp4qhMYWfvmdu3fh8AmKg= - dependencies: - passport-strategy "1.x.x" - -passport-http@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/passport-http/-/passport-http-0.3.0.tgz#8ee53d4380be9c60df2151925029826f77115603" - integrity sha1-juU9Q4C+nGDfIVGSUCmCb3cRVgM= - dependencies: - passport-strategy "1.x.x" - -passport-oauth2-client-password@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/passport-oauth2-client-password/-/passport-oauth2-client-password-0.1.2.tgz#4f378b678b92d16dbbd233a6c706520093e561ba" - integrity sha1-TzeLZ4uS0W270jOmxwZSAJPlYbo= - dependencies: - passport-strategy "1.x.x" - -passport-strategy@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" - integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= - -passport@^0.3.0: - version "0.3.2" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" - integrity sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI= - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -path-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" - integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU= - dependencies: - no-case "^2.2.0" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - -pause@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" - integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-pool@^2.0.4: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg@^7.12.1: - version "7.12.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" - integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "0.1.3" - pg-pool "^2.0.4" - pg-types "^2.1.0" - pgpass "1.x" - semver "4.3.2" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= - dependencies: - split "^1.0.0" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pluralize@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" - integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== - -pluralize@~1.1.1: - version "1.1.6" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.1.6.tgz#e4bf5d6b36b2afc22c801f7c37293617e0bdc56d" - integrity sha1-5L9dazayr8IsgB98Nyk2F+C9xW0= - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= - -postgres-date@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -pretty@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5" - integrity sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU= - dependencies: - condense-newlines "^0.2.1" - extend-shallow "^2.0.1" - js-beautify "^1.6.12" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-polyfill@8.1.3: - version "8.1.3" - resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" - integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -q@0.9.7: - version "0.9.7" - resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" - integrity sha1-TeLmyzspCIyeTLwDv51C+5bOL3U= - -q@1.5.1, q@^1.4.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.8.0.tgz#87b763f0d37ca54200334cd57bb2ef8f68a1d081" - integrity sha512-tPSkj8y92PfZVbinY1n84i1Qdx75lZjMQYx9WZhnkofyxzw2r7Ho39G3/aEvSUdebxpnnM4LZJCtvE/Aq3+s9w== - -raml-1-parser@1.1.x: - version "1.1.56" - resolved "https://registry.yarnpkg.com/raml-1-parser/-/raml-1-parser-1.1.56.tgz#e13aa32b8bb3d8a4b9743a3f3e7fe5ffc7a4e059" - integrity sha512-t3KsHjtUKusuDXxTd6OVrJNZDFUxo54xTUrMlQoaHmkVPtyUxftw50aO5Z0sTASvTb7ry/vAXNW6KU9HAa1ctg== - dependencies: - change-case "3.1.0" - fs-extra "8.1.0" - http-response-object "3.0.2" - invariant "2.2.4" - json-path "0.1.3" - json-schema-compatibility "1.1.0" - json-stable-stringify "1.0.1" - loophole "1.1.0" - lrucache "1.0.3" - media-typer "1.1.0" - mkdirp "0.5.1" - pluralize "8.0.0" - promise-polyfill "8.1.3" - q "1.5.1" - raml-definition-system "0.0.90" - ts-model "0.0.18" - underscore "1.9.1" - urlsafe-base64 "^1.0.0" - xhr2 "0.2.0" - xmldom "0.1.27" - xmlhttprequest "1.8.0" - yaml-ast-parser "0.0.43" - z-schema "4.1.0" - -raml-definition-system@0.0.90: - version "0.0.90" - resolved "https://registry.yarnpkg.com/raml-definition-system/-/raml-definition-system-0.0.90.tgz#68294efbe01310cd895bd177a049277b30da6a11" - integrity sha512-5k2mrN4Z4qvljmTDcghpvYp7aB5aYGYaPyU84xFF6WMPPbCL1w36bSHJNKudItwYmxST7XoBG4VPfnQjbDnIVA== - dependencies: - know-your-http-well "0.5.0" - raml-typesystem "0.0.93" - ts-structure-model "0.0.1" - underscore "1.9.1" - -raml-json-validation@0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/raml-json-validation/-/raml-json-validation-0.0.18.tgz#a6cbc1828f61b16bae4b94a5f264bf17960fecb9" - integrity sha512-U43jM2+2203s59jMWlNQIc1SmQ4B8rJKJXL5bQJdFHVyr2W9ImLJOmDCSpkKHKlM24f72iRbU/aVupjpWY8fBA== - dependencies: - z-schema "3.21.0" - -raml-parser@^0.8.10, raml-parser@^0.8.18: - version "0.8.18" - resolved "https://registry.yarnpkg.com/raml-parser/-/raml-parser-0.8.18.tgz#0873375034f8b8a1d20c10e3147b6279b33497a8" - integrity sha1-CHM3UDT4uKHSDBDjFHtiebM0l6g= - dependencies: - got "~2.4.0" - jju "~1.2.0" - json-schema-ref-parser "^3.1.2" - object-assign "^4.1.0" - pluralize "~1.1.1" - q "0.9.7" - uritemplate "~0.3.4" - -raml-path-match@^2.0.0, raml-path-match@^2.1.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/raml-path-match/-/raml-path-match-2.2.2.tgz#efac2d3281f73b38c340fb281dd743c8e8f2fec8" - integrity sha512-1SYmFXB/21FNFHl/UUdmpUhO74afIhWlLxvAP0vC3OAOZaD4b8ewai1oky90UBytMs3OhMxFmPSyVpHv4Yqy+Q== - dependencies: - raml-sanitize "^1.3.4" - raml-validate "^1.2.3" - xtend "^4.0.1" - -raml-sanitize@^1.1.2, raml-sanitize@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/raml-sanitize/-/raml-sanitize-1.3.4.tgz#209d888fb4e655395491ec68df2d0187d21214ac" - integrity sha512-IacU0ElCxABf7j01h8P+9LMW1xaMahFumpWM6GTbKzndKSgHFWTQpZFA+EuPu2OxUTCGwjo2JLSw2tZmRgbEMA== - -raml-typesystem@0.0.93: - version "0.0.93" - resolved "https://registry.yarnpkg.com/raml-typesystem/-/raml-typesystem-0.0.93.tgz#9bb01da634234f3f37fbe864c3f83f65f38465e1" - integrity sha512-KTl+7CTzBK7ie2rxSu/5uTp+JCPQrgikLw1lnSOTPizOeW0s1i5c+R5lf78ucjgUztRQidhSJK1wwnVH1aBbVA== - dependencies: - bignumber.js "9.0.0" - date-and-time "0.7.0" - escape-html "1.0.3" - json-schema-compatibility "1.1.0" - json-to-ast "2.0.0-alpha1.3" - lrucache "1.0.3" - underscore "1.9.1" - xml2js "0.4.19" - xmldom "0.1.27" - optionalDependencies: - raml-json-validation "0.0.18" - raml-xml-validation "0.0.15" - -raml-typesystem@^0.0.92: - version "0.0.92" - resolved "https://registry.yarnpkg.com/raml-typesystem/-/raml-typesystem-0.0.92.tgz#7fbfc1e84b82fb75a5afafbffd126d7cefab530b" - integrity sha512-v+fKYYcLLxJ3XqV7ANoG7clqKAUw/BmKVa+P/g07dfMq0qcJ3r/uFb5khw1jol7NXCRyb8hKyRfXN0l1oy/rQw== - dependencies: - bignumber.js "9.0.0" - date-and-time "0.7.0" - escape-html "1.0.3" - json-schema-compatibility "1.1.0" - json-to-ast "2.0.0-alpha1.3" - lrucache "1.0.3" - underscore "1.9.1" - xml2js "0.4.19" - xmldom "0.1.27" - optionalDependencies: - raml-json-validation "0.0.18" - raml-xml-validation "0.0.15" - -raml-validate@^1.0.6, raml-validate@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/raml-validate/-/raml-validate-1.2.4.tgz#137e522095df3bc0c86de1c46f4d96e35cbce177" - integrity sha512-KXwFRqgKl8pvxib8TWFWQ2sGEguNiPoTB7VOQWzQO36/2YhMi/WK5xBpn+P3liruJHNcKdD3VDnqUkY2/WWNmQ== - dependencies: - raml-typesystem "^0.0.92" - -raml-xml-validation@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/raml-xml-validation/-/raml-xml-validation-0.0.15.tgz#3172ac2d7c05a3151533f5864f8068e67184ad3d" - integrity sha512-ixkKvCc2b/R7WkPxhFDT7Bg7HLRyzXGp/2UrGFJfkxvsAEMC5JZ2b7LEpmrx6JGzLaHFA01KJ/IBNoZdxvM2xw== - dependencies: - xmllint-jsparser "0.0.3" - -raml2html-default-theme@^2.9.3: - version "2.9.3" - resolved "https://registry.yarnpkg.com/raml2html-default-theme/-/raml2html-default-theme-2.9.3.tgz#a4806714c4c2c0bd2ccd2be6ebfd868474b2ee46" - integrity sha512-NQq5qa1M9SfDhKGoWOmTdGU5WwKZnEuHSH7O/tMPiMgU9+DkLEM7IIrs0/ETwyqlnkv4PJE1R75fOq84T4tbDg== - -raml2html@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/raml2html/-/raml2html-7.4.0.tgz#2e390c7617f601349207a3857cab3fe17b7763df" - integrity sha512-7QaFXsGPH7MLQ+VxEO8nNDI/7b5R4lEl7SNBRm1vVlN3KdrcOZSk090wtruF0hdn8WDP3+Mkc51tq8i9ha0S1w== - dependencies: - chalk "^2.4.2" - marked "^0.6.1" - minimize "2.1.x" - nunjucks "^3.2.0" - nunjucks-markdown "2.0.x" - pretty "^2.0.0" - raml2html-default-theme "^2.9.3" - raml2obj "^6.3.0" - yargs "10.x" - -raml2obj@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/raml2obj/-/raml2obj-6.5.0.tgz#eb96031ae6e36cafe127a375a6545d207f6a7e30" - integrity sha512-1r7dSlEb3OchwszGFars9wEwtMsDT+3MD0uChG7+Kd3FL97kJXPCXj8hRvRol47UEAqWtw5fSQeG7OromdkOfA== - dependencies: - datatype-expansion "^0.3.6" - raml-1-parser "1.1.x" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read-all-stream@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-1.0.2.tgz#d378cf4ef6e236b188ea42d135e5b180a89e3e92" - integrity sha1-03jPTvbiNrGI6kLRNeWxgKiePpI= - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" - integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== - dependencies: - find-up "^3.0.0" - read-pkg "^3.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -readable-stream@1.1.x: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -release-zalgo@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" - integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= - dependencies: - es6-error "^4.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -request-error-handler@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/request-error-handler/-/request-error-handler-1.2.1.tgz#d3a86f294357a6d0f4ad78b6af1cfee2d3bf536b" - integrity sha512-mg//tyL9S5J0znQmVW427nbyDqvNR4zh7tMs9PHCWNTYDMr16Eh+Exw9rY7ez3fxQxUwQMBO8FP6mth8/Sfd+w== - dependencies: - debug "^4.1.1" - escape-html "^1.0.2" - invariant "^2.1.0" - mustache "^3.0.1" - negotiator "^0.6.2" - xtend "^4.0.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rfdc@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" - integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== - -rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -router@blakeembrey/router#router-engine: - version "1.1.4" - resolved "https://codeload.github.com/blakeembrey/router/tar.gz/5eb68560e91b302251ff17a70cd1b6af1fc36d30" - dependencies: - array-flatten "2.0.0" - debug "^3.1.0" - methods "~1.1.2" - parseurl "~1.3.1" - path-to-regexp "0.1.7" - setprototypeof "1.0.0" - utils-merge "1.0.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@>=0.6.0, sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= - -semver@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - 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" - -sentence-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4" - integrity sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ= - dependencies: - no-case "^2.2.0" - upper-case-first "^1.1.2" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setprototypeof@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.0.tgz#d5fafca01e1174d0079bd1bf881f09c8a339794c" - integrity sha1-1fr8oB4RdNAHm9G/iB8JyKM5eUw= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shelljs@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" - integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -snake-case@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" - integrity sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8= - dependencies: - no-case "^2.2.0" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.5.6: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.0, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spawn-wrap@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848" - integrity sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw== - dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" - signal-exit "^3.0.2" - which "^1.3.0" - -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -standard-headers@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/standard-headers/-/standard-headers-0.1.1.tgz#f7f2bac4a16ae12fc39ff6a84e4c23ba4abe4fb9" - integrity sha1-9/K6xKFq4S/Dn/aoTkwjukq+T7k= - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.5.0 < 2", statuses@^1.2.1, statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stream-equal@^0.1.5: - version "0.1.13" - resolved "https://registry.yarnpkg.com/stream-equal/-/stream-equal-0.1.13.tgz#17c2d7cf8de5570d0ffb99e3a5142a58c76bc4ae" - integrity sha1-F8LXz43lVw0P+5njpRQqWMdrxK4= - optionalDependencies: - "@types/node" "*" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamroller@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-2.1.0.tgz#702de4dbba428c82ed3ffc87a75a21a61027e461" - integrity sha512-Ps7CuQL0RRG0YAigxNehrGfHrLu+jKSSnhiZBwF8uWi62WmtHDQV1OG5gVgV5SAzitcz1GrM3QVgnRO0mXV2hg== - dependencies: - date-format "^2.1.0" - debug "^4.1.1" - fs-extra "^8.1.0" - -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-json-comments@2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -superagent@^3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" - integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== - dependencies: - component-emitter "^1.2.0" - cookiejar "^2.1.0" - debug "^3.1.0" - extend "^3.0.0" - form-data "^2.3.1" - formidable "^1.2.0" - methods "^1.1.1" - mime "^1.4.1" - qs "^6.5.1" - readable-stream "^2.3.5" - -supertest@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-4.0.2.tgz#c2234dbdd6dc79b6f15b99c8d6577b90e4ce3f36" - integrity sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ== - dependencies: - methods "^1.1.2" - superagent "^3.8.3" - -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -swap-case@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" - integrity sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM= - dependencies: - lower-case "^1.1.1" - upper-case "^1.1.1" - -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -test-exclude@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" - integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - read-pkg-up "^4.0.0" - require-main-filename "^2.0.0" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through@2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -timed-out@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" - integrity sha1-84sK6B03R9YoAB9B2vxlKs5nHAo= - -timers-ext@^0.1.5: - version "0.1.7" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" - integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== - dependencies: - es5-ext "~0.10.46" - next-tick "1" - -title-case@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" - integrity sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o= - dependencies: - no-case "^2.2.0" - upper-case "^1.0.3" - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -ts-model@0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ts-model/-/ts-model-0.0.18.tgz#ea1ca84c2f22340b59b12bb5f8fa4b857af3e55b" - integrity sha512-wIBuWYxYES3m0JNT8nnPTo3GgH+Xa2NGig2GWGGTryMVPiME/Tg5DQrcydBfLjf/cWcPMn9uxgANiQWaGTyFDg== - dependencies: - underscore "1.9.1" - -ts-node@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57" - integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ== - dependencies: - arg "^4.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.6" - yn "^3.0.0" - -ts-structure-model@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/ts-structure-model/-/ts-structure-model-0.0.1.tgz#6e6c9ad489b8c9065c83f8e9d215dd09a20188ee" - integrity sha512-7hqYQx4kPWUkJXTVsZe++1IMd63jZAjW6O00+kHJf9/DcNaxCJxNjsQhLVcC57HZhK4SUPSxMZd+AnGrLA6Itw== - -tslib@^1.8.0, tslib@^1.8.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -tslint-stylish@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslint-stylish/-/tslint-stylish-2.1.0.tgz#8cda3c38c9cab54e7b22df7cf42b8ef115dcd95f" - integrity sha1-jNo8OMnKtU57It989CuO8RXc2V8= - dependencies: - chalk "^1.1.1" - lodash "^3.10.1" - log-symbols "^1.0.2" - text-table "^0.2.0" - tslint "^2.5.0" - -tslint@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-2.5.1.tgz#bde4c99e97cd5d1c6fbb3033f64b7d897fd41a92" - integrity sha1-veTJnpfNXRxvuzAz9kt9iX/UGpI= - dependencies: - findup-sync "~0.2.1" - optimist "~0.6.0" - underscore.string "~3.1.1" - -tslint@^5.19.0: - version "5.19.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.19.0.tgz#a2cbd4a7699386da823f6b499b8394d6c47bb968" - integrity sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^3.2.0" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.1" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-is@^1.5.5, type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/type/-/type-1.0.3.tgz#16f5d39f27a2d28d86e48f8981859e9d3296c179" - integrity sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg== - -typedoc-default-themes@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.6.0.tgz#7e73bf54dd9e11550dd0fb576d5176b758f8f8b5" - integrity sha512-MdTROOojxod78CEv22rIA69o7crMPLnVZPefuDLt/WepXqJwgiSu8Xxq+H36x0Jj3YGc7lOglI2vPJ2GhoOybw== - dependencies: - backbone "^1.4.0" - jquery "^3.4.1" - lunr "^2.3.6" - underscore "^1.9.1" - -typedoc@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.0.tgz#21eaf4db41cf2797bad027a74f2a75cd08ae0c2d" - integrity sha512-NOtfq5Tis4EFt+J2ozhVq9RCeUnfEYMFKoU6nCXCXUULJz1UQynOM+yH3TkfZCPLzigbqB0tQYGVlktUWweKlw== - dependencies: - "@types/minimatch" "3.0.3" - fs-extra "^8.1.0" - handlebars "^4.1.2" - highlight.js "^9.15.8" - lodash "^4.17.15" - marked "^0.7.0" - minimatch "^3.0.0" - progress "^2.0.3" - shelljs "^0.8.3" - typedoc-default-themes "^0.6.0" - typescript "3.5.x" - -typescript@3.5.x, typescript@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" - integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== - -uglify-js@^3.1.4: - version "3.6.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" - integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== - dependencies: - commander "~2.20.0" - source-map "~0.6.1" - -uid2@0.0.x: - version "0.0.3" - resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" - integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= - -underscore.string@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.1.1.tgz#0cdd6bcad0c046fd7663d305d8a785b5da10f335" - integrity sha1-DN1rytDARv12Y9MF2KeFtdoQ8zU= - -underscore@1.9.1, underscore@>=1.8.3, underscore@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== - -upper-case-first@^1.1.0, upper-case-first@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" - integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU= - dependencies: - upper-case "^1.1.1" - -upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - -uritemplate@~0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/uritemplate/-/uritemplate-0.3.4.tgz#05d0a853ffbc8b0f49aa3d4d2ad777b0d1ee070c" - integrity sha1-BdCoU/+8iw9Jqj1NKtd3sNHuBww= - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -urlsafe-base64@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz#23f89069a6c62f46cf3a1d3b00169cefb90be0c6" - integrity sha1-I/iQaabGL0bPOh07ABac77kL4MY= - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utils-merge@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" - integrity sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg= - -utils-merge@1.0.1, utils-merge@1.x.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.0.0, uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validator@^10.0.0, validator@^10.11.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228" - integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@1.3.1, which@^1.2.9, which@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@1.1.3, wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -xhr2@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.0.tgz#eddeff782f3b7551061b8d75645085269396e521" - integrity sha512-BDtiD0i2iKPK/S8OAZfpk6tyzEDnKKSjxWHcMBVmh+LuqJ8A32qXTyOx+TVOg2dKvq6zGBq2sgKPkEeRs1qTRA== - -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xmldom@0.1.27: - version "0.1.27" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= - -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= - -xmllint-jsparser@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/xmllint-jsparser/-/xmllint-jsparser-0.0.3.tgz#68b051343917da95f77b7a0c7a0fbb400175e366" - integrity sha1-aLBRNDkX2pX3e3oMeg+7QAF142Y= - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^3.2.0, y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== - -yaml-ast-parser@0.0.43: - version "0.0.43" - resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" - integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== - -yargs-parser@13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" - integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^13.0.0, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - -yargs-parser@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== - dependencies: - camelcase "^4.1.0" - -yargs-unparser@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" - integrity sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw== - dependencies: - flat "^4.1.0" - lodash "^4.17.11" - yargs "^12.0.5" - -yargs@10.x: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.1.0" - -yargs@13.2.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" - integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA== - dependencies: - cliui "^4.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - os-locale "^3.1.0" - 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.0.0" - -yargs@^12.0.5: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== - dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" - -yargs@^13.2.2: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - 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.1" - -yargs@^3.32.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" - integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= - dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" - decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" - -yargs@^4.1.0: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - -yn@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -z-schema@3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.21.0.tgz#26c753e85e39e741cc08bc2e7c3861d66d766a0a" - integrity sha512-+MXJmBRZvqn+LInpJBSSETK1XLQqyhKCCNqc7MY7FqiqWCTQddAahg5i0jlfX5dli7gvIfpJvijV3ZlAJRtZ1Q== - dependencies: - lodash.get "^4.0.0" - lodash.isequal "^4.0.0" - validator "^10.0.0" - optionalDependencies: - commander "^2.7.1" - -z-schema@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-4.1.0.tgz#8f824eabffdf018875cbcfa9b92dc3a348140b76" - integrity sha512-C4In7uaih70TVnpCDtfnMeCjGRIkaikT8Yxqgz0GZrLJ3nkI5TsdRPOOjEYaebRnxGlbX68qeBSOBdbCufaqjQ== - dependencies: - core-js "^2.5.7" - lodash.get "^4.4.2" - lodash.isequal "^4.5.0" - validator "^10.11.0" - optionalDependencies: - commander "^2.7.1" - -z-schema@^3.18.2: - version "3.25.1" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.25.1.tgz#7e14663be2b96003d938a56f644fb8561643fb7e" - integrity sha512-7tDlwhrBG+oYFdXNOjILSurpfQyuVgkRe3hB2q8TEssamDHB7BbLWYkYO98nTn0FibfdFroFKDjndbgufAgS/Q== - dependencies: - core-js "^2.5.7" - lodash.get "^4.0.0" - lodash.isequal "^4.0.0" - validator "^10.0.0" - optionalDependencies: - commander "^2.7.1"