diff --git a/.eslintignore b/.eslintignore index 44ccaa3..2cb6327 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ test/integration/defaultValues/**/*.ts test/integration/entityTypes/**/*.ts test/integration/examples/**/*.ts -test/integration/github-issues/**/*.ts \ No newline at end of file +test/integration/github-issues/**/*.ts +dist/**/*.d.ts diff --git a/.eslintrc.js b/.eslintrc.js index b2ae4ed..fc4df69 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,8 +28,7 @@ module.exports = { "no-plusplus": ["error", { allowForLoopAfterthoughts: true }], "@typescript-eslint/no-non-null-assertion": ["off"], - "@typescript-eslint/no-object-literal-type-assertion": ["off"], - + "import/extensions": ["off"], "no-param-reassign": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "no-loop-func": ["off"] @@ -37,17 +36,8 @@ module.exports = { settings: { "import/resolver": { node: { - extensions: [".js", ".jsx", ".ts", ".tsx"] + extensions: [".ts"] } } - }, - overrides: [ - { - files: ["**/*.test.ts"], - rules: { - "no-unused-expressions": "off", - "func-names": "off" - } - } - ] + } }; diff --git a/.travis.yml b/.travis.yml index 256e399..9af7e5c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: +- 13 - 12 - 10 -- 8 cache: npm sudo: required services: @@ -35,14 +35,17 @@ before_install: - if [ -z "$DOCKER_USERNAME" ]; then export ORACLE_Skip=1; else images=(${images[@]} oracle oracle_client); fi - if [ -n "$DOCKER_USERNAME" ]; then docker-compose up -d ${images[@]}; fi - echo ${images[@]} -- docker-compose pull --parallel --ignore-pull-failures ${images[@]} +- docker-compose pull --ignore-pull-failures ${images[@]} - docker-compose up -d ${images[@]} before_script: - if [ -n "$DOCKER_USERNAME" ]; then mkdir /opt/oracle; npm i oracledb --no-save; docker cp typeorm-mg-oracle-client:/usr/lib/oracle/12.2/client64/lib /opt/oracle/instantclient_12_2; fi - export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2:$LD_LIBRARY_PATH script: -- travis_retry sh -c 'sleep 60 && npm t -- --colors' +- travis_retry sh -c 'sleep 90 && npm t -- --colors' after_success: - codecov +after_failure: +- docker ps +- docker-compose logs dd: secure: lONUbDz2a1LWId+Z2tTaxajK7MilX/XbQ875FYD6EE09DQ0xcoPdq2/KW5/pxuN1tz4QzTG7izMwra3XWtkBySxqFwJDUOibsgYVgn+EMMuPWNMNnQgXqTTmHbtbm1L1aSMHu4bCu4cJkJBX6503R0Kv4Hbdr2LFnSUI/9KqrevA1cVyksN71BlNBdRtvnHInwB5wNNvGULSLT+DR6qGytLGjq4ZF+pW7dH3A1LNGfDY4ivGPHt9eAWGHcVuESmudO1ADmf6XTZAJVdKqDy5eJguK48XyAqRmTc1vBxDJmCNDaU/mV6fkUoEkCjn9XfG5nJLOKviycc1j/OCuuWuqojmTlRInPGV8GDT8lNivwqLBMzvKoKgSQQROEVus4xzo64M808dFbUS30et3++O589X/7P9Wjmt+6HawcEsSq5TQfEutyB+tM9OwedTkB5Fwwmymuqx23zCAJ2orP7WoIG/ApmnKu6LmpoM340UxxSGkurztQP1OqFrf4u8kDVp9/xzqnd7qSfEd8iKvvb1bOykWGxx6dhyThCdSNyT5GQL3aub3LV6g0UB37lbhB+BVSrOAhN0r1cIWT2wr2mRxwoepObmrcNQ+AOUUXE/RcONsiEQr+STsEIjJb7bTANljRYMKpiPdsAdhvDaUZRyu8KBArTCDPotanzwQFERcw8= diff --git a/CHANGELOG.md b/CHANGELOG.md index 08134e0..70d553b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,40 @@ # Changelog -## Unreleased +## 0.4.0 -* change default case conversions for generated files (#196) -* enum type safety (#205) -* postgress geography type support (#232) +### BREAKING CHANGES + +* Custom NamingStrategy is now defined as separate functions instead of a class +* Rework how parameters are passed to the library: + - Utilization of partial config files + - Option to save .tomg-config file without connection options +* Generation of separate fields for primary columns which are used in relations(old approach won't be compatible with typeorm@0.3.0) +* Remove timeout parameter - query timeout is now set by default to 1 hr +* Change default case conversions for generated files (#196) + +### FIXES +* Support complex relationships (#117) +* Proper support for many to many relations +* Proper pluralization of entity names (#142) +* Skip generation of imports not used by entity definition files +* Skip generation of indices generated by PKs or relations +* Columns with unrecognized sql type are generated with unknown type +* Generation of proper type for nullable columns +* Fixed specifying custom naming strategy by relative path (#171) +* Disallow generation of relationId fields with lazy relations(not supported in typeorm) + +### ENHANCEMENTS +* Support for old oracle versions (#195) +* New options: + * Disable column name pluralization (#142) + * Ignore tables parameter (#120) + * Generation of index file (#174) + * Default exports on generated models +* Enum type safety (#205) +* Mysql set type support (#91) +* Postgres geography type support (#232) +* Make generated models compatible with common ESLint rules +* Ability to use typeorm-model-generator as library in other projects (but no guarantees about api compatibility between different version) ## 0.3.5 diff --git a/docker-compose.yml b/docker-compose.yml index 5ff1d03..57dc65e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ services: # mssql mssql: - image: "mcr.microsoft.com/mssql/server:2017-GA-ubuntu" + image: "mcr.microsoft.com/mssql/server:2017-latest-ubuntu" container_name: "typeorm-mg-mssql" ports: - "1433:1433" diff --git a/package-lock.json b/package-lock.json index 30d9c06..6066f9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,36 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@azure/ms-rest-azure-env": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-1.1.2.tgz", + "integrity": "sha512-l7z0DPCi2Hp88w12JhDTtx5d0Y3+vhfE7JKJb9O7sEz71Cwp053N8piTtTnnk/tUor9oZHgEKi/p3tQQmLPjvA==" + }, + "@azure/ms-rest-js": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.8.14.tgz", + "integrity": "sha512-IrCPN22c8RbKWA06ZXuFwwEb15cSnr0zZ6J8Fspp9ns1SSNTERf7hv+gWvTIis1FlwHy42Mfk8hVu0/r3a0AWA==", + "requires": { + "@types/tunnel": "0.0.0", + "axios": "^0.19.0", + "form-data": "^2.3.2", + "tough-cookie": "^2.4.3", + "tslib": "^1.9.2", + "tunnel": "0.0.6", + "uuid": "^3.2.1", + "xml2js": "^0.4.19" + } + }, + "@azure/ms-rest-nodeauth": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-nodeauth/-/ms-rest-nodeauth-2.0.2.tgz", + "integrity": "sha512-KmNNICOxt3EwViAJI3iu2VH8t8BQg5J2rSAyO4IUYLF9ZwlyYsP419pdvl4NBUhluAP2cgN7dfD2V6E6NOMZlQ==", + "requires": { + "@azure/ms-rest-azure-env": "^1.1.2", + "@azure/ms-rest-js": "^1.8.7", + "adal-node": "^0.1.28" + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -13,17 +43,70 @@ "@babel/highlight": "^7.0.0" } }, - "@babel/generator": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", - "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "@babel/core": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.7.tgz", + "integrity": "sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==", "dev": true, "requires": { - "@babel/types": "^7.4.4", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.7", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.7", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz", + "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4", "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "lodash": "^4.17.13", + "source-map": "^0.5.0" }, "dependencies": { "source-map": { @@ -35,32 +118,43 @@ } }, "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.7.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", "dev": true, "requires": { - "@babel/types": "^7.4.4" + "@babel/types": "^7.7.4" + } + }, + "@babel/helpers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", + "dev": true, + "requires": { + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/highlight": { @@ -75,39 +169,48 @@ } }, "@babel/parser": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.7.tgz", + "integrity": "sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw==", "dev": true }, "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/traverse": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", - "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.4", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.4.5", - "@babel/types": "^7.4.4", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.11" + "lodash": "^4.17.13" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -120,39 +223,99 @@ } }, "@babel/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", - "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, - "@nodelib/fs.scandir": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz", - "integrity": "sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg==", + "@istanbuljs/load-nyc-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.1", + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz", - "integrity": "sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz", - "integrity": "sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.1", + "@nodelib/fs.scandir": "2.1.3", "fastq": "^1.6.0" } }, @@ -166,18 +329,18 @@ } }, "@sinonjs/commons": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", - "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.0.tgz", + "integrity": "sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/formatio": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", - "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", "dev": true, "requires": { "@sinonjs/commons": "^1", @@ -185,14 +348,22 @@ } }, "@sinonjs/samsam": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", - "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", "dev": true, "requires": { - "@sinonjs/commons": "^1.0.2", + "@sinonjs/commons": "^1.3.0", "array-from": "^2.1.1", - "lodash": "^4.17.11" + "lodash": "^4.17.15" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } } }, "@sinonjs/text-encoding": { @@ -201,36 +372,63 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/array.prototype.flatmap": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/array.prototype.flatmap/-/array.prototype.flatmap-1.2.0.tgz", + "integrity": "sha512-sMRMigmTCA1EVX46F0jPhSFo51uFNo83GkeYlp7r4xKkXwfjkDpTm13vB9Tba4Ey+0rUXX3QjSWHAIwSb3qzrA==", + "dev": true + }, "@types/chai": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.7.tgz", + "integrity": "sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g==", "dev": true }, "@types/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-dberBxQW/XWv6BMj0su1lV9/C9AUx5Hqu2pisuS6S4YK/Qt6vurcj/BmcbEsobIWWCQzhesNY8k73kIxx4X7Mg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-PO2gcfR3Oxa+u0QvECLe1xKXOqYTzCmWf0FhLhjREoW3fPAVamjihL7v1MOVLJLsnAMdLcjkfrs01yvDMwVK4Q==", "dev": true, "requires": { "@types/chai": "*" } }, "@types/chai-subset": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.2.tgz", - "integrity": "sha512-VMA1aOXwPEJADlj5ykmYv77YKmbEuAxiLz/+lT6vFIWQ1EA06jF01TytVBAbVTNk0pjfW1Uhw5R5MaEq426N0A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", "dev": true, "requires": { "@types/chai": "*" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/eslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-6.1.3.tgz", + "integrity": "sha512-llYf1QNZaDweXtA7uY6JczcwHmFwJL9TpK3E6sY0B18l6ulDT6VWNMAdEjYccFHiDfxLPxffd8QmSDV4QUUspA==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, + "@types/estree": { + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.41.tgz", + "integrity": "sha512-rIAmXyJlqw4KEBO7+u9gxZZSQHaCNnIzYrnNmYVpgfJhxTqO0brCX0SYpqUTkVI5mwwUwzmtspLBGBKroMeynA==", + "dev": true + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -238,9 +436,9 @@ "dev": true }, "@types/fs-extra": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", - "integrity": "sha512-bCtL5v9zdbQW86yexOlXWTEGvLNqWxMFyi7gQA7Gcthbezr2cPSOb8SkESVKA937QD5cIwOFLDFt0MQoXOEr9Q==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.1.tgz", + "integrity": "sha512-J00cVDALmi/hJOYsunyT52Hva5TnJeKP5yd1r+mH/ZU0mbYZflR0Z5kw5kITtKTRYMhm1JMClOFYdHnQszEvqw==", "dev": true, "requires": { "@types/node": "*" @@ -295,28 +493,28 @@ "dev": true }, "@types/mssql": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@types/mssql/-/mssql-4.0.16.tgz", - "integrity": "sha512-bvH+9IZJ46QyQtuBciDyDf3lSqFFM/XhdVsHsCdVm0CdaZwH421wOIHJ2ajb2CG4XFqfNXA+UVNDyPqiNz6c0w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/mssql/-/mssql-6.0.0.tgz", + "integrity": "sha512-Mn+PYRNugxJQlfY50xUa2PuKUO3knie8/MclSGQGOTh0fITd6l+yjotq23tmahmTml3hiARwTksqV0hjLrVnhA==", "dev": true, "requires": { - "@types/node": "*" + "@types/node": "*", + "@types/tedious": "*" } }, "@types/mysql": { - "version": "2.15.6", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.6.tgz", - "integrity": "sha512-PJBY2R3jGJwGrmFgGAJ+1nj4S/PLkF6nT+HvUygniq9ZcVht0mTH1TLAjjyfIXf9FfrELs8mbqOrWa/Tn89NCA==", + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.8.tgz", + "integrity": "sha512-l0TUdg6KDEaLO75/yjdjksobJDRWv8iZlpRfv/WW1lQZCQDKdTDnKCkeH10oapzP/JTuKiTy6Cvq/sm/0GgcUw==", "dev": true, "requires": { "@types/node": "*" } }, "@types/node": { - "version": "12.6.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.9.tgz", - "integrity": "sha512-+YB9FtyxXGyD54p8rXwWaN1EWEyar5L58GlGWgtH2I9rGmLGBQcw63+0jw+ujqVavNuO47S1ByAjm9zdHMnskw==", - "dev": true + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.4.tgz", + "integrity": "sha512-Lue/mlp2egZJoHXZr4LndxDAd7i/7SQYhV0EjWfb/a4/OZ6tuVwMCVPiwkU5nsEipxEf7hmkSU7Em5VQ8P5NGA==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -325,18 +523,27 @@ "dev": true }, "@types/oracledb": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-3.1.3.tgz", - "integrity": "sha512-UlFv/T2A+PnvaNldjGjVQ7EBXxrAqtPman3i5J9kUQu37W+l/iFM2BPTg6CYr/Uxx6v0dAoVgHb1Po+dFfCdSg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-4.1.1.tgz", + "integrity": "sha512-Vjk5RLENuQKzgqjoIyGH9wZCGOxc4r4j2nh7jKo32+yJ4zwwPiKp808YZh0iRPgXOZeqFVaQYHB0xpEFuV4lug==", "dev": true, "requires": { - "@types/node": "*" + "@types/node": "*", + "dotenv": "^8.2.0" + }, + "dependencies": { + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + } } }, "@types/pg": { - "version": "7.4.14", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.4.14.tgz", - "integrity": "sha512-2e4XapP9V/X42IGByC5IHzCzHqLLCNJid8iZBbkk6lkaDMvli8Rk62YE9wjGcLD5Qr5Zaw1ShkQyXy91PI8C0Q==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.14.1.tgz", + "integrity": "sha512-gQgg4bLuykokypx4O1fwEzl5e6UjjyaBtN3znn5zhm0YB9BnKyHDw+e4cQY9rAPzpdM2qpJbn9TNzUazbmTsdw==", "dev": true, "requires": { "@types/node": "*", @@ -344,24 +551,51 @@ } }, "@types/pg-types": { - "version": "1.11.4", - "resolved": "https://registry.npmjs.org/@types/pg-types/-/pg-types-1.11.4.tgz", - "integrity": "sha512-WdIiQmE347LGc1Vq3Ki8sk3iyCuLgnccqVzgxek6gEHp2H0p3MQ3jniIHt+bRODXKju4kNQ+mp53lmP5+/9moQ==", - "dev": true, + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@types/pg-types/-/pg-types-1.11.5.tgz", + "integrity": "sha512-L8ogeT6vDzT1vxlW3KITTCt+BVXXVkLXfZ/XNm6UqbcJgxf+KPO7yjWx7dQQE8RW07KopL10x2gNMs41+IkMGQ==", + "dev": true + }, + "@types/pluralize": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.29.tgz", + "integrity": "sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==", + "dev": true + }, + "@types/prettier": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.0.tgz", + "integrity": "sha512-gDE8JJEygpay7IjA/u3JiIURvwZW08f0cZSZLAzFoX/ZmeqvS0Sqv+97aKuHpNsalAMMhwPe+iAS6fQbfmbt7A==", + "dev": true + }, + "@types/readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-Mq2eLkGYamlcolW603FY2ROBvcl90jPF+3jLkjpBV6qS+2aVeJqlgRG0TVAa1oWbmPdb5yOWlOPVvQle76nUNw==", "requires": { - "moment": ">=2.14.0" + "@types/node": "*", + "safe-buffer": "*" } }, "@types/sinon": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.0.13.tgz", - "integrity": "sha512-d7c/C/+H/knZ3L8/cxhicHUiTDxdgap0b/aNJfsmLwFu/iOP17mdgbQsbHA3SJmrzsjD0l3UEE5SN4xxuz5ung==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", + "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", "dev": true }, "@types/sqlite3": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/sqlite3/-/sqlite3-3.1.5.tgz", - "integrity": "sha512-upsrd1zEYMa4Y+prurQ+vpo5SN63BUF6tOjeTv3ziF+9W9PHVh4/S5cy0qAqkHvmOEm/AZhEKd7V/0bR2udmFw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/sqlite3/-/sqlite3-3.1.6.tgz", + "integrity": "sha512-OBsK0KIGUICExQ/ZvnPY4cKx5Kz4NcrVyGTIvOL5y4ajXu7r++RfBajfpGfGDmDVCKcoCDX1dO84/oeyeITnxA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/tedious": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.0.tgz", + "integrity": "sha512-uu/7XzkXSoU/AngLDdGURUFw98vZFgzQOuOIIUbSPiUfkaU7O1z29bDN4VejtmM5NS21fCHVJdd+cM96h+L78w==", "dev": true, "requires": { "@types/node": "*" @@ -376,71 +610,107 @@ "@types/node": "*" } }, - "@types/yargs": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.1.tgz", - "integrity": "sha512-UVjo2oH79aRNcsDlFlnQ/iJ67Jd7j6uSg7jUJP/RZ/nUjAh5ElmnwlD5K/6eGgETJUgCHkiWn91B8JjXQ6ubAw==", - "dev": true - }, - "@types/yn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/yn/-/yn-3.1.0.tgz", - "integrity": "sha512-Qs2tU/syFYlALjR3EoT+NcvpMwAd6voSiDxW+c8bhAN1WbzQUnRfWTmttORf4R1WqDUT+dvHKj+llupSxs0O/w==", - "dev": true, + "@types/tunnel": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.0.tgz", + "integrity": "sha512-FGDp0iBRiBdPjOgjJmn1NH0KDLN+Z8fRmo+9J7XGBhubq1DPrGrbmG4UTlGzrpbCpesMqD0sWkzi27EYkOMHyg==", "requires": { - "yn": "*" + "@types/node": "*" } }, - "@typescript-eslint/eslint-plugin": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz", - "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==", + "@types/yargs": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", + "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "1.13.0", - "eslint-utils": "^1.3.1", + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.14.0.tgz", + "integrity": "sha512-sneOJ3Hu0m5whJiVIxGBZZZMxMJ7c0LhAJzeMJgHo+n5wFs+/6rSR/gl7crkdR2kNwfOOSdzdc0gMvatG4dX2Q==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "2.14.0", + "eslint-utils": "^1.4.3", "functional-red-black-tree": "^1.0.1", - "regexpp": "^2.0.1", - "tsutils": "^3.7.0" + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" } }, "@typescript-eslint/experimental-utils": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", - "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.14.0.tgz", + "integrity": "sha512-KcyKS7G6IWnIgl3ZpyxyBCxhkBPV+0a5Jjy2g5HxlrbG2ZLQNFeneIBVXdaBCYOVjvGmGGFKom1kgiAY75SDeQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-scope": "^4.0.0" + "@typescript-eslint/typescript-estree": "2.14.0", + "eslint-scope": "^5.0.0" } }, "@typescript-eslint/parser": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", - "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.14.0.tgz", + "integrity": "sha512-haS+8D35fUydIs+zdSf4BxpOartb/DjrZ2IxQ5sR8zyGfd77uT9ZJZYF8+I0WPhzqHmfafUBx8MYpcp8pfaoSA==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "1.13.0", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-visitor-keys": "^1.0.0" + "@typescript-eslint/experimental-utils": "2.14.0", + "@typescript-eslint/typescript-estree": "2.14.0", + "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", - "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.14.0.tgz", + "integrity": "sha512-pnLpUcMNG7GfFFfNQbEX6f1aPa5fMnH2G9By+A1yovYI4VIOK2DzkaRuUlIkbagpAcrxQHLqovI1YWqEcXyRnA==", "dev": true, "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", "lodash.unescape": "4.0.1", - "semver": "5.5.0" + "semver": "^6.3.0", + "tsutils": "^3.17.1" }, "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -451,15 +721,15 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, "adal-node": { @@ -479,21 +749,31 @@ }, "dependencies": { "@types/node": { - "version": "8.10.49", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.49.tgz", - "integrity": "sha512-YX30JVx0PvSmJ3Eqr74fYLGeBxD+C7vIL20ek+GGGLJeUbVYRUW3EzyAXpIRA0K8c8o0UWqR/GwEFYiFoz1T8w==" + "version": "8.10.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", + "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==" } } }, "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" } }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -514,7 +794,8 @@ "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -540,18 +821,28 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, - "app-root-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", - "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==" - }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "default-require-extensions": "^2.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" + }, + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" } }, "aproba": { @@ -575,9 +866,9 @@ } }, "arg": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz", - "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz", + "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==", "dev": true }, "argparse": { @@ -601,13 +892,51 @@ "dev": true }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.0.tgz", + "integrity": "sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } } }, "array-union": { @@ -616,6 +945,103 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, + "array.prototype.flatmap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", + "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -642,9 +1068,9 @@ "dev": true }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==" }, "asynckit": { "version": "0.4.0", @@ -661,15 +1087,24 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -679,23 +1114,35 @@ "tweetnacl": "^0.14.3" } }, - "big-number": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/big-number/-/big-number-1.0.0.tgz", - "integrity": "sha512-cHUzdT+mMXd1ozht8n5ZwBlNiPO/4zCqqkyp3lF1TMPsRJLXUbQ7cKnfXRkrW475H5SOtSOP0HFeihNbpa53MQ==" - }, "bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", + "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "readable-stream": "^3.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "brace-expansion": { @@ -723,9 +1170,9 @@ "dev": true }, "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" @@ -748,15 +1195,15 @@ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "requires": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" } }, "caller-callsite": { @@ -766,6 +1213,14 @@ "dev": true, "requires": { "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } } }, "caller-path": { @@ -778,18 +1233,25 @@ } }, "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "camelcase": { @@ -797,6 +1259,23 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, + "capital-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.3.tgz", + "integrity": "sha512-OlUSJpUr7SY0uZFOxcwnDOU7/MpHlKTZx2mqnDYQFrDudXLFm0JJ9wr/l4csB+rh2Ug0OPuoSO53PqiZBqno9A==", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0", + "upper-case-first": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -842,28 +1321,29 @@ } }, "change-case": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz", - "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.1.tgz", + "integrity": "sha512-qRlUWn/hXnX1R1LBDF/RelJLiqNjKjUqlmuBVSEIyye8kq49CXqkZWKmi8XeUAdDXWFOcGLUMZ+aHn3Q5lzUXw==", "requires": { - "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" + "camel-case": "^4.1.1", + "capital-case": "^1.0.3", + "constant-case": "^3.0.3", + "dot-case": "^3.0.3", + "header-case": "^2.0.3", + "no-case": "^3.0.3", + "param-case": "^3.0.3", + "pascal-case": "^3.1.1", + "path-case": "^3.0.3", + "sentence-case": "^3.0.3", + "snake-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "chardet": { @@ -877,10 +1357,26 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" }, "ci-info": { "version": "2.0.0", @@ -888,24 +1384,78 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, "requires": { "restore-cursor": "^2.0.0" } }, "cli-highlight": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.1.tgz", - "integrity": "sha512-0y0VlNmdD99GXZHYnvrQcmHxP8Bi6T00qucGgBgGv4kJ0RyDthNnnFPupHV7PYv/OXSVk+azFbOeaW6+vGmx9A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.4.tgz", + "integrity": "sha512-s7Zofobm20qriqDoU9sXptQx0t2R9PEgac92mENNm7xaEe1hn71IIMsXMK+6encA6WRCWWxIGQbipr3q998tlQ==", "requires": { - "chalk": "^2.3.0", + "chalk": "^3.0.0", "highlight.js": "^9.6.0", "mz": "^2.4.0", - "parse5": "^4.0.0", - "yargs": "^13.0.0" + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^5.1.1", + "yargs": "^15.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, "cli-truncate": { @@ -933,6 +1483,12 @@ "number-is-nan": "^1.0.0" } }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -961,70 +1517,33 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { - "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=", - "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==", "requires": { - "number-is-nan": "^1.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, + "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==", "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } } } @@ -1035,9 +1554,9 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codecov": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.5.0.tgz", - "integrity": "sha512-/OsWOfIHaQIr7aeZ4pY0UC1PZT6kimoKFOFYFNb6wxo3iw12nRrh+mNGH72rnXxNsq6SGfesVPizm/6Q3XqcFQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.1.tgz", + "integrity": "sha512-IUJB6WG47nWK7o50etF8jBadxdMw7DmoQg05yIljstXFBGB6clOZsIj6iD4P82T2YaIU3qq+FFu8K9pxgkCJDQ==", "dev": true, "requires": { "argv": "^0.0.2", @@ -1045,18 +1564,6 @@ "js-yaml": "^3.13.1", "teeny-request": "^3.11.3", "urlgrey": "^0.4.4" - }, - "dependencies": { - "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" - } - } } }, "color-convert": { @@ -1081,10 +1588,9 @@ } }, "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true + "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==" }, "commondir": { "version": "1.0.1", @@ -1109,12 +1615,20 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "constant-case": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", - "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.3.tgz", + "integrity": "sha512-FXtsSnnrFYpzDmvwDGQW+l8XK3GV1coLyBN0eBz16ZUzGaZcT2ANVCJmLeuw2GQgxKHQIe9e0w2dzkSfaRlUmA==", "requires": { - "snake-case": "^2.1.0", - "upper-case": "^1.1.1" + "no-case": "^3.0.3", + "tslib": "^1.10.0", + "upper-case": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "contains-path": { @@ -1124,9 +1638,9 @@ "dev": true }, "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -1147,25 +1661,22 @@ "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" - } - }, - "cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, - "requires": { - "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" }, "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true } } @@ -1184,9 +1695,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -1250,34 +1761,52 @@ "dev": true }, "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", "dev": true, "requires": { - "strip-bom": "^3.0.0" + "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } }, "del": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-5.0.0.tgz", - "integrity": "sha512-TfU3nUY0WDIhN18eq+pgpbLY9AfL5RfiE9czKaTSolc6aK7qASXfDErvYgjV1UqCR4sNXDoxO0/idPmhDUt2Sg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", + "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", "dev": true, "requires": { - "globby": "^10.0.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "rimraf": "^2.6.3" + "globby": "^10.0.1", + "graceful-fs": "^4.2.2", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.1", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } } }, "delayed-stream": { @@ -1291,9 +1820,9 @@ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "detect-libc": { "version": "1.0.3", @@ -1333,17 +1862,25 @@ } }, "dot-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", - "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz", + "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==", "requires": { - "no-case": "^2.2.0" + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "dotenv": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz", - "integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", "dev": true }, "ecc-jsbn": { @@ -1375,9 +1912,9 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -1424,9 +1961,9 @@ "dev": true }, "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, "es6-promisify": { @@ -1444,9 +1981,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", - "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -1456,19 +1993,19 @@ "debug": "^4.0.1", "doctrine": "^3.0.0", "eslint-scope": "^5.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^6.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.4.1", + "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -1477,7 +2014,7 @@ "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^6.1.2", @@ -1497,36 +2034,19 @@ "ms": "^2.1.1" } }, - "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "type-fest": "^0.8.1" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "semver": { @@ -1535,10 +2055,10 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true } } @@ -1555,20 +2075,12 @@ } }, "eslint-config-prettier": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.0.0.tgz", - "integrity": "sha512-vDrcCFE3+2ixNT5H83g28bO/uYAwibJxerXPj+E7op4qzBCsAV36QfvdAyVOoNxKAH2Os/e01T/2x++V0LPukA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz", + "integrity": "sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA==", "dev": true, "requires": { "get-stdin": "^6.0.0" - }, - "dependencies": { - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - } } }, "eslint-import-resolver-node": { @@ -1599,12 +2111,12 @@ } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz", + "integrity": "sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==", "dev": true, "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -1617,83 +2129,32 @@ "ms": "2.0.0" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } } } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz", + "integrity": "sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw==", "dev": true, "requires": { "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", + "eslint-module-utils": "^2.4.1", "has": "^1.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" + "resolve": "^1.12.0" }, "dependencies": { "debug": { @@ -1724,18 +2185,6 @@ "locate-path": "^2.0.0" } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -1776,41 +2225,6 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", @@ -1824,9 +2238,9 @@ } }, "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -1834,29 +2248,29 @@ } }, "eslint-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", - "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, "espree": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.0.0.tgz", - "integrity": "sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" } }, "esprima": { @@ -1883,9 +2297,9 @@ } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { @@ -1935,16 +2349,15 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.0.4.tgz", - "integrity": "sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", + "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", "dev": true, "requires": { - "@nodelib/fs.stat": "^2.0.1", - "@nodelib/fs.walk": "^1.2.1", - "glob-parent": "^5.0.0", - "is-glob": "^4.0.1", - "merge2": "^1.2.3", + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", "micromatch": "^4.0.2" } }, @@ -1969,16 +2382,18 @@ } }, "figlet": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.3.tgz", - "integrity": "sha512-+F5zdvZ66j77b8x2KCPvWUHC0UCKUMWrewxmewgPlagp3wmDpcrHMbyv/ygq/6xoxBPGQA+UJU3SMoBzKoROQQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.4.tgz", + "integrity": "sha512-mv8YA9RruB4C5QawPaD29rEVx3N97ZTyNrE4DAfbhuo6tpcMdKnPVo8MlyT3RP5uPcg5M14bEJBq7kjFf4kAWg==" }, "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, "file-entry-cache": { @@ -2000,23 +2415,57 @@ } }, "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz", + "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" }, "dependencies": { - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "find-up": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" } } } @@ -2036,14 +2485,6 @@ "dev": true, "requires": { "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - } } }, "flat-cache": { @@ -2055,6 +2496,17 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "flatted": { @@ -2063,24 +2515,78 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" }, "dependencies": { "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } @@ -2100,6 +2606,12 @@ "mime-types": "^2.1.12" } }, + "fromentries": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", + "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "dev": true + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -2118,11 +2630,11 @@ } }, "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs.realpath": { @@ -2130,11 +2642,17 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2190,11 +2708,6 @@ } } }, - "generic-pool": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.7.1.tgz", - "integrity": "sha512-ug6DAZoNgWm6q5KhPFA+hzXfBLFQu5sTXxPpv44DmE0A2g+CiHoq9LTVdkXpZMkYVMoGw83F6W+WT0h0MFMK/w==" - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2207,15 +2720,15 @@ "dev": true }, "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "dev": true }, "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, "get-stream": { @@ -2249,9 +2762,9 @@ } }, "glob-parent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", - "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -2277,6 +2790,14 @@ "ignore": "^5.1.1", "merge2": "^1.2.3", "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } } }, "graceful-fs": { @@ -2291,9 +2812,9 @@ "dev": true }, "handlebars": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.0.tgz", - "integrity": "sha512-7XlnO8yBXOdi7AzowjZssQr47Ctidqm7GbgARapOaqSN9HQhlClnOkR9HieGauIT3A8MBC6u9wPCXs97PCYpWg==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", @@ -2319,7 +2840,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -2347,8 +2867,7 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "has-unicode": { "version": "2.0.1", @@ -2356,12 +2875,27 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.1.0.tgz", + "integrity": "sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA==", "dev": true, "requires": { - "is-stream": "^1.0.1" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "he": { @@ -2371,18 +2905,28 @@ "dev": true }, "header-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", - "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.3.tgz", + "integrity": "sha512-LChe/V32mnUQnTwTxd3aAlNMk8ia9tjCDb/LjYtoMrdAPApxLB+azejUk5ERZIZdIqvinwv6BAUuFXH/tQPdZA==", "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.3" + "capital-case": "^1.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "highlight.js": { - "version": "9.15.8", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz", - "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==" + "version": "9.17.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.17.1.tgz", + "integrity": "sha512-TA2/doAur5Ol8+iM3Ov7qy3jYcr/QiJ2eDTdRF4dfbjG7AaaB99J5G+zSl11ljbl6cIcahgPY6SKb3sC3EJ0fw==", + "requires": { + "handlebars": "^4.5.3" + } }, "hosted-git-info": { "version": "2.7.1", @@ -2390,6 +2934,12 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-escaper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "dev": true + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2401,32 +2951,107 @@ } }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", + "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", "dev": true, "requires": { - "agent-base": "^4.1.0", + "agent-base": "^4.3.0", "debug": "^3.1.0" } }, "husky": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/husky/-/husky-3.0.2.tgz", - "integrity": "sha512-WXCtaME2x0o4PJlKY4ap8BzLA+D0zlvefqAvLCPriOOu+x0dpO5uc5tlB7CY6/0SE2EESmoZsj4jW5D09KrJoA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", + "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==", "dev": true, "requires": { "chalk": "^2.4.2", + "ci-info": "^2.0.0", "cosmiconfig": "^5.2.1", "execa": "^1.0.0", "get-stdin": "^7.0.0", - "is-ci": "^2.0.0", "opencollective-postinstall": "^2.0.2", "pkg-dir": "^4.2.0", - "please-upgrade-node": "^3.1.1", - "read-pkg": "^5.1.1", + "please-upgrade-node": "^3.2.0", + "read-pkg": "^5.2.0", "run-node": "^1.0.0", "slash": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + } + } } }, "iconv-lite": { @@ -2443,27 +3068,27 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "ignore": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.2.tgz", - "integrity": "sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "requires": { "minimatch": "^3.0.4" } }, "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, "imurmurhash": { @@ -2473,9 +3098,9 @@ "dev": true }, "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, "inflight": { @@ -2498,57 +3123,142 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz", - "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.2.tgz", + "integrity": "sha512-cZGvHaHwcR9E3xK9EGO5pHKELU+yaeJO7l2qGKIbqk4bCuDuAn15LCoUTS2nSkfv9JybFlnAGrOcVpCDZZOLhw==", "requires": { - "ansi-escapes": "^3.2.0", + "ansi-escapes": "^4.2.1", "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", + "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", "strip-ansi": "^5.1.0", "through": "^2.3.6" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "requires": { + "type-fest": "^0.8.1" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "figures": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rxjs": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "requires": { + "tslib": "^1.9.0" + } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-directory": { "version": "0.3.1", @@ -2576,14 +3286,6 @@ "is-extglob": "^2.1.1" } }, - "is-lower-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", - "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", - "requires": { - "lower-case": "^1.1.0" - } - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2611,23 +3313,11 @@ "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true }, "is-promise": { "version": "2.1.0", @@ -2638,7 +3328,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -2659,7 +3348,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -2669,13 +3357,11 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-upper-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", - "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", - "requires": { - "upper-case": "^1.1.0" - } + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -2694,75 +3380,143 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, "istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "requires": { - "append-transform": "^1.0.0" + "append-transform": "^2.0.0" } }, "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.0.tgz", + "integrity": "sha512-Nm4wVHdo7ZXSG30KjZ2Wl5SU/Bw7bDx1PdaiIFzEStdjs0H12mOTncn1GVYuqQSaZxpg87VGBRsVRPGD2cD1AQ==", "dev": true, "requires": { - "@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" + "@babel/core": "^7.7.5", + "@babel/parser": "^7.7.5", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "dependencies": { "semver": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" }, "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", "dev": true, "requires": { "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", + "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "dependencies": { @@ -2778,12 +3532,13 @@ } }, "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, "js-tokens": { @@ -2796,12 +3551,16 @@ "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" } }, + "jsbi": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.1.tgz", + "integrity": "sha512-+HQESPaV0mRiH614z4JPVPAftcRC2p53x92lySPzUzFwJbJTMpzHz8OYUkcXPN3fOcHUe0NdVcHnCtX/1+eCrA==" + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -2840,6 +3599,23 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -2884,15 +3660,6 @@ "safe-buffer": "^5.0.1" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2910,9 +3677,9 @@ "dev": true }, "lint-staged": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.2.1.tgz", - "integrity": "sha512-3lGgJfBddCy/WndKdNko+uJbwyYjBD1k+V+SA+phBYWzH265S95KQya/Wln/UL+hOjc7NcjtFYVCUWuAcqYHhg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.5.0.tgz", + "integrity": "sha512-nawMob9cb/G1J98nb8v3VC/E8rcX1rryUYXVZ69aT9kde6YWX+uvNOEHY5yf2gcWcTJGiD0kqXmCnS3oD75GIA==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -2925,11 +3692,23 @@ "listr": "^0.14.3", "log-symbols": "^3.0.0", "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", "please-upgrade-node": "^3.1.1", "string-argv": "^0.3.0", "stringify-object": "^3.3.0" }, "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -2940,12 +3719,12 @@ } }, "execa": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-2.0.3.tgz", - "integrity": "sha512-iM124nlyGSrXmuyZF1EMe83ESY2chIYVyDRZKgmcDynid2Q2v/+GuE7gNMl6Sy9Niwf4MC0DDxagOxeMPjuLsw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", "dev": true, "requires": { - "cross-spawn": "^6.0.5", + "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", @@ -2971,21 +3750,6 @@ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, "npm-run-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", @@ -2995,15 +3759,6 @@ "path-key": "^3.0.0" } }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, "p-finally": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", @@ -3011,10 +3766,34 @@ "dev": true }, "path-key": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", - "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -3033,6 +3812,14 @@ "listr-verbose-renderer": "^0.5.0", "p-map": "^2.0.0", "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } } }, "listr-silent-renderer": { @@ -3082,15 +3869,11 @@ "supports-color": "^2.0.0" } }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true }, "log-symbols": { "version": "1.0.2", @@ -3128,18 +3911,17 @@ "cli-cursor": "^2.1.0", "date-fns": "^1.27.2", "figures": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + }, + "dependencies": { + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + } } }, "locate-path": { @@ -3154,7 +3936,8 @@ "lodash": { "version": "4.17.14", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==", + "dev": true }, "lodash.flattendeep": { "version": "4.4.0", @@ -3169,12 +3952,12 @@ "dev": true }, "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", "dev": true, "requires": { - "chalk": "^2.0.1" + "chalk": "^2.4.2" } }, "log-update": { @@ -3189,62 +3972,39 @@ } }, "lolex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", - "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", "dev": true }, "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" - }, - "lower-case-first": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", - "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", "requires": { - "lower-case": "^1.1.2" - } - }, - "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" + "tslib": "^1.10.0" }, "dependencies": { - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" } } }, "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "semver": "^6.0.0" }, "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -3255,43 +4015,6 @@ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - } - } - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -3299,9 +4022,9 @@ "dev": true }, "merge2": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.4.tgz", - "integrity": "sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", + "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", "dev": true }, "micromatch": { @@ -3328,9 +4051,9 @@ } }, "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "minimatch": { "version": "3.0.4", @@ -3346,9 +4069,9 @@ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" }, "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3362,11 +4085,11 @@ } }, "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mkdirp": { @@ -3385,13 +4108,14 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.0.tgz", + "integrity": "sha512-CirsOPbO3jU86YKjjMzFLcXIb5YiGLUrjrXFHoJ3e2z9vWiaZVCZQ2+gtRGMPWF+nFhN6AWwLM/juzAQ6KRkbA==", "dev": true, "requires": { "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", + "chokidar": "3.3.0", "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", @@ -3404,15 +4128,15 @@ "minimatch": "3.0.4", "mkdirp": "0.5.1", "ms": "2.1.1", - "node-environment-flags": "1.0.5", + "node-environment-flags": "1.0.6", "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" + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" }, "dependencies": { "glob": { @@ -3429,6 +4153,15 @@ "path-is-absolute": "^1.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" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3440,6 +4173,12 @@ "strip-ansi": "^5.1.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", @@ -3459,51 +4198,64 @@ } }, "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", "dev": true, "requires": { - "cliui": "^4.0.0", + "cliui": "^5.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-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", - "dev": true - }, "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==" }, "mssql": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-5.1.0.tgz", - "integrity": "sha512-eHrqRWCEBaXo48y2ZBaDleFvrWm2vYm6dNm1ci0XLYxm6kUb4KRsvjl74iKFhfYyuF9z6qzmTe/QmoQk+YVcVw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-6.0.1.tgz", + "integrity": "sha512-7oPhbQjotFJBgMPlzLmPwWlnrryxrDltjCNCD9BK7Df7TA9wc6Mb/0Bcx04NJyHCMAhw8C/iWjbJoeDyUfRNUA==", "requires": { - "debug": "^3.2.6", - "generic-pool": "^3.6.1", - "tedious": "^4.2.0" + "debug": "^4", + "tarn": "^1.1.5", + "tedious": "^6.6.2" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + } } }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "mysql": { "version": "2.17.1", @@ -3570,12 +4322,6 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" }, - "nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true - }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -3583,30 +4329,49 @@ "dev": true }, "nise": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", - "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", "dev": true, "requires": { - "@sinonjs/formatio": "^3.1.0", + "@sinonjs/formatio": "^3.2.1", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", - "lolex": "^4.1.0", + "lolex": "^5.0.1", "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } } }, "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", "requires": { - "lower-case": "^1.1.1" + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", "dev": true, "requires": { "object.getownpropertydescriptors": "^2.0.3", @@ -3614,9 +4379,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -3644,13 +4409,30 @@ "tar": "^4" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, "nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", @@ -3683,15 +4465,29 @@ } } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-bundled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" }, "npm-packlist": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.4.tgz", - "integrity": "sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", "requires": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" @@ -3723,448 +4519,39 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.0.tgz", + "integrity": "sha512-qcLBlNCKMDVuKb7d1fpxjPR8sHeMVX0CHarXAVzrVWoFrigCkYR8xcrjfXSPi5HXM7EU78L6ywO7w1c5rZNCNg==", "dev": true, "requires": { - "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", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", "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", + "make-dir": "^3.0.0", + "node-preload": "^0.2.0", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", "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" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "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.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.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", - "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "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==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "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==" - }, - "package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "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": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "requires": { - "no-case": "^2.2.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } - } - }, - "parent-require": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", - "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=" - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" - }, - "pascal-case": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", - "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=", - "requires": { - "camel-case": "^3.0.0", - "upper-case-first": "^1.1.0" - } - }, - "path-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", - "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=", - "requires": { - "no-case": "^2.2.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.12.0.tgz", - "integrity": "sha512-q54Ic0oBXfDZMwheP8ALeUX32TUXvF7SNgAlZjyhkDuFCJkQCgcLBz0Be5uOrAj3ljSok/CI9lRbYzEko0z1Zw==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.4", - "pg-types": "~2.0.0", - "pgpass": "1.x", - "semver": "4.3.2" - } - }, - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" - }, - "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": "2.0.7", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.7.tgz", - "integrity": "sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw==" - }, - "pg-types": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.1.tgz", - "integrity": "sha512-b7y6QM1VF5nOeX9ukMQ0h8a9z89mojrBHXfJeSug4mhL0YpxNBm83ot2TROyoAmX/ZOX3UbwVO4EbH7i1ZZNiw==", - "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.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "requires": { - "split": "^1.0.0" - } - }, - "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "uuid": "^3.3.3", + "yargs": "^15.0.2" }, "dependencies": { "find-up": { @@ -4177,6 +4564,20 @@ "path-exists": "^4.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -4200,18 +4601,539 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "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.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + } + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", + "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "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==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.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==" + }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz", + "integrity": "sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==", + "requires": { + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parent-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", + "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=" + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-5.1.1.tgz", + "integrity": "sha512-CF+TKjXqoqyDwHqBhFQ+3l5t83xYi6fVT1tQNg+Ye0JRLnTxWvIroCjEp1A0k4lneHNBGnICUf0cfYVYGEazqw==", + "requires": { + "parse5": "^5.1.1" + } + }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz", + "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "path-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.3.tgz", + "integrity": "sha512-UMFU6UETFpCNWbIWNczshPrnK/7JAXBP2NYw80ojElbQ2+JYxdqWDBkvvqM93u4u6oLmuJ/tPOf2tM8KtXv4eg==", + "requires": { + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pg": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.17.0.tgz", + "integrity": "sha512-70Q4ZzIdPgwMPb3zUIzAUwigNJ4v5vsWdMED6OzXMfOECeYTvTm7iSC3FpKizu/R1BHL8Do3bLs6ltGfOTAnqg==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "0.1.3", + "pg-packet-stream": "^1.1.0", + "pg-pool": "^2.0.9", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" + }, + "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-packet-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz", + "integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg==" + }, + "pg-pool": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.9.tgz", + "integrity": "sha512-gNiuIEKNCT3OnudQM2kvgSnXsLkSpd6mS/fRnqs6ANtrke6j8OY5l9mnAryf1kgwJMWLg0C1N1cYTZG1xmEYHQ==" + }, + "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.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "^1.0.0" + } + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true } } }, "please-upgrade-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", - "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", "dev": true, "requires": { "semver-compare": "^1.0.0" } }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, "postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -4242,10 +5164,18 @@ "dev": true }, "prettier": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", - "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", - "dev": true + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" + }, + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } }, "progress": { "version": "2.0.3", @@ -4253,12 +5183,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "psl": { "version": "1.1.32", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", @@ -4299,55 +5223,60 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" } } }, "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" }, "dependencies": { + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" + "error-ex": "^1.2.0" } - } - } - }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "pify": "^2.0.0" } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -4372,15 +5301,24 @@ } } }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, "release-zalgo": { @@ -4437,27 +5375,45 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.0.tgz", + "integrity": "sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw==", "dev": true, "requires": { "path-parse": "^1.0.6" } }, "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, "requires": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + } } }, "reusify": { @@ -4467,26 +5423,12 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "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" - } - } } }, "run-async": { @@ -4513,6 +5455,7 @@ "version": "6.5.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "dev": true, "requires": { "tslib": "^1.9.0" } @@ -4544,12 +5487,20 @@ "dev": true }, "sentence-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", - "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.3.tgz", + "integrity": "sha512-ZPr4dgTcNkEfcGOMFQyDdJrTU9uQO1nb1cjf+nuzb6FxgMDgKddZOM29qEsB7jvsZSMruLRcL2KfM4ypKpa0LA==", "requires": { - "no-case": "^2.2.0", - "upper-case-first": "^1.1.2" + "no-case": "^3.0.3", + "tslib": "^1.10.0", + "upper-case-first": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "set-blocking": { @@ -4578,24 +5529,24 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.2.tgz", - "integrity": "sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", "dev": true, "requires": { "@sinonjs/commons": "^1.4.0", "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.1", + "@sinonjs/samsam": "^3.3.3", "diff": "^3.5.0", - "lolex": "^4.0.1", - "nise": "^1.4.10", + "lolex": "^4.2.0", + "nise": "^1.5.2", "supports-color": "^5.5.0" } }, "sinon-chai": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.3.0.tgz", - "integrity": "sha512-r2JhDY7gbbmh5z3Q62pNbrjxZdOAjpsqW/8yxAZRSqLZqowmfGZPGUZPFf3UX36NLis0cv8VEM5IJh9HgkSOAA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.4.0.tgz", + "integrity": "sha512-BpVxsjEkGi6XPbDXrgWUe7Cb1ZzIfxKUbu/MmH5RoUnS7AXpKo3aIYIyQUg0FMvlUL05aPt7VZuAdaeQhEnWxg==", "dev": true }, "slash": { @@ -4605,17 +5556,30 @@ "dev": true }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } }, "snake-case": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.3.tgz", + "integrity": "sha512-WM1sIXEO+rsAHBKjGf/6R1HBBcgbncKS08d2Aqec/mrDSpU80SiOU41hO7ny6DToHSyrlwTYzQBIK1FPSx4Y3Q==", "requires": { - "no-case": "^2.2.0" + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "source-map": { @@ -4624,9 +5588,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4634,17 +5598,28 @@ } }, "spawn-wrap": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", - "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", "signal-exit": "^3.0.2", - "which": "^1.3.0" + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "spdx-correct": { @@ -4693,9 +5668,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sqlite3": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.9.tgz", - "integrity": "sha512-IkvzjmsWQl9BuBiM4xKpl5X8WCR4w0AeJHRdobCdXZ8dT/lNc1XS6WqvY35N6+YzIIgzSBeY5prdFObID9F9tA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", + "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", "requires": { "nan": "^2.12.1", "node-pre-gyp": "^0.11.0", @@ -4724,9 +5699,9 @@ } }, "string-argv": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.0.tgz", - "integrity": "sha512-NGZHq3nkSXVtGZXTBjFru3MNfoZyIzN25T7BmvdgnSC0LCJczAGLLMQLyjywSIaAoqSemgLzBRHOsnrHbt60+Q==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "dev": true }, "string-width": { @@ -4748,6 +5723,24 @@ } } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4801,9 +5794,10 @@ "dev": true }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true }, "supports-color": { "version": "5.5.0", @@ -4813,15 +5807,6 @@ "has-flag": "^3.0.0" } }, - "swap-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", - "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", - "requires": { - "lower-case": "^1.1.1", - "upper-case": "^1.1.1" - } - }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -4829,9 +5814,9 @@ "dev": true }, "table": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.5.tgz", - "integrity": "sha512-oGa2Hl7CQjfoaogtrOHEJroOcYILTx7BZWLGsJIlzoWmB2zmguhNfPJZsWPKYek/MgCxfco54gEi31d1uN2hFA==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { "ajv": "^6.10.2", @@ -4852,17 +5837,6 @@ "uri-js": "^4.2.2" } }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -4877,13 +5851,13 @@ } }, "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", + "minipass": "^2.8.6", "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", @@ -4897,22 +5871,42 @@ } } }, + "tarn": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-1.1.5.tgz", + "integrity": "sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g==" + }, "tedious": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tedious/-/tedious-4.2.0.tgz", - "integrity": "sha512-Py59XmvMcYWdjc1qyXDsbBwQE3yM8CJzuDnagjRpwjgndaBQXBULDI3D6OxKClbTNxA3qaLBFd9DjfV+is3AYA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-6.6.2.tgz", + "integrity": "sha512-0Yziuys2h66dVlqMPJpNFciQ/N2VrgwY8o8TXyj4OZBaxrvqRPeMuTKZZVBFTGOjt/J15fR0fX0HBnCHjm7QWA==", "requires": { - "adal-node": "^0.1.22", - "big-number": "1.0.0", - "bl": "^2.0.1", - "depd": "^1.1.2", - "iconv-lite": "^0.4.23", + "@azure/ms-rest-nodeauth": "2.0.2", + "@types/node": "^12.7.11", + "@types/readable-stream": "^2.3.5", + "bl": "^3.0.0", + "depd": "^2.0.0", + "iconv-lite": "^0.5.0", + "jsbi": "^3.1.1", "native-duplexpair": "^1.0.0", "punycode": "^2.1.0", - "readable-stream": "^3.0.3", - "sprintf-js": "^1.1.1" + "readable-stream": "^3.4.0", + "sprintf-js": "^1.1.2" }, "dependencies": { + "@types/node": { + "version": "12.12.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.24.tgz", + "integrity": "sha512-1Ciqv9pqwVtW6FsIUKSZNB82E5Cu1I2bBTj1xuIHXLe/1zYLl3956Nbhg2MzSYHVfl9/rmanjbQIb7LibfCnug==" + }, + "iconv-lite": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz", + "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "readable-stream": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", @@ -4942,15 +5936,14 @@ } }, "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" } }, "text-table": { @@ -4980,15 +5973,6 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "title-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", - "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.0.3" - } - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -5028,16 +6012,10 @@ } } }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, "ts-node": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.3.0.tgz", - "integrity": "sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz", + "integrity": "sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==", "dev": true, "requires": { "arg": "^4.1.0", @@ -5075,6 +6053,11 @@ "tslib": "^1.8.1" } }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5109,12 +6092,21 @@ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true }, - "typeorm": { - "version": "0.2.18", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.18.tgz", - "integrity": "sha512-S553GwtG5ab268+VmaLCN7gKDqFPIzUw0eGMTobJ9yr0Np62Ojfx8j1Oa9bIeh5p7Pz1/kmGabAHoP1MYK05pA==", + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { - "app-root-path": "^2.0.1", + "is-typedarray": "^1.0.0" + } + }, + "typeorm": { + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.22.tgz", + "integrity": "sha512-mDEnMtzRwX4zMYbyzM9xDn7jvGs8hfQ2ymOBq36Zxq1RVM642numwlRbr4W8dU7ZYx8CQUE9rmk+sU0baHD9Rw==", + "requires": { + "app-root-path": "^3.0.0", "buffer": "^5.1.0", "chalk": "^2.4.2", "cli-highlight": "^2.0.0", @@ -5143,26 +6135,53 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "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==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "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.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==" + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz", + "integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==" }, "uglify-js": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.3.tgz", - "integrity": "sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.2.tgz", + "integrity": "sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==", "optional": true, "requires": { "commander": "~2.20.3", @@ -5188,16 +6207,33 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.1.tgz", + "integrity": "sha512-laAsbea9SY5osxrv7S99vH9xAaJKrw5Qpdh4ENRLcaxipjKsiaBwiAsxfa8X5mObKNTQPsupSq0J/VIxsSJe3A==", + "requires": { + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } }, "upper-case-first": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.1.tgz", + "integrity": "sha512-105J8XqQ+9RxW3l9gHZtgve5oaiR9TIwvmZAMAIZWRHe00T21cdvewKORTlOJf/zXW6VukuTshM+HXZNWz7N5w==", "requires": { - "upper-case": "^1.1.1" + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } } }, "uri-js": { @@ -5219,6 +6255,15 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -5272,6 +6317,12 @@ "string-width": "^1.0.2 || 2" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -5313,29 +6364,31 @@ } }, "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", + "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", + "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", "requires": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "util.promisify": "~1.0.0", + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmldom": { "version": "0.1.27", @@ -5358,9 +6411,9 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargonaut": { "version": "1.1.4", @@ -5410,56 +6463,132 @@ } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", + "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==", "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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", + "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^16.1.0" }, "dependencies": { - "cliui": { + "ansi-regex": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "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==", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" } }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -5467,63 +6596,56 @@ } } }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "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.11", - "yargs": "^12.0.5" + "lodash": "^4.17.15", + "yargs": "^13.3.0" }, "dependencies": { - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "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=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "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": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -5533,9 +6655,9 @@ } }, "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/package.json b/package.json index 52324d8..2f950c6 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,15 @@ "version": "0.3.5", "description": "Generates models for TypeORM from existing databases.", "bin": "bin/typeorm-model-generator", + "main": "./dist/src/library.js", + "types": "./dist/src/library.d.ts", "scripts": { "start": "ts-node ./src/index.ts", - "build": "npm run clean && tsc && ncp src/entity.mst dist/src/entity.mst", + "build": "npm run clean && tsc && ncp src/templates/ dist/src/templates/ && ncp package.json dist/package.json", "prepare": "npm run build", "pretest": "tsc --noEmit", - "test": "nyc --reporter=lcov ts-node ./node_modules/mocha/bin/_mocha test/**/*.test.ts -- -R spec --bail", - "posttest": "eslint ./**/*.ts ./src/**/*.ts ./test/**/*.ts", + "test": "nyc --reporter=lcov ts-node ./node_modules/mocha/bin/_mocha test/**/*.test.ts -- --bail", + "posttest": "eslint ./src/**/*.ts ./test/**/*.ts", "clean": "rimraf coverage output dist", "prettier": "prettier --write ./src/*.ts ./src/**/*.ts" }, @@ -24,59 +26,64 @@ }, "homepage": "https://github.com/Kononnable/typeorm-model-generator#readme", "dependencies": { - "change-case": "^3.1.0", + "change-case": "^4.1.1", "fs-extra": "^8.1.0", - "handlebars": "^4.1.2", - "inquirer": "^6.5.0", - "mssql": "^5.1.0", + "handlebars": "^4.5.3", + "inquirer": "^7.0.2", + "mssql": "^6.0.1", "mysql": "^2.17.1", - "pg": "^7.12.0", + "pg": "^7.17.0", + "pluralize": "^8.0.0", + "prettier": "^1.19.1", "reflect-metadata": "^0.1.13", - "sqlite3": "^4.0.9", - "typeorm": "^0.2.18", - "typescript": "^3.5.3", - "yargs": "^13.3.0", - "yn": "^2.0.0" + "sqlite3": "^4.1.1", + "typeorm": "^0.2.22", + "typescript": "^3.7.4", + "yargs": "^15.1.0", + "yn": "^3.1.1" }, "devDependencies": { - "@types/chai": "^4.1.7", - "@types/chai-as-promised": "^7.1.1", - "@types/chai-subset": "^1.3.2", - "@types/fs-extra": "^8.0.0", + "@types/array.prototype.flatmap": "^1.2.0", + "@types/chai": "^4.2.7", + "@types/chai-as-promised": "^7.1.2", + "@types/chai-subset": "^1.3.3", + "@types/eslint": "^6.1.3", + "@types/fs-extra": "^8.0.1", "@types/handlebars": "^4.1.0", "@types/inquirer": "^6.5.0", "@types/mocha": "^5.2.7", - "@types/mssql": "^4.0.16", - "@types/mysql": "^2.15.6", - "@types/node": "^12.6.9", - "@types/oracledb": "^3.1.3", - "@types/pg": "^7.4.14", - "@types/sinon": "^7.0.13", - "@types/sqlite3": "^3.1.5", - "@types/yargs": "^12.0.1", - "@types/yn": "^3.1.0", - "@typescript-eslint/eslint-plugin": "^1.13.0", - "@typescript-eslint/parser": "^1.13.0", - "@typescript-eslint/typescript-estree": "^1.13.0", + "@types/mssql": "^6.0.0", + "@types/mysql": "^2.15.8", + "@types/node": "^13.1.4", + "@types/oracledb": "^4.1.1", + "@types/pg": "^7.14.1", + "@types/pluralize": "0.0.29", + "@types/prettier": "^1.19.0", + "@types/sinon": "^7.5.1", + "@types/sqlite3": "^3.1.6", + "@types/yargs": "^13.0.4", + "@typescript-eslint/eslint-plugin": "^2.14.0", + "@typescript-eslint/parser": "^2.14.0", + "@typescript-eslint/typescript-estree": "^2.14.0", + "array.prototype.flatmap": "^1.2.3", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", - "codecov": "^3.5.0", - "dotenv": "^8.0.0", - "eslint": "^6.1.0", + "codecov": "^3.6.1", + "dotenv": "^8.2.0", + "eslint": "^6.8.0", "eslint-config-airbnb-base": "^14.0.0", - "eslint-config-prettier": "^6.0.0", - "eslint-plugin-import": "^2.18.2", - "husky": "^3.0.2", - "lint-staged": "^9.2.1", - "mocha": "^6.2.0", + "eslint-config-prettier": "^6.9.0", + "eslint-plugin-import": "^2.19.1", + "husky": "^3.1.0", + "lint-staged": "^9.5.0", + "mocha": "^7.0.0", "ncp": "^2.0.0", - "nyc": "^14.1.1", - "prettier": "^1.18.2", - "rimraf": "^2.6.3", - "sinon": "^7.3.2", - "sinon-chai": "^3.3.0", - "ts-node": "^8.3.0" + "nyc": "^15.0.0", + "rimraf": "^3.0.0", + "sinon": "^7.5.0", + "sinon-chai": "^3.4.0", + "ts-node": "^8.5.4" }, "husky": { "hooks": { diff --git a/src/AbstractNamingStrategy.ts b/src/AbstractNamingStrategy.ts deleted file mode 100644 index b568992..0000000 --- a/src/AbstractNamingStrategy.ts +++ /dev/null @@ -1,15 +0,0 @@ -import RelationInfo from "./models/RelationInfo"; -import EntityInfo from "./models/EntityInfo"; -import ColumnInfo from "./models/ColumnInfo"; - -export default abstract class AbstractNamingStrategy { - public abstract relationName( - columnName: string, - relation: RelationInfo, - dbModel: EntityInfo[] - ): string; - - public abstract entityName(entityName: string, entity?: EntityInfo): string; - - public abstract columnName(columnName: string, column?: ColumnInfo): string; -} diff --git a/src/Engine.ts b/src/Engine.ts index 687d26b..026896c 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -1,22 +1,16 @@ -import * as Handlebars from "handlebars"; -import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "./Utils"; import AbstractDriver from "./drivers/AbstractDriver"; import MssqlDriver from "./drivers/MssqlDriver"; import MariaDbDriver from "./drivers/MariaDbDriver"; import IConnectionOptions from "./IConnectionOptions"; import IGenerationOptions from "./IGenerationOptions"; -import EntityInfo from "./models/EntityInfo"; import PostgresDriver from "./drivers/PostgresDriver"; import MysqlDriver from "./drivers/MysqlDriver"; import OracleDriver from "./drivers/OracleDriver"; import SqliteDriver from "./drivers/SqliteDriver"; -import NamingStrategy from "./NamingStrategy"; -import AbstractNamingStrategy from "./AbstractNamingStrategy"; - -import changeCase = require("change-case"); -import fs = require("fs"); -import path = require("path"); +import modelCustomizationPhase from "./ModelCustomization"; +import modelGenerationPhase from "./ModelGeneration"; +import { Entity } from "./models/Entity"; export function createDriver(driverName: string): AbstractDriver { switch (driverName) { @@ -42,8 +36,12 @@ export async function createModelFromDatabase( driver: AbstractDriver, connectionOptions: IConnectionOptions, generationOptions: IGenerationOptions -) { - let dbModel = await dataCollectionPhase(driver, connectionOptions); +): Promise { + let dbModel = await dataCollectionPhase( + driver, + connectionOptions, + generationOptions + ); if (dbModel.length === 0) { TomgUtils.LogError( "Tables not found in selected database. Skipping creation of typeorm model.", @@ -60,439 +58,8 @@ export async function createModelFromDatabase( } export async function dataCollectionPhase( driver: AbstractDriver, - connectionOptions: IConnectionOptions -) { - return driver.GetDataFromServer(connectionOptions); -} - -export function modelCustomizationPhase( - dbModel: EntityInfo[], - generationOptions: IGenerationOptions, - defaultValues: DataTypeDefaults -) { - let namingStrategy: AbstractNamingStrategy; - if ( - generationOptions.customNamingStrategyPath && - generationOptions.customNamingStrategyPath !== "" - ) { - // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires - const req = require(generationOptions.customNamingStrategyPath); - namingStrategy = new req.NamingStrategy(); - } else { - namingStrategy = new NamingStrategy(); - } - let retVal = setRelationId(generationOptions, dbModel); - retVal = applyNamingStrategy(namingStrategy, retVal); - retVal = addImportsAndGenerationOptions(retVal, generationOptions); - retVal = removeColumnDefaultProperties(retVal, defaultValues); - return retVal; -} -function removeColumnDefaultProperties( - dbModel: EntityInfo[], - defaultValues: DataTypeDefaults -) { - if (!defaultValues) { - return dbModel; - } - dbModel.forEach(entity => { - entity.Columns.forEach(column => { - const defVal = defaultValues[column.options.type as any]; - if (defVal) { - if ( - column.options.length && - defVal.length && - column.options.length === defVal.length - ) { - column.options.length = undefined; - } - if ( - column.options.precision && - defVal.precision && - column.options.precision === defVal.precision && - column.options.scale && - defVal.scale && - column.options.scale === defVal.scale - ) { - column.options.precision = undefined; - column.options.scale = undefined; - } - if ( - column.options.width && - defVal.width && - column.options.width === defVal.width - ) { - column.options.width = undefined; - } - } - }); - }); - return dbModel; -} -function addImportsAndGenerationOptions( - dbModel: EntityInfo[], - generationOptions: IGenerationOptions -) { - dbModel.forEach(element => { - element.Imports = []; - element.Columns.forEach(column => { - column.relations.forEach(relation => { - if (element.tsEntityName !== relation.relatedTable) { - element.Imports.push(relation.relatedTable); - } - }); - }); - element.GenerateConstructor = generationOptions.generateConstructor; - element.IsActiveRecord = generationOptions.activeRecord; - element.Imports.filter((elem, index, self) => { - return index === self.indexOf(elem); - }); - if (generationOptions.skipSchema) { - element.Schema = undefined; - element.Database = undefined; - } - }); - return dbModel; -} - -function setRelationId( - generationOptions: IGenerationOptions, - model: EntityInfo[] -) { - if (generationOptions.relationIds) { - model.forEach(ent => { - ent.Columns.forEach(col => { - col.relations.forEach(rel => { - rel.relationIdField = rel.isOwner; - }); - }); - }); - } - return model; -} -export function modelGenerationPhase( connectionOptions: IConnectionOptions, - generationOptions: IGenerationOptions, - databaseModel: EntityInfo[] -) { - createHandlebarsHelpers(generationOptions); - const templatePath = path.resolve(__dirname, "entity.mst"); - const template = fs.readFileSync(templatePath, "UTF-8"); - const resultPath = generationOptions.resultsPath; - if (!fs.existsSync(resultPath)) { - fs.mkdirSync(resultPath); - } - let entitesPath = resultPath; - if (!generationOptions.noConfigs) { - createTsConfigFile(resultPath); - createTypeOrmConfig(resultPath, connectionOptions); - entitesPath = path.resolve(resultPath, "./entities"); - if (!fs.existsSync(entitesPath)) { - fs.mkdirSync(entitesPath); - } - } - const compliedTemplate = Handlebars.compile(template, { - noEscape: true - }); - databaseModel.forEach(element => { - let casedFileName = ""; - switch (generationOptions.convertCaseFile) { - case "camel": - casedFileName = changeCase.camelCase(element.tsEntityName); - break; - case "param": - casedFileName = changeCase.paramCase(element.tsEntityName); - break; - case "pascal": - casedFileName = changeCase.pascalCase(element.tsEntityName); - break; - case "none": - casedFileName = element.tsEntityName; - break; - default: - throw new Error("Unknown case style"); - } - const resultFilePath = path.resolve(entitesPath, `${casedFileName}.ts`); - const rendered = compliedTemplate(element); - fs.writeFileSync(resultFilePath, rendered, { - encoding: "UTF-8", - flag: "w" - }); - }); -} - -function createHandlebarsHelpers(generationOptions: IGenerationOptions) { - Handlebars.registerHelper("curly", open => (open ? "{" : "}")); - Handlebars.registerHelper("toEntityName", str => { - let retStr = ""; - switch (generationOptions.convertCaseEntity) { - case "camel": - retStr = changeCase.camelCase(str); - break; - case "pascal": - retStr = changeCase.pascalCase(str); - break; - case "none": - retStr = str; - break; - default: - throw new Error("Unknown case style"); - } - return retStr; - }); - Handlebars.registerHelper("concat", (stra, strb) => { - return stra + strb; - }); - Handlebars.registerHelper("toFileName", str => { - let retStr = ""; - switch (generationOptions.convertCaseFile) { - case "camel": - retStr = changeCase.camelCase(str); - break; - case "param": - retStr = changeCase.paramCase(str); - break; - case "pascal": - retStr = changeCase.pascalCase(str); - break; - case "none": - retStr = str; - break; - default: - throw new Error("Unknown case style"); - } - return retStr; - }); - Handlebars.registerHelper("printPropertyVisibility", () => - generationOptions.propertyVisibility !== "none" - ? `${generationOptions.propertyVisibility} ` - : "" - ); - Handlebars.registerHelper("toPropertyName", str => { - let retStr = ""; - switch (generationOptions.convertCaseProperty) { - case "camel": - retStr = changeCase.camelCase(str); - break; - case "pascal": - retStr = changeCase.pascalCase(str); - break; - case "none": - retStr = str; - break; - default: - throw new Error("Unknown case style"); - } - return retStr; - }); - Handlebars.registerHelper("toLowerCase", str => str.toLowerCase()); - Handlebars.registerHelper("tolowerCaseFirst", str => - changeCase.lowerCaseFirst(str) - ); - Handlebars.registerHelper("strictMode", () => - generationOptions.strictMode ? generationOptions.strictMode : "" - ); - Handlebars.registerHelper("toLazy", str => { - if (generationOptions.lazy) { - return `Promise<${str}>`; - } - return str; - }); - Handlebars.registerHelper({ - and: (v1, v2) => v1 && v2, - eq: (v1, v2) => v1 === v2, - gt: (v1, v2) => v1 > v2, - gte: (v1, v2) => v1 >= v2, - lt: (v1, v2) => v1 < v2, - lte: (v1, v2) => v1 <= v2, - ne: (v1, v2) => v1 !== v2, - or: (v1, v2) => v1 || v2 - }); -} - -// TODO:Move to mustache template file -function createTsConfigFile(resultPath) { - fs.writeFileSync( - path.resolve(resultPath, "tsconfig.json"), - `{"compilerOptions": { - "lib": ["es5", "es6"], - "target": "es6", - "module": "commonjs", - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "sourceMap": true - }}`, - { encoding: "UTF-8", flag: "w" } - ); -} -function createTypeOrmConfig( - resultPath: string, - connectionOptions: IConnectionOptions -) { - if (connectionOptions.schemaName === "") { - fs.writeFileSync( - path.resolve(resultPath, "ormconfig.json"), - `[ - { - "name": "default", - "type": "${connectionOptions.databaseType}", - "host": "${connectionOptions.host}", - "port": ${connectionOptions.port}, - "username": "${connectionOptions.user}", - "password": "${connectionOptions.password}", - "database": "${connectionOptions.databaseName}", - "synchronize": false, - "entities": [ - "entities/*.js" - ] - } -]`, - { encoding: "UTF-8", flag: "w" } - ); - } else { - fs.writeFileSync( - path.resolve(resultPath, "ormconfig.json"), - `[ - { - "name": "default", - "type": "${connectionOptions.databaseType}", - "host": "${connectionOptions.host}", - "port": ${connectionOptions.port}, - "username": "${connectionOptions.user}", - "password": "${connectionOptions.password}", - "database": "${connectionOptions.databaseName}", - "schema": "${connectionOptions.schemaName}", - "synchronize": false, - "entities": [ - "entities/*.js" - ] - } -]`, - { encoding: "UTF-8", flag: "w" } - ); - } -} -function applyNamingStrategy( - namingStrategy: AbstractNamingStrategy, - dbModel: EntityInfo[] -) { - let retval = changeRelationNames(dbModel); - retval = changeEntityNames(retval); - retval = changeColumnNames(retval); - return retval; - - function changeRelationNames(model: EntityInfo[]) { - model.forEach(entity => { - entity.Columns.forEach(column => { - column.relations.forEach(relation => { - const newName = namingStrategy.relationName( - column.tsName, - relation, - model - ); - model.forEach(entity2 => { - entity2.Columns.forEach(column2 => { - column2.relations.forEach(relation2 => { - if ( - relation2.relatedTable === - entity.tsEntityName && - relation2.ownerColumn === column.tsName - ) { - relation2.ownerColumn = newName; - } - if ( - relation2.relatedTable === - entity.tsEntityName && - relation2.relatedColumn === column.tsName - ) { - relation2.relatedColumn = newName; - } - if (relation.isOwner) { - entity.Indexes.forEach(ind => { - ind.columns - .filter( - col => - col.name === column.tsName - ) - .forEach(col => { - col.name = newName; - }); - }); - } - }); - }); - }); - column.tsName = newName; - }); - }); - }); - return dbModel; - } - - function changeColumnNames(model: EntityInfo[]) { - model.forEach(entity => { - entity.Columns.forEach(column => { - const newName = namingStrategy.columnName( - column.tsName, - column - ); - entity.Indexes.forEach(index => { - index.columns - .filter(column2 => column2.name === column.tsName) - .forEach(column2 => { - column2.name = newName; - }); - }); - model.forEach(entity2 => { - entity2.Columns.forEach(column2 => { - column2.relations - .filter( - relation => - relation.relatedTable === - entity.tsEntityName && - relation.relatedColumn === column.tsName - ) - .forEach(v => { - v.relatedColumn = newName; - }); - column2.relations - .filter( - relation => - relation.relatedTable === - entity.tsEntityName && - relation.ownerColumn === column.tsName - ) - .forEach(v => { - v.ownerColumn = newName; - }); - }); - }); - - column.tsName = newName; - }); - }); - return model; - } - function changeEntityNames(entities: EntityInfo[]) { - entities.forEach(entity => { - const newName = namingStrategy.entityName( - entity.tsEntityName, - entity - ); - entities.forEach(entity2 => { - entity2.Columns.forEach(column => { - column.relations.forEach(relation => { - if (relation.ownerTable === entity.tsEntityName) { - relation.ownerTable = newName; - } - if (relation.relatedTable === entity.tsEntityName) { - relation.relatedTable = newName; - } - }); - }); - }); - entity.tsEntityName = newName; - }); - return entities; - } + generationOptions: IGenerationOptions +): Promise { + return driver.GetDataFromServer(connectionOptions, generationOptions); } diff --git a/src/IConnectionOptions.ts b/src/IConnectionOptions.ts index 3cab302..5aef82d 100644 --- a/src/IConnectionOptions.ts +++ b/src/IConnectionOptions.ts @@ -1,19 +1,35 @@ -export default class IConnectionOptions { - public host: string = ""; +// TODO: change name - public port: number = 0; - - public databaseName: string = ""; - - public user: string = ""; - - public password: string = ""; - - public databaseType: string = ""; - - public schemaName: string = ""; - - public ssl: boolean = false; - - public timeout?: number; +// eslint-disable-next-line @typescript-eslint/interface-name-prefix +export default interface IConnectionOptions { + host: string; + port: number; + databaseName: string; + user: string; + password: string; + databaseType: + | "mssql" + | "postgres" + | "mysql" + | "mariadb" + | "oracle" + | "sqlite"; + schemaName: string; + ssl: boolean; + skipTables: string[]; +} + +export function getDefaultConnectionOptions(): IConnectionOptions { + const connectionOptions: IConnectionOptions = { + host: "127.0.0.1", + port: 0, + databaseName: "", + user: "", + password: "", + databaseType: undefined as any, + schemaName: "", + ssl: false, + skipTables: [] + }; + return connectionOptions; } diff --git a/src/IGenerationOptions.ts b/src/IGenerationOptions.ts index 9b64956..7e3ae8f 100644 --- a/src/IGenerationOptions.ts +++ b/src/IGenerationOptions.ts @@ -1,28 +1,44 @@ -export default class IGenerationOptions { - public resultsPath: string = ""; +import path = require("path"); - public noConfigs: boolean = false; +// TODO: change name - public convertCaseFile: "pascal" | "param" | "camel" | "none" = "none"; - - public convertCaseEntity: "pascal" | "camel" | "none" = "none"; - - public convertCaseProperty: "pascal" | "camel" | "none" = "none"; - - public propertyVisibility: "public" | "protected" | "private" | "none" = - "none"; - - public lazy: boolean = false; - - public activeRecord: boolean = false; - - public generateConstructor: boolean = false; - - public customNamingStrategyPath: string = ""; - - public relationIds: boolean = false; - - public strictMode: false | "?" | "!" = false; - - public skipSchema: boolean = false; +// eslint-disable-next-line @typescript-eslint/interface-name-prefix +export default interface IGenerationOptions { + resultsPath: string; + pluralizeNames: boolean; + noConfigs: boolean; + convertCaseFile: "pascal" | "param" | "camel" | "none"; + convertCaseEntity: "pascal" | "camel" | "none"; + convertCaseProperty: "pascal" | "camel" | "none"; + propertyVisibility: "public" | "protected" | "private" | "none"; + lazy: boolean; + activeRecord: boolean; + generateConstructor: boolean; + customNamingStrategyPath: string; + relationIds: boolean; + strictMode: "none" | "?" | "!"; + skipSchema: boolean; + indexFile: boolean; + exportType: "named" | "default"; +} +export function getDefaultGenerationOptions(): IGenerationOptions { + const generationOptions: IGenerationOptions = { + resultsPath: path.resolve(process.cwd(), "output"), + pluralizeNames: true, + noConfigs: false, + convertCaseFile: "pascal", + convertCaseEntity: "pascal", + convertCaseProperty: "camel", + propertyVisibility: "none", + lazy: false, + activeRecord: false, + generateConstructor: false, + customNamingStrategyPath: "", + relationIds: false, + strictMode: "none", + skipSchema: false, + indexFile: false, + exportType: "named" + }; + return generationOptions; } diff --git a/src/ModelCustomization.ts b/src/ModelCustomization.ts new file mode 100644 index 0000000..46f80d0 --- /dev/null +++ b/src/ModelCustomization.ts @@ -0,0 +1,357 @@ +import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; +import { DefaultNamingStrategy } from "typeorm/naming-strategy/DefaultNamingStrategy"; +import { Entity } from "./models/Entity"; +import IGenerationOptions from "./IGenerationOptions"; +import * as NamingStrategy from "./NamingStrategy"; +import * as TomgUtils from "./Utils"; +import { Relation } from "./models/Relation"; +import { RelationId } from "./models/RelationId"; +import { Column } from "./models/Column"; + +type NamingStrategy = { + enablePluralization: (value: boolean) => void; + relationIdName: ( + relationId: RelationId, + relation: Relation, + owner: Entity + ) => string; + relationName: (relation: Relation, owner: Entity) => string; + columnName: (columnName: string, column?: Column) => string; + entityName: (entityName: string, entity?: Entity) => string; +}; + +export default function modelCustomizationPhase( + dbModel: Entity[], + generationOptions: IGenerationOptions, + defaultValues: DataTypeDefaults +): Entity[] { + const namingStrategy: NamingStrategy = { + enablePluralization: NamingStrategy.enablePluralization, + columnName: NamingStrategy.columnName, + entityName: NamingStrategy.entityName, + relationIdName: NamingStrategy.relationIdName, + relationName: NamingStrategy.relationName + }; + if ( + generationOptions.customNamingStrategyPath && + generationOptions.customNamingStrategyPath !== "" + ) { + // TODO: change form of logging + const req = TomgUtils.requireLocalFile( + generationOptions.customNamingStrategyPath + ) as Partial; + if (req.columnName) { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom naming strategy for column names.` + ); + namingStrategy.columnName = req.columnName; + } else { + console.log( + `[${new Date().toLocaleTimeString()}] Using standard naming strategy for column names.` + ); + } + if (req.entityName) { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom naming strategy for entity names.` + ); + namingStrategy.entityName = req.entityName; + } else { + console.log( + `[${new Date().toLocaleTimeString()}] Using standard naming strategy for entity names.` + ); + } + if (req.relationIdName) { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom naming strategy for relationId field names.` + ); + namingStrategy.relationIdName = req.relationIdName; + } else { + console.log( + `[${new Date().toLocaleTimeString()}] Using standard naming strategy for relationId field names.` + ); + } + if (req.relationName) { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom naming strategy for relation field names.` + ); + namingStrategy.relationName = req.relationName; + } else { + console.log( + `[${new Date().toLocaleTimeString()}] Using standard naming strategy for relation field names.` + ); + } + if (req.enablePluralization) { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom pluralization method for OneToMany, ManyToMany relation field names.` + ); + namingStrategy.enablePluralization = req.enablePluralization; + } else { + console.log( + `[${new Date().toLocaleTimeString()}] Using custom pluralization method for OneToMany, ManyToMany relation field names.` + ); + } + } + namingStrategy.enablePluralization(generationOptions.pluralizeNames); + let retVal = removeIndicesGeneratedByTypeorm(dbModel); + retVal = removeColumnsInRelation(dbModel); + retVal = applyNamingStrategy(namingStrategy, dbModel); + retVal = addImportsAndGenerationOptions(retVal, generationOptions); + retVal = removeColumnDefaultProperties(retVal, defaultValues); + return retVal; +} +function removeIndicesGeneratedByTypeorm(dbModel: Entity[]): Entity[] { + // TODO: Support typeorm CustomNamingStrategy + const namingStrategy = new DefaultNamingStrategy(); + dbModel.forEach(entity => { + entity.indices = entity.indices.filter( + v => + !( + v.name.startsWith(`sqlite_autoindex_`) || + (v.primary && v.name === "PRIMARY") + ) + ); + const primaryColumns = entity.columns + .filter(v => v.primary) + .map(v => v.tscName); + entity.indices = entity.indices.filter( + v => + !( + v.primary && + v.name === + namingStrategy.primaryKeyName( + entity.tscName, + primaryColumns + ) + ) + ); + entity.relations + .filter(v => v.joinColumnOptions) + .forEach(rel => { + const columnNames = rel.joinColumnOptions!.map(v => v.name); + const idxName = namingStrategy.relationConstraintName( + entity.tscName, + columnNames + ); + const fkName = namingStrategy.foreignKeyName( + entity.tscName, + columnNames + ); + entity.indices = entity.indices.filter( + v => v.name !== idxName && v.name !== fkName + ); + }); + }); + return dbModel; +} +function removeColumnsInRelation(dbModel: Entity[]): Entity[] { + dbModel.forEach(entity => { + entity.columns = entity.columns.filter( + col => + !col.isUsedInRelationAsOwner || + col.isUsedInRelationAsReferenced || + entity.indices.some(idx => + idx.columns.some(v => v === col.tscName) + ) || + col.primary + ); + }); + return dbModel; +} +function removeColumnDefaultProperties( + dbModel: Entity[], + defaultValues: DataTypeDefaults +): Entity[] { + if (!defaultValues) { + return dbModel; + } + dbModel.forEach(entity => { + entity.columns.forEach(column => { + const defVal = defaultValues[column.tscType]; + if (defVal) { + if ( + column.options.length && + defVal.length && + column.options.length === defVal.length + ) { + column.options.length = undefined; + } + if ( + column.options.precision && + defVal.precision && + column.options.precision === defVal.precision && + column.options.scale && + defVal.scale && + column.options.scale === defVal.scale + ) { + column.options.precision = undefined; + column.options.scale = undefined; + } + if ( + column.options.width && + defVal.width && + column.options.width === defVal.width + ) { + column.options.width = undefined; + } + } + }); + }); + return dbModel; +} + +function findFileImports(dbModel: Entity[]) { + dbModel.forEach(entity => { + entity.relations.forEach(relation => { + if ( + relation.relatedTable !== entity.tscName && + !entity.fileImports.some(v => v === relation.relatedTable) + ) { + entity.fileImports.push(relation.relatedTable); + } + }); + }); + return dbModel; +} + +function addImportsAndGenerationOptions( + dbModel: Entity[], + generationOptions: IGenerationOptions +): Entity[] { + dbModel = findFileImports(dbModel); + dbModel.forEach(entity => { + entity.relations.forEach(relation => { + if (generationOptions.lazy) { + if (!relation.relationOptions) { + relation.relationOptions = {}; + } + relation.relationOptions.lazy = true; + } + }); + if (generationOptions.skipSchema) { + entity.schema = undefined; + entity.database = undefined; + } + if (generationOptions.activeRecord) { + entity.activeRecord = true; + } + if (generationOptions.generateConstructor) { + entity.generateConstructor = true; + } + }); + return dbModel; +} + +function applyNamingStrategy( + namingStrategy: NamingStrategy, + dbModel: Entity[] +): Entity[] { + let retVal = changeRelationNames(dbModel); + retVal = changeRelationIdNames(retVal); + retVal = changeEntityNames(retVal); + retVal = changeColumnNames(retVal); + return retVal; + + function changeRelationIdNames(model: Entity[]): Entity[] { + model.forEach(entity => { + entity.relationIds.forEach(relationId => { + const oldName = relationId.fieldName; + const relation = entity.relations.find( + v => v.fieldName === relationId.relationField + )!; + let newName = namingStrategy.relationIdName( + relationId, + relation, + entity + ); + newName = TomgUtils.findNameForNewField( + newName, + entity, + oldName + ); + entity.indices.forEach(index => { + index.columns = index.columns.map(column2 => + column2 === oldName ? newName : column2 + ); + }); + + relationId.fieldName = newName; + }); + }); + return dbModel; + } + + function changeRelationNames(model: Entity[]): Entity[] { + model.forEach(entity => { + entity.relations.forEach(relation => { + const oldName = relation.fieldName; + let newName = namingStrategy.relationName(relation, entity); + newName = TomgUtils.findNameForNewField( + newName, + entity, + oldName + ); + + const relatedEntity = model.find( + v => v.tscName === relation.relatedTable + )!; + const relation2 = relatedEntity.relations.find( + v => v.fieldName === relation.relatedField + )!; + + entity.relationIds + .filter(v => v.relationField === oldName) + .forEach(v => { + v.relationField = newName; + }); + + relation.fieldName = newName; + relation2.relatedField = newName; + + if (relation.relationOptions) { + entity.indices.forEach(ind => { + ind.columns.map(column2 => + column2 === oldName ? newName : column2 + ); + }); + } + }); + }); + return dbModel; + } + + function changeColumnNames(model: Entity[]): Entity[] { + model.forEach(entity => { + entity.columns.forEach(column => { + const oldName = column.tscName; + let newName = namingStrategy.columnName(column.tscName, column); + newName = TomgUtils.findNameForNewField( + newName, + entity, + oldName + ); + entity.indices.forEach(index => { + index.columns = index.columns.map(column2 => + column2 === oldName ? newName : column2 + ); + }); + + column.tscName = newName; + }); + }); + return model; + } + function changeEntityNames(entities: Entity[]): Entity[] { + entities.forEach(entity => { + const newName = namingStrategy.entityName(entity.tscName, entity); + entities.forEach(entity2 => { + entity2.relations.forEach(relation => { + if (relation.relatedTable === entity.tscName) { + relation.relatedTable = newName; + } + }); + }); + entity.tscName = newName; + }); + return entities; + } +} diff --git a/src/ModelGeneration.ts b/src/ModelGeneration.ts new file mode 100644 index 0000000..c723447 --- /dev/null +++ b/src/ModelGeneration.ts @@ -0,0 +1,269 @@ +import * as Handlebars from "handlebars"; +import * as Prettier from "prettier"; +import * as changeCase from "change-case"; +import * as fs from "fs"; +import * as path from "path"; +import IConnectionOptions from "./IConnectionOptions"; +import IGenerationOptions from "./IGenerationOptions"; +import { Entity } from "./models/Entity"; +import { Relation } from "./models/Relation"; + +export default function modelGenerationPhase( + connectionOptions: IConnectionOptions, + generationOptions: IGenerationOptions, + databaseModel: Entity[] +): void { + createHandlebarsHelpers(generationOptions); + + const resultPath = generationOptions.resultsPath; + if (!fs.existsSync(resultPath)) { + fs.mkdirSync(resultPath); + } + let entitiesPath = resultPath; + if (!generationOptions.noConfigs) { + createTsConfigFile(resultPath); + createTypeOrmConfig(resultPath, connectionOptions); + entitiesPath = path.resolve(resultPath, "./entities"); + if (!fs.existsSync(entitiesPath)) { + fs.mkdirSync(entitiesPath); + } + } + if (generationOptions.indexFile) { + createIndexFile(databaseModel, generationOptions, entitiesPath); + } + generateModels(databaseModel, generationOptions, entitiesPath); +} + +function generateModels( + databaseModel: Entity[], + generationOptions: IGenerationOptions, + entitiesPath: string +) { + const entityTemplatePath = path.resolve( + __dirname, + "templates", + "entity.mst" + ); + const entityTemplate = fs.readFileSync(entityTemplatePath, "UTF-8"); + const entityCompliedTemplate = Handlebars.compile(entityTemplate, { + noEscape: true + }); + databaseModel.forEach(element => { + let casedFileName = ""; + switch (generationOptions.convertCaseFile) { + case "camel": + casedFileName = changeCase.camelCase(element.tscName); + break; + case "param": + casedFileName = changeCase.paramCase(element.tscName); + break; + case "pascal": + casedFileName = changeCase.pascalCase(element.tscName); + break; + case "none": + casedFileName = element.tscName; + break; + default: + throw new Error("Unknown case style"); + } + const resultFilePath = path.resolve( + entitiesPath, + `${casedFileName}.ts` + ); + const rendered = entityCompliedTemplate(element); + const withImportStatements = removeUnusedImports(rendered); + const formatted = Prettier.format(withImportStatements, { + parser: "typescript" + }); + fs.writeFileSync(resultFilePath, formatted, { + encoding: "UTF-8", + flag: "w" + }); + }); +} + +function createIndexFile( + databaseModel: Entity[], + generationOptions: IGenerationOptions, + entitiesPath: string +) { + const templatePath = path.resolve(__dirname, "templates", "index.mst"); + const template = fs.readFileSync(templatePath, "UTF-8"); + const compliedTemplate = Handlebars.compile(template, { + noEscape: true + }); + const rendered = compliedTemplate({ entities: databaseModel }); + const formatted = Prettier.format(rendered, { + parser: "typescript" + }); + let fileName = "index"; + switch (generationOptions.convertCaseFile) { + case "camel": + fileName = changeCase.camelCase(fileName); + break; + case "param": + fileName = changeCase.paramCase(fileName); + break; + case "pascal": + fileName = changeCase.pascalCase(fileName); + break; + default: + } + const resultFilePath = path.resolve(entitiesPath, `${fileName}.ts`); + fs.writeFileSync(resultFilePath, formatted, { + encoding: "UTF-8", + flag: "w" + }); +} + +function removeUnusedImports(rendered: string) { + const openBracketIndex = rendered.indexOf("{") + 1; + const closeBracketIndex = rendered.indexOf("}"); + const imports = rendered + .substring(openBracketIndex, closeBracketIndex) + .split(","); + const restOfEntityDefinition = rendered.substring(closeBracketIndex); + const distinctImports = imports.filter( + v => + restOfEntityDefinition.indexOf(`@${v}(`) !== -1 || + (v === "BaseEntity" && restOfEntityDefinition.indexOf(v) !== -1) + ); + return `${rendered.substring(0, openBracketIndex)}${distinctImports.join( + "," + )}${restOfEntityDefinition}`; +} + +function createHandlebarsHelpers(generationOptions: IGenerationOptions): void { + Handlebars.registerHelper("json", context => { + const json = JSON.stringify(context); + const withoutQuotes = json.replace(/"([^(")"]+)":/g, "$1:"); + return withoutQuotes.slice(1, withoutQuotes.length - 1); + }); + Handlebars.registerHelper("toEntityName", str => { + let retStr = ""; + switch (generationOptions.convertCaseEntity) { + case "camel": + retStr = changeCase.camelCase(str); + break; + case "pascal": + retStr = changeCase.pascalCase(str); + break; + case "none": + retStr = str; + break; + default: + throw new Error("Unknown case style"); + } + return retStr; + }); + Handlebars.registerHelper("toFileName", str => { + let retStr = ""; + switch (generationOptions.convertCaseFile) { + case "camel": + retStr = changeCase.camelCase(str); + break; + case "param": + retStr = changeCase.paramCase(str); + break; + case "pascal": + retStr = changeCase.pascalCase(str); + break; + case "none": + retStr = str; + break; + default: + throw new Error("Unknown case style"); + } + return retStr; + }); + Handlebars.registerHelper("printPropertyVisibility", () => + generationOptions.propertyVisibility !== "none" + ? `${generationOptions.propertyVisibility} ` + : "" + ); + Handlebars.registerHelper("toPropertyName", str => { + let retStr = ""; + switch (generationOptions.convertCaseProperty) { + case "camel": + retStr = changeCase.camelCase(str); + break; + case "pascal": + retStr = changeCase.pascalCase(str); + break; + case "none": + retStr = str; + break; + default: + throw new Error("Unknown case style"); + } + return retStr; + }); + Handlebars.registerHelper( + "toRelation", + (entityType: string, relationType: Relation["relationType"]) => { + let retVal = entityType; + if (relationType === "ManyToMany" || relationType === "OneToMany") { + retVal = `${retVal}[]`; + } + if (generationOptions.lazy) { + retVal = `Promise<${retVal}>`; + } + return retVal; + } + ); + Handlebars.registerHelper("defaultExport", () => + generationOptions.exportType === "default" ? "default" : "" + ); + Handlebars.registerHelper("localImport", (entityName: string) => + generationOptions.exportType === "default" + ? entityName + : `{${entityName}}` + ); + Handlebars.registerHelper("strictMode", () => + generationOptions.strictMode !== "none" + ? generationOptions.strictMode + : "" + ); + Handlebars.registerHelper({ + and: (v1, v2) => v1 && v2, + eq: (v1, v2) => v1 === v2, + gt: (v1, v2) => v1 > v2, + gte: (v1, v2) => v1 >= v2, + lt: (v1, v2) => v1 < v2, + lte: (v1, v2) => v1 <= v2, + ne: (v1, v2) => v1 !== v2, + or: (v1, v2) => v1 || v2 + }); +} + +function createTsConfigFile(outputPath: string): void { + const templatePath = path.resolve(__dirname, "templates", "tsconfig.mst"); + const template = fs.readFileSync(templatePath, "UTF-8"); + const compliedTemplate = Handlebars.compile(template, { + noEscape: true + }); + const rendered = compliedTemplate({}); + const formatted = Prettier.format(rendered, { parser: "json" }); + const resultFilePath = path.resolve(outputPath, "tsconfig.json"); + fs.writeFileSync(resultFilePath, formatted, { + encoding: "UTF-8", + flag: "w" + }); +} +function createTypeOrmConfig( + outputPath: string, + connectionOptions: IConnectionOptions +): void { + const templatePath = path.resolve(__dirname, "templates", "ormconfig.mst"); + const template = fs.readFileSync(templatePath, "UTF-8"); + const compliedTemplate = Handlebars.compile(template, { + noEscape: true + }); + const rendered = compliedTemplate(connectionOptions); + const formatted = Prettier.format(rendered, { parser: "json" }); + const resultFilePath = path.resolve(outputPath, "ormconfig.json"); + fs.writeFileSync(resultFilePath, formatted, { + encoding: "UTF-8", + flag: "w" + }); +} diff --git a/src/NamingStrategy.ts b/src/NamingStrategy.ts index bcdde51..4836377 100644 --- a/src/NamingStrategy.ts +++ b/src/NamingStrategy.ts @@ -1,74 +1,75 @@ -import AbstractNamingStrategy from "./AbstractNamingStrategy"; -import RelationInfo from "./models/RelationInfo"; -import EntityInfo from "./models/EntityInfo"; +import { plural } from "pluralize"; +import * as changeCase from "change-case"; +import { Relation } from "./models/Relation"; +import { RelationId } from "./models/RelationId"; -import changeCase = require("change-case"); +let pluralize: boolean; -/* eslint-disable class-methods-use-this */ -export default class NamingStrategy extends AbstractNamingStrategy { - public relationName( - columnOldName: string, - relation: RelationInfo, - dbModel: EntityInfo[] - ): string { - const isRelationToMany = relation.isOneToMany || relation.isManyToMany; - const ownerEntity = dbModel.find( - v => v.tsEntityName === relation.ownerTable - )!; - let columnName = changeCase.camelCase(columnOldName); - - if ( - columnName.toLowerCase().endsWith("id") && - !columnName.toLowerCase().endsWith("guid") - ) { - columnName = columnName.substring( - 0, - columnName.toLowerCase().lastIndexOf("id") - ); - } - if (!Number.isNaN(parseInt(columnName[columnName.length - 1], 10))) { - columnName = columnName.substring(0, columnName.length - 1); - } - if (!Number.isNaN(parseInt(columnName[columnName.length - 1], 10))) { - columnName = columnName.substring(0, columnName.length - 1); - } - columnName += isRelationToMany ? "s" : ""; - - if ( - relation.relationType !== "ManyToMany" && - columnOldName !== columnName - ) { - if (ownerEntity.Columns.some(v => v.tsName === columnName)) { - columnName += "_"; - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - columnName.substring( - 0, - columnName.length - i.toString().length - ) + i.toString(); - if ( - ownerEntity.Columns.every( - v => - v.tsName !== columnName || - columnName === columnOldName - ) - ) { - break; - } - } - } - } - - return columnName; - } - - public entityName(entityName: string): string { - return entityName; - } - - public columnName(columnName: string): string { - return columnName; - } +export function enablePluralization(value: boolean) { + pluralize = value; } -/* eslint-enable class-methods-use-this */ +export function relationIdName( + relationId: RelationId, + relation: Relation +): string { + const columnOldName = relationId.fieldName; + + const isRelationToMany = + relation.relationType === "OneToMany" || + relation.relationType === "ManyToMany"; + let newColumnName = changeCase.camelCase( + columnOldName.replace(/[0-9]$/, "") + ); + + if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) { + newColumnName = newColumnName.substring(0, newColumnName.length - 1); + } + if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) { + newColumnName = newColumnName.substring(0, newColumnName.length - 1); + } + if (isRelationToMany && pluralize) { + newColumnName = plural(newColumnName); + } + + return newColumnName; +} + +export function relationName(relation: Relation): string { + const columnOldName = relation.fieldName; + + const isRelationToMany = + relation.relationType === "OneToMany" || + relation.relationType === "ManyToMany"; + let newColumnName = changeCase.camelCase( + columnOldName.replace(/[0-9]$/, "") + ); + + if ( + newColumnName.toLowerCase().endsWith("id") && + !newColumnName.toLowerCase().endsWith("guid") + ) { + newColumnName = newColumnName.substring( + 0, + newColumnName.toLowerCase().lastIndexOf("id") + ); + } + if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) { + newColumnName = newColumnName.substring(0, newColumnName.length - 1); + } + if (!Number.isNaN(parseInt(newColumnName[newColumnName.length - 1], 10))) { + newColumnName = newColumnName.substring(0, newColumnName.length - 1); + } + if (isRelationToMany && pluralize) { + newColumnName = plural(newColumnName); + } + return newColumnName; +} + +export function entityName(oldEntityName: string): string { + return oldEntityName; +} + +export function columnName(oldColumnName: string): string { + return oldColumnName; +} diff --git a/src/Utils.ts b/src/Utils.ts index aebf54d..d121435 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,18 +1,19 @@ +import * as changeCase from "change-case"; +import * as path from "path"; import * as packagejson from "../package.json"; +import { Entity } from "./models/Entity"; export function LogError( errText: string, - isABug: boolean = true, - passedError?: any -) { + isABug = true, + passedError?: string | ErrorConstructor +): void { let errObject = passedError; console.error(errText); - console.error(`Error occured in typeorm-model-generator.`); + console.error(`Error occurred in typeorm-model-generator.`); console.error(`${packageVersion()} node@${process.version}`); console.error( - `If you think this is a bug please open an issue including this log on ${ - (packagejson as any).bugs.url - }` + `If you think this is a bug please open an issue including this log on ${packagejson.bugs.url}` ); if (isABug && !passedError) { errObject = new Error().stack; @@ -21,6 +22,61 @@ export function LogError( console.error(errObject); } } -export function packageVersion() { - return `${(packagejson as any).name}@${(packagejson as any).version}`; +export function packageVersion(): string { + return `${packagejson.name}@${packagejson.version}`; +} +export function findNameForNewField( + _fieldName: string, + entity: Entity, + columnOldName = "" +): string { + let fieldName = _fieldName; + const validNameCondition = () => + (entity.columns.every( + v => + changeCase.camelCase(v.tscName) !== + changeCase.camelCase(fieldName) + ) && + entity.relations.every( + v => + changeCase.camelCase(v.fieldName) !== + changeCase.camelCase(fieldName) + ) && + entity.relationIds.every( + v => + changeCase.camelCase(v.fieldName) !== + changeCase.camelCase(fieldName) + )) || + (columnOldName && + changeCase.camelCase(columnOldName) === + changeCase.camelCase(fieldName)); + if (!validNameCondition()) { + fieldName += "_"; + for ( + let i = 2; + i <= entity.columns.length + entity.relations.length; + i++ + ) { + fieldName = + fieldName.substring(0, fieldName.length - i.toString().length) + + i.toString(); + if (validNameCondition()) { + break; + } + } + } + return fieldName; +} + +export function requireLocalFile(fileName: string): any { + try { + // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires + return require(fileName); + } catch (err) { + if (!path.isAbsolute(fileName)) { + // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires + return require(path.resolve(process.cwd(), fileName)); + } + throw err; + } } diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index a74045a..07a08f3 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -3,14 +3,15 @@ import { WithPrecisionColumnType, WithWidthColumnType } from "typeorm/driver/types/ColumnTypes"; +import { JoinColumnOptions, RelationOptions } from "typeorm"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; -import EntityInfo from "../models/EntityInfo"; -import RelationInfo from "../models/RelationInfo"; -import ColumnInfo from "../models/ColumnInfo"; import IConnectionOptions from "../IConnectionOptions"; -import IndexInfo from "../models/IndexInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; +import { Entity } from "../models/Entity"; +import { RelationInternal } from "../models/RelationInternal"; +import { Relation } from "../models/Relation"; +import IGenerationOptions from "../IGenerationOptions"; +import { Column } from "../models/Column"; export default abstract class AbstractDriver { public abstract standardPort: number; @@ -68,7 +69,8 @@ export default abstract class AbstractDriver { public abstract GetAllTablesQuery: ( schema: string, - dbNames: string + dbNames: string, + tableNames: string[] ) => Promise< { TABLE_SCHEMA: string; @@ -77,131 +79,136 @@ export default abstract class AbstractDriver { }[] >; - public static FindManyToManyRelations(dbModel: EntityInfo[]) { - let retval = dbModel; - const manyToManyEntities = retval.filter( + public static FindManyToManyRelations(dbModel: Entity[]) { + let retVal = dbModel; + const manyToManyEntities = retVal.filter( entity => - entity.Columns.filter(column => { - return ( - column.relations.length === 1 && - !column.relations[0].isOneToMany && - column.relations[0].isOwner - ); - }).length === entity.Columns.length + entity.relations.length === 2 && + entity.relations.every( + v => v.joinColumnOptions && v.relationType !== "ManyToMany" + ) && + entity.relations[0].relatedTable !== + entity.relations[1].relatedTable && + entity.relations[0].joinColumnOptions!.length === + entity.relations[1].joinColumnOptions!.length && + entity.columns.length === + entity.columns.filter(c => c.primary).length && + entity.columns + .map(v => v.tscName) + .filter( + v => + !entity.relations[0] + .joinColumnOptions!.map(x => x.name) + .some(jc => jc === v) && + !entity.relations[1] + .joinColumnOptions!.map(x => x.name) + .some(jc => jc === v) + ).length === 0 ); - manyToManyEntities.forEach(entity => { - const relations: RelationInfo[] = []; - const joinColumnMap = new Map(); + manyToManyEntities.forEach(junctionEntity => { + const firstEntity = dbModel.find( + v => v.tscName === junctionEntity.relations[0].relatedTable + )!; + const secondEntity = dbModel.find( + v => v.tscName === junctionEntity.relations[1].relatedTable + )!; - entity.Columns.forEach(column => { - column.relations.forEach(relation => { - joinColumnMap.set(relation.relatedTable, column.tsName); - relations.push(relation); - }); - }); + const firstRelation = firstEntity.relations.find( + v => v.relatedTable === junctionEntity.tscName + )!; + const secondRelation = secondEntity.relations.find( + v => v.relatedTable === junctionEntity.tscName + )!; - const namesOfRelatedTables = relations - .map(v => v.relatedTable) - .filter((v, i, s) => s.indexOf(v) === i); - const [ - firstRelatedTable, - secondRelatedTable - ] = namesOfRelatedTables; + firstRelation.relationType = "ManyToMany"; + secondRelation.relationType = "ManyToMany"; + firstRelation.relatedTable = secondEntity.tscName; + secondRelation.relatedTable = firstEntity.tscName; - if (namesOfRelatedTables.length === 2) { - const relatedTable1 = retval.find( - v => v.tsEntityName === firstRelatedTable - )!; - relatedTable1.Columns = relatedTable1.Columns.filter( - v => - !v.tsName - .toLowerCase() - .startsWith(entity.tsEntityName.toLowerCase()) - ); - const relatedTable2 = retval.find( - v => v.tsEntityName === namesOfRelatedTables[1] - )!; - relatedTable2.Columns = relatedTable2.Columns.filter( - v => - !v.tsName - .toLowerCase() - .startsWith(entity.tsEntityName.toLowerCase()) - ); - retval = retval.filter(ent => { - return ent.tsEntityName !== entity.tsEntityName; - }); + firstRelation.fieldName = TomgUtils.findNameForNewField( + secondEntity.tscName, + firstEntity + ); + secondRelation.fieldName = TomgUtils.findNameForNewField( + firstEntity.tscName, + secondEntity + ); + firstRelation.relatedField = secondRelation.fieldName; + secondRelation.relatedField = firstRelation.fieldName; - const column1 = new ColumnInfo(); - column1.tsName = secondRelatedTable; - column1.options.name = entity.sqlEntityName; - - const col1Rel = new RelationInfo(); - col1Rel.relatedTable = secondRelatedTable; - col1Rel.relatedColumn = secondRelatedTable; - - col1Rel.relationType = "ManyToMany"; - col1Rel.isOwner = true; - col1Rel.ownerColumn = firstRelatedTable; - - col1Rel.joinColumn = joinColumnMap.get(namesOfRelatedTables[0]); - col1Rel.inverseJoinColumn = joinColumnMap.get( - namesOfRelatedTables[1] - ); - - column1.relations.push(col1Rel); - relatedTable1.Columns.push(column1); - - const column2 = new ColumnInfo(); - column2.tsName = firstRelatedTable; - - const col2Rel = new RelationInfo(); - col2Rel.relatedTable = firstRelatedTable; - col2Rel.relatedColumn = secondRelatedTable; - - col2Rel.joinColumn = joinColumnMap.get(namesOfRelatedTables[1]); - col2Rel.inverseJoinColumn = joinColumnMap.get( - namesOfRelatedTables[0] - ); - - col2Rel.relationType = "ManyToMany"; - col2Rel.isOwner = false; - column2.relations.push(col2Rel); - relatedTable2.Columns.push(column2); + firstRelation.joinTableOptions = { + name: junctionEntity.sqlName, + joinColumns: junctionEntity.relations[0].joinColumnOptions!.map( + (v, i) => { + return { + referencedColumnName: v.referencedColumnName, + name: junctionEntity.relations[0] + .joinColumnOptions![i].name + }; + } + ), + inverseJoinColumns: junctionEntity.relations[1].joinColumnOptions!.map( + (v, i) => { + return { + referencedColumnName: v.referencedColumnName, + name: junctionEntity.relations[1] + .joinColumnOptions![i].name + }; + } + ) + }; + if (junctionEntity.database) { + firstRelation.joinTableOptions.database = + junctionEntity.database; } + if (junctionEntity.schema) { + firstRelation.joinTableOptions.schema = junctionEntity.schema; + } + + firstRelation.relationOptions = undefined; + secondRelation.relationOptions = undefined; + firstRelation.joinColumnOptions = undefined; + secondRelation.joinColumnOptions = undefined; + retVal = retVal.filter(ent => { + return ent.tscName !== junctionEntity.tscName; + }); }); - return retval; + return retVal; } public async GetDataFromServer( - connectionOptons: IConnectionOptions - ): Promise { - let dbModel = [] as EntityInfo[]; - await this.ConnectToServer(connectionOptons); + connectionOptions: IConnectionOptions, + generationOptions: IGenerationOptions + ): Promise { + let dbModel = [] as Entity[]; + await this.ConnectToServer(connectionOptions); const sqlEscapedSchema = AbstractDriver.escapeCommaSeparatedList( - connectionOptons.schemaName + connectionOptions.schemaName ); dbModel = await this.GetAllTables( sqlEscapedSchema, - connectionOptons.databaseName + connectionOptions.databaseName, + connectionOptions.skipTables ); await this.GetCoulmnsFromEntity( dbModel, sqlEscapedSchema, - connectionOptons.databaseName + connectionOptions.databaseName ); await this.GetIndexesFromEntity( dbModel, sqlEscapedSchema, - connectionOptons.databaseName + connectionOptions.databaseName ); + AbstractDriver.FindPrimaryColumnsFromIndexes(dbModel); dbModel = await this.GetRelations( dbModel, sqlEscapedSchema, - connectionOptons.databaseName + connectionOptions.databaseName, + generationOptions ); await this.DisconnectFromServer(); dbModel = AbstractDriver.FindManyToManyRelations(dbModel); - AbstractDriver.FindPrimaryColumnsFromIndexes(dbModel); return dbModel; } @@ -209,225 +216,227 @@ export default abstract class AbstractDriver { public async GetAllTables( schema: string, - dbNames: string - ): Promise { - const response = await this.GetAllTablesQuery(schema, dbNames); - const ret: EntityInfo[] = [] as EntityInfo[]; + dbNames: string, + tableNames: string[] + ): Promise { + const response = await this.GetAllTablesQuery( + schema, + dbNames, + tableNames + ); + const ret: Entity[] = [] as Entity[]; response.forEach(val => { - const ent: EntityInfo = new EntityInfo(); - ent.tsEntityName = val.TABLE_NAME; - ent.sqlEntityName = val.TABLE_NAME; - ent.Schema = val.TABLE_SCHEMA; - ent.Columns = [] as ColumnInfo[]; - ent.Indexes = [] as IndexInfo[]; - ent.Database = dbNames.includes(",") ? val.DB_NAME : ""; - ret.push(ent); + ret.push({ + columns: [], + indices: [], + relations: [], + relationIds: [], + sqlName: val.TABLE_NAME, + tscName: val.TABLE_NAME, + database: dbNames.includes(",") ? val.DB_NAME : "", + schema: val.TABLE_SCHEMA, + fileImports: [] + }); }); return ret; } public static GetRelationsFromRelationTempInfo( - relationsTemp: RelationTempInfo[], - entities: EntityInfo[] + relationsTemp: RelationInternal[], + entities: Entity[], + generationOptions: IGenerationOptions ) { relationsTemp.forEach(relationTmp => { - if (relationTmp.ownerColumnsNames.length > 1) { - const relatedTable = entities.find( - entity => entity.tsEntityName === relationTmp.ownerTable - )!; - if ( - relatedTable.Columns.length !== - relationTmp.ownerColumnsNames.length * 2 - ) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} wasn't generated correctly - complex relationships aren't supported yet.`, - false - ); - return; - } - - const secondRelation = relationsTemp.find( - relation => - relation.ownerTable === relatedTable.tsEntityName && - relation.referencedTable !== relationTmp.referencedTable - )!; - if (!secondRelation) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} wasn't generated correctly - complex relationships aren't supported yet.`, - false - ); - return; - } - } - const ownerEntity = entities.find( - entitity => entitity.tsEntityName === relationTmp.ownerTable + entity => entity.tscName === relationTmp.ownerTable.tscName ); if (!ownerEntity) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.` + `Relation between tables ${relationTmp.ownerTable.sqlName} and ${relationTmp.relatedTable.sqlName} didn't found entity model ${relationTmp.ownerTable.sqlName}.` ); return; } const referencedEntity = entities.find( - entitity => - entitity.tsEntityName === relationTmp.referencedTable + entity => entity.tscName === relationTmp.relatedTable.tscName ); if (!referencedEntity) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.` + `Relation between tables ${relationTmp.ownerTable.sqlName} and ${relationTmp.relatedTable.sqlName} didn't found entity model ${relationTmp.relatedTable.sqlName}.` ); return; } + + const ownerColumns: Column[] = []; + const relatedColumns: Column[] = []; for ( let relationColumnIndex = 0; - relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex < relationTmp.ownerColumns.length; relationColumnIndex++ ) { - const ownerColumn = ownerEntity.Columns.find( + const ownerColumn = ownerEntity.columns.find( column => - column.tsName === - relationTmp.ownerColumnsNames[relationColumnIndex] + column.tscName === + relationTmp.ownerColumns[relationColumnIndex] ); if (!ownerColumn) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.` + `Relation between tables ${relationTmp.ownerTable.sqlName} and ${relationTmp.relatedTable.sqlName} didn't found entity column ${relationTmp.ownerTable.sqlName}.${ownerColumn}.` ); return; } - const relatedColumn = referencedEntity.Columns.find( + const relatedColumn = referencedEntity.columns.find( column => - column.tsName === - relationTmp.referencedColumnsNames[relationColumnIndex] + column.tscName === + relationTmp.relatedColumns[relationColumnIndex] ); if (!relatedColumn) { TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.` + `Relation between tables ${relationTmp.ownerTable.sqlName} and ${relationTmp.relatedTable.sqlName} didn't found entity column ${relationTmp.relatedTable.sqlName}.${relatedColumn}.` ); return; } - let isOneToMany: boolean; - isOneToMany = false; - const index = ownerEntity.Indexes.find( - ind => - ind.isUnique && - ind.columns.length === 1 && - ind.columns[0].name === ownerColumn!.tsName + ownerColumns.push(ownerColumn); + relatedColumns.push(relatedColumn); + } + let isOneToMany: boolean; + isOneToMany = false; + const index = ownerEntity.indices.find( + ind => + ind.options.unique && + ind.columns.length === ownerColumns.length && + ownerColumns.every(ownerColumn => + ind.columns.some(col => col === ownerColumn.tscName) + ) + ); + isOneToMany = !index; + + ownerColumns.forEach(column => { + column.isUsedInRelationAsOwner = true; + }); + relatedColumns.forEach(column => { + column.isUsedInRelationAsReferenced = true; + }); + let fieldName = ""; + if (ownerColumns.length === 1) { + fieldName = TomgUtils.findNameForNewField( + ownerColumns[0].tscName, + ownerEntity ); - isOneToMany = !index; + } else { + fieldName = TomgUtils.findNameForNewField( + relationTmp.relatedTable.tscName, + ownerEntity + ); + } - const ownerRelation = new RelationInfo(); - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.tsName.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.relationType = isOneToMany - ? "ManyToOne" - : "OneToOne"; + const relationOptions: RelationOptions = { + onDelete: relationTmp.onDelete, + onUpdate: relationTmp.onUpdate + }; - let columnName = ownerEntity.tsEntityName; - if ( - referencedEntity.Columns.some(v => v.tsName === columnName) - ) { - columnName += "_"; - for (let i = 2; i <= referencedEntity.Columns.length; i++) { - columnName = - columnName.substring( - 0, - columnName.length - i.toString().length - ) + i.toString(); - if ( - referencedEntity.Columns.every( - v => v.tsName !== columnName - ) - ) { - break; - } + const ownerRelation: Relation = { + fieldName, + relatedField: TomgUtils.findNameForNewField( + relationTmp.ownerTable.tscName, + relationTmp.relatedTable + ), + joinColumnOptions: relationTmp.ownerColumns.map((v, idx) => { + const retVal: Required = { + name: v, + referencedColumnName: relationTmp.relatedColumns[idx] + }; + return retVal; + }), + relatedTable: relationTmp.relatedTable.tscName, + relationType: isOneToMany ? "ManyToOne" : "OneToOne" + }; + if (JSON.stringify(relationOptions) !== "{}") { + ownerRelation.relationOptions = relationOptions; + } + const relatedRelation: Relation = { + fieldName: ownerRelation.relatedField, + relatedField: ownerRelation.fieldName, + relatedTable: relationTmp.ownerTable.tscName, + relationType: isOneToMany ? "OneToMany" : "OneToOne" + }; + + ownerEntity.relations.push(ownerRelation); + relationTmp.relatedTable.relations.push(relatedRelation); + + if (generationOptions.relationIds && ownerColumns.length === 1) { + let relationIdFieldName = ""; + relationIdFieldName = TomgUtils.findNameForNewField( + ownerColumns[0].tscName, + ownerEntity + ); + + let fieldType = ""; + if (isOneToMany) { + fieldType = `${ownerColumns[0].tscType}[]`; + } else { + fieldType = ownerColumns[0].tscType; + if (ownerColumns[0].options.nullable) { + fieldType += " | null"; } } - ownerRelation.ownerColumn = columnName; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - const col = new ColumnInfo(); - col.tsName = columnName; - const referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.tsName; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.tsName; - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - const col = new ColumnInfo(); - col.tsName = columnName; - const referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = - relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = - relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.tsName; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.tsName; - referencedRelation.relationType = "OneToOne"; - referencedEntity.Columns.push(col); - } + ownerEntity.relationIds.push({ + fieldName: relationIdFieldName, + fieldType, + relationField: ownerRelation.fieldName + }); + // TODO: RelationId on ManyToMany } }); return entities; } public abstract async GetCoulmnsFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise; + ): Promise; public abstract async GetIndexesFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise; + ): Promise; public abstract async GetRelations( - entities: EntityInfo[], + entities: Entity[], schema: string, - dbNames: string - ): Promise; + dbNames: string, + generationOptions: IGenerationOptions + ): Promise; - public static FindPrimaryColumnsFromIndexes(dbModel: EntityInfo[]) { + public static FindPrimaryColumnsFromIndexes(dbModel: Entity[]) { dbModel.forEach(entity => { - const primaryIndex = entity.Indexes.find(v => v.isPrimaryKey); - entity.Columns.filter( - col => - primaryIndex && - primaryIndex.columns.some( - cIndex => cIndex.name === col.tsName - ) - ).forEach(col => { - // eslint-disable-next-line no-param-reassign - col.options.primary = true; - }); + const primaryIndex = entity.indices.find(v => v.primary); + entity.columns + .filter( + col => + primaryIndex && + primaryIndex.columns.some( + cIndex => cIndex === col.tscName + ) + ) + .forEach(col => { + // eslint-disable-next-line no-param-reassign + col.primary = true; + if ( + primaryIndex!.columns.length === 1 && + col.options.unique + ) { + delete col.options.unique; + } + }); if ( - !entity.Columns.some(v => { - return !!v.options.primary; + !entity.columns.some(v => { + return !!v.primary; }) ) { - TomgUtils.LogError( - `Table ${entity.tsEntityName} has no PK.`, - false - ); + TomgUtils.LogError(`Table ${entity.tscName} has no PK.`, false); } }); } diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 2aed97b..3e9e1ab 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -4,12 +4,12 @@ import * as TypeormDriver from "typeorm/driver/sqlserver/SqlServerDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../models/EntityInfo"; -import ColumnInfo from "../models/ColumnInfo"; -import IndexInfo from "../models/IndexInfo"; -import IndexColumnInfo from "../models/IndexColumnInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; +import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import IGenerationOptions from "../IGenerationOptions"; +import { RelationInternal } from "../models/RelationInternal"; export default class MssqlDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.SqlServerDriver({ @@ -24,26 +24,36 @@ export default class MssqlDriver extends AbstractDriver { private Connection: MSSQL.ConnectionPool; - public GetAllTablesQuery = async (schema: string, dbNames: string) => { + public GetAllTablesQuery = async ( + schema: string, + dbNames: string, + tableNames: string[] + ) => { const request = new MSSQL.Request(this.Connection); + const tableCondition = + tableNames.length > 0 + ? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')` + : ""; const response: { TABLE_SCHEMA: string; TABLE_NAME: string; DB_NAME: string; - }[] = (await request.query( - `SELECT TABLE_SCHEMA,TABLE_NAME, table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES + }[] = ( + await request.query( + `SELECT TABLE_SCHEMA,TABLE_NAME, table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList( - dbNames - )})` - )).recordset; + dbNames + )}) ${tableCondition}` + ) + ).recordset; return response; }; public async GetCoulmnsFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise { + ): Promise { const request = new MSSQL.Request(this.Connection); const response: { TABLE_NAME: string; @@ -56,140 +66,145 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG NUMERIC_SCALE: number; IsIdentity: number; IsUnique: number; - }[] = (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE, - DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE, - COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity, - (SELECT count(*) - FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc - inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu - on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME - where - tc.CONSTRAINT_TYPE = 'UNIQUE' - and tc.TABLE_NAME = c.TABLE_NAME - and cu.COLUMN_NAME = c.COLUMN_NAME - and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique - FROM INFORMATION_SCHEMA.COLUMNS c - where TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList( - dbNames - )}) - order by ordinal_position`)).recordset; + }[] = ( + await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE, + DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE, + COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity, + (SELECT count(*) + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc + inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu + on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME + where + tc.CONSTRAINT_TYPE = 'UNIQUE' + and tc.TABLE_NAME = c.TABLE_NAME + and cu.COLUMN_NAME = c.COLUMN_NAME + and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique + FROM INFORMATION_SCHEMA.COLUMNS c + where TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList( + dbNames + )}) + order by ordinal_position`) + ).recordset; entities.forEach(ent => { response .filter(filterVal => { - return filterVal.TABLE_NAME === ent.tsEntityName; + return filterVal.TABLE_NAME === ent.tscName; }) .forEach(resp => { - const colInfo: ColumnInfo = new ColumnInfo(); - colInfo.tsName = resp.COLUMN_NAME; - colInfo.options.name = resp.COLUMN_NAME; - colInfo.options.nullable = resp.IS_NULLABLE === "YES"; - colInfo.options.generated = resp.IsIdentity === 1; - colInfo.options.unique = resp.IsUnique === 1; - colInfo.options.default = MssqlDriver.ReturnDefaultValueFunction( + const tscName = resp.COLUMN_NAME; + const options: Column["options"] = { + name: resp.COLUMN_NAME + }; + if (resp.IS_NULLABLE === "YES") options.nullable = true; + if (resp.IsUnique === 1) options.unique = true; + const generated = resp.IsIdentity === 1 ? true : undefined; + const defaultValue = MssqlDriver.ReturnDefaultValueFunction( resp.COLUMN_DEFAULT ); - colInfo.options.type = resp.DATA_TYPE as any; + const columnType = resp.DATA_TYPE; + let tscType = ""; switch (resp.DATA_TYPE) { case "bigint": - colInfo.tsType = "string"; + tscType = "string"; break; case "bit": - colInfo.tsType = "boolean"; + tscType = "boolean"; break; case "decimal": - colInfo.tsType = "number"; + tscType = "number"; break; case "int": - colInfo.tsType = "number"; + tscType = "number"; break; case "money": - colInfo.tsType = "number"; + tscType = "number"; break; case "numeric": - colInfo.tsType = "number"; + tscType = "number"; break; case "smallint": - colInfo.tsType = "number"; + tscType = "number"; break; case "smallmoney": - colInfo.tsType = "number"; + tscType = "number"; break; case "tinyint": - colInfo.tsType = "number"; + tscType = "number"; break; case "float": - colInfo.tsType = "number"; + tscType = "number"; break; case "real": - colInfo.tsType = "number"; + tscType = "number"; break; case "date": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "datetime2": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "datetime": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "datetimeoffset": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "smalldatetime": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "time": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "char": - colInfo.tsType = "string"; + tscType = "string"; break; case "text": - colInfo.tsType = "string"; + tscType = "string"; break; case "varchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "nchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "ntext": - colInfo.tsType = "string"; + tscType = "string"; break; case "nvarchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "binary": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "image": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "varbinary": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "hierarchyid": - colInfo.tsType = "string"; + tscType = "string"; break; case "sql_variant": - colInfo.tsType = "string"; + tscType = "string"; break; case "timestamp": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "uniqueidentifier": - colInfo.tsType = "string"; + tscType = "string"; break; case "xml": - colInfo.tsType = "string"; + tscType = "string"; break; case "geometry": - colInfo.tsType = "string"; + tscType = "string"; break; case "geography": - colInfo.tsType = "string"; + tscType = "string"; break; default: + tscType = "NonNullable"; TomgUtils.LogError( `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` ); @@ -198,36 +213,42 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG if ( this.ColumnTypesWithPrecision.some( - v => v === colInfo.options.type + v => v === columnType ) ) { - colInfo.options.precision = resp.NUMERIC_PRECISION; - colInfo.options.scale = resp.NUMERIC_SCALE; + if (resp.NUMERIC_PRECISION !== null) { + options.precision = resp.NUMERIC_PRECISION; + } + if (resp.NUMERIC_SCALE !== null) { + options.scale = resp.NUMERIC_SCALE; + } } if ( - this.ColumnTypesWithLength.some( - v => v === colInfo.options.type - ) + this.ColumnTypesWithLength.some(v => v === columnType) ) { - colInfo.options.length = + options.length = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : undefined; } - - if (colInfo.options.type) { - ent.Columns.push(colInfo); - } + ent.columns.push({ + generated, + type: columnType, + default: defaultValue, + options, + tscName, + tscType + }); }); }); return entities; } public async GetIndexesFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise { + ): Promise { const request = new MSSQL.Request(this.Connection); const response: { TableName: string; @@ -245,63 +266,64 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG ColumnName: string; is_unique: boolean; is_primary_key: boolean; - }[] = (await request.query(`SELECT - TableName = t.name, - IndexName = ind.name, - ColumnName = col.name, - ind.is_unique, - ind.is_primary_key - FROM - sys.indexes ind - INNER JOIN - sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id - INNER JOIN - sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id - INNER JOIN - sys.tables t ON ind.object_id = t.object_id - INNER JOIN - sys.schemas s on s.schema_id=t.schema_id - WHERE - t.is_ms_shipped = 0 and s.name in (${schema}) - ORDER BY - t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset; + }[] = ( + await request.query(`SELECT + TableName = t.name, + IndexName = ind.name, + ColumnName = col.name, + ind.is_unique, + ind.is_primary_key + FROM + sys.indexes ind + INNER JOIN + sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id + INNER JOIN + sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id + INNER JOIN + sys.tables t ON ind.object_id = t.object_id + INNER JOIN + sys.schemas s on s.schema_id=t.schema_id + WHERE + t.is_ms_shipped = 0 and s.name in (${schema}) + ORDER BY + t.name, ind.name, ind.index_id, ic.key_ordinal;`) + ).recordset; response.push(...resp); }) ); + entities.forEach(ent => { - response - .filter(filterVal => filterVal.TableName === ent.tsEntityName) - .forEach(resp => { - let indexInfo: IndexInfo = {} as IndexInfo; - const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - if ( - ent.Indexes.filter(filterVal => { - return filterVal.name === resp.IndexName; - }).length > 0 - ) { - [indexInfo] = ent.Indexes.filter(filterVal => { - return filterVal.name === resp.IndexName; - }); - } else { - indexInfo.columns = [] as IndexColumnInfo[]; - indexInfo.name = resp.IndexName; - indexInfo.isUnique = resp.is_unique; - indexInfo.isPrimaryKey = resp.is_primary_key; - ent.Indexes.push(indexInfo); - } - indexColumnInfo.name = resp.ColumnName; - indexInfo.columns.push(indexColumnInfo); + const entityIndices = response.filter( + filterVal => filterVal.TableName === ent.tscName + ); + const indexNames = new Set(entityIndices.map(v => v.IndexName)); + indexNames.forEach(indexName => { + const records = entityIndices.filter( + v => v.IndexName === indexName + ); + const indexInfo: Index = { + columns: [], + options: {}, + name: records[0].IndexName + }; + if (records[0].is_primary_key) indexInfo.primary = true; + if (records[0].is_unique) indexInfo.options.unique = true; + records.forEach(record => { + indexInfo.columns.push(record.ColumnName); }); + ent.indices.push(indexInfo); + }); }); return entities; } public async GetRelations( - entities: EntityInfo[], + entities: Entity[], schema: string, - dbNames: string - ): Promise { + dbNames: string, + generationOptions: IGenerationOptions + ): Promise { const request = new MSSQL.Request(this.Connection); const response: { TableWithForeignKey: string; @@ -325,78 +347,93 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; objectId: number; - }[] = (await request.query(`select - parentTable.name as TableWithForeignKey, - fkc.constraint_column_id as FK_PartNo, - parentColumn.name as ForeignKeyColumn, - referencedTable.name as TableReferenced, - referencedColumn.name as ForeignKeyColumnReferenced, - fk.delete_referential_action_desc as onDelete, - fk.update_referential_action_desc as onUpdate, - fk.object_id as objectId -from - sys.foreign_keys fk -inner join - sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id -inner join - sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id -inner join - sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id -inner join - sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id -inner join - sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id -inner join - sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id -where - fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema}) -order by - TableWithForeignKey, FK_PartNo`)).recordset; + }[] = ( + await request.query(`select + parentTable.name as TableWithForeignKey, + fkc.constraint_column_id as FK_PartNo, + parentColumn.name as ForeignKeyColumn, + referencedTable.name as TableReferenced, + referencedColumn.name as ForeignKeyColumnReferenced, + fk.delete_referential_action_desc as onDelete, + fk.update_referential_action_desc as onUpdate, + fk.object_id as objectId + from + sys.foreign_keys fk + inner join + sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id + inner join + sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id + inner join + sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id + inner join + sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id + inner join + sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id + inner join + sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id + where + fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema}) + order by + TableWithForeignKey, FK_PartNo`) + ).recordset; response.push(...resp); }) ); - const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - response.forEach(resp => { - let rels = relationsTemp.find( - val => val.objectId === resp.objectId + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.objectId)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.objectId === relationId); + const ownerTable = entities.find( + v => v.sqlName === rows[0].TableWithForeignKey ); - if (rels === undefined) { - rels = {} as RelationTempInfo; - rels.ownerColumnsNames = []; - rels.referencedColumnsNames = []; - switch (resp.onDelete) { - case "NO_ACTION": - rels.actionOnDelete = null; - break; - case "SET_NULL": - rels.actionOnDelete = "SET NULL"; - break; - default: - rels.actionOnDelete = resp.onDelete; - break; - } - switch (resp.onUpdate) { - case "NO_ACTION": - rels.actionOnUpdate = null; - break; - case "SET_NULL": - rels.actionOnUpdate = "SET NULL"; - break; - default: - rels.actionOnUpdate = resp.onUpdate; - break; - } - rels.objectId = resp.objectId; - rels.ownerTable = resp.TableWithForeignKey; - rels.referencedTable = resp.TableReferenced; - relationsTemp.push(rels); + const relatedTable = entities.find( + v => v.sqlName === rows[0].TableReferenced + ); + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${rows[0].TableWithForeignKey} and ${rows[0].TableReferenced} wasn't found in entity model.`, + true + ); + return; } - rels.ownerColumnsNames.push(resp.ForeignKeyColumn); - rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced); + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + switch (rows[0].onDelete) { + case "NO_ACTION": + break; + case "SET_NULL": + internal.onDelete = "SET NULL"; + break; + default: + internal.onDelete = rows[0].onDelete; + break; + } + switch (rows[0].onUpdate) { + case "NO_ACTION": + break; + case "SET_NULL": + internal.onUpdate = "SET NULL"; + break; + default: + internal.onUpdate = rows[0].onUpdate; + break; + } + rows.forEach(row => { + internal.ownerColumns.push(row.ForeignKeyColumn); + internal.relatedColumns.push(row.ForeignKeyColumnReferenced); + }); + relationsTemp.push(internal); }); + const retVal = MssqlDriver.GetRelationsFromRelationTempInfo( relationsTemp, - entities + entities, + generationOptions ); return retVal; } @@ -417,7 +454,7 @@ order by }, password: connectionOptons.password, port: connectionOptons.port, - requestTimeout: connectionOptons.timeout, + requestTimeout: 60 * 60 * 1000, server: connectionOptons.host, user: connectionOptons.user }; @@ -465,10 +502,10 @@ order by private static ReturnDefaultValueFunction( defVal: string | null - ): string | null { + ): string | undefined { let defaultValue = defVal; if (!defaultValue) { - return null; + return undefined; } if (defaultValue.startsWith("(") && defaultValue.endsWith(")")) { defaultValue = defaultValue.slice(1, -1); diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 9878739..59a5e33 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -4,12 +4,12 @@ import * as TypeormDriver from "typeorm/driver/mysql/MysqlDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../models/EntityInfo"; -import ColumnInfo from "../models/ColumnInfo"; -import IndexInfo from "../models/IndexInfo"; -import IndexColumnInfo from "../models/IndexColumnInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; +import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import { RelationInternal } from "../models/RelationInternal"; +import IGenerationOptions from "../IGenerationOptions"; export default class MysqlDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.MysqlDriver({ @@ -26,7 +26,15 @@ export default class MysqlDriver extends AbstractDriver { private Connection: MYSQL.Connection; - public GetAllTablesQuery = async (schema: string, dbNames: string) => { + public GetAllTablesQuery = async ( + schema: string, + dbNames: string, + tableNames: string[] + ) => { + const tableCondition = + tableNames.length > 0 + ? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')` + : ""; const response = this.ExecQuery<{ TABLE_SCHEMA: string; TABLE_NAME: string; @@ -36,15 +44,15 @@ export default class MysqlDriver extends AbstractDriver { WHERE table_type='BASE TABLE' AND table_schema IN (${MysqlDriver.escapeCommaSeparatedList( dbNames - )})`); + )}) ${tableCondition}`); return response; }; public async GetCoulmnsFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise { + ): Promise { const response = await this.ExecQuery<{ TABLE_NAME: string; COLUMN_NAME: string; @@ -52,8 +60,8 @@ export default class MysqlDriver extends AbstractDriver { IS_NULLABLE: string; DATA_TYPE: string; CHARACTER_MAXIMUM_LENGTH: number; - NUMERIC_PRECISION: number; - NUMERIC_SCALE: number; + NUMERIC_PRECISION: number | null; + NUMERIC_SCALE: number | null; IsIdentity: number; COLUMN_TYPE: string; COLUMN_KEY: string; @@ -66,152 +74,170 @@ export default class MysqlDriver extends AbstractDriver { order by ordinal_position`); entities.forEach(ent => { response - .filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName) + .filter(filterVal => filterVal.TABLE_NAME === ent.tscName) .forEach(resp => { - const colInfo: ColumnInfo = new ColumnInfo(); - colInfo.tsName = resp.COLUMN_NAME; - colInfo.options.name = resp.COLUMN_NAME; - colInfo.options.nullable = resp.IS_NULLABLE === "YES"; - colInfo.options.generated = resp.IsIdentity === 1; - colInfo.options.unique = resp.COLUMN_KEY === "UNI"; - colInfo.options.default = MysqlDriver.ReturnDefaultValueFunction( - resp.COLUMN_DEFAULT - ); - colInfo.options.type = resp.DATA_TYPE as any; - colInfo.options.unsigned = resp.COLUMN_TYPE.endsWith( - " unsigned" + const tscName = resp.COLUMN_NAME; + let tscType = ""; + const options: Column["options"] = { + name: resp.COLUMN_NAME + }; + const generated = resp.IsIdentity === 1 ? true : undefined; + const defaultValue = MysqlDriver.ReturnDefaultValueFunction( + resp.COLUMN_DEFAULT, + resp.DATA_TYPE ); + let columnType = resp.DATA_TYPE; + if (resp.IS_NULLABLE === "YES") options.nullable = true; + if (resp.COLUMN_KEY === "UNI") options.unique = true; + if (resp.COLUMN_TYPE.endsWith(" unsigned")) + options.unsigned = true; switch (resp.DATA_TYPE) { case "int": - colInfo.tsType = "number"; + tscType = "number"; break; case "bit": if (resp.COLUMN_TYPE === "bit(1)") { - colInfo.options.width = 1; - colInfo.tsType = "boolean"; + tscType = "boolean"; } else { - colInfo.tsType = "number"; + tscType = "number"; } break; case "tinyint": if (resp.COLUMN_TYPE === "tinyint(1)") { - colInfo.options.width = 1; - colInfo.tsType = "boolean"; + options.width = 1; + tscType = "boolean"; } else { - colInfo.tsType = "number"; + tscType = "number"; } break; case "smallint": - colInfo.tsType = "number"; + tscType = "number"; break; case "mediumint": - colInfo.tsType = "number"; + tscType = "number"; break; case "bigint": - colInfo.tsType = "string"; + tscType = "string"; break; case "float": - colInfo.tsType = "number"; + tscType = "number"; break; case "double": - colInfo.tsType = "number"; + tscType = "number"; break; case "decimal": - colInfo.tsType = "string"; + tscType = "string"; break; case "date": - colInfo.tsType = "string"; + tscType = "string"; break; case "datetime": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "timestamp": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "time": - colInfo.tsType = "string"; + tscType = "string"; break; case "year": - colInfo.tsType = "number"; + tscType = "number"; break; case "char": - colInfo.tsType = "string"; + tscType = "string"; break; case "varchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "blob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "text": - colInfo.tsType = "string"; + tscType = "string"; break; case "tinyblob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "tinytext": - colInfo.tsType = "string"; + tscType = "string"; break; case "mediumblob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "mediumtext": - colInfo.tsType = "string"; + tscType = "string"; break; case "longblob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "longtext": - colInfo.tsType = "string"; + tscType = "string"; break; case "enum": - colInfo.tsType = resp.COLUMN_TYPE.substring( + tscType = resp.COLUMN_TYPE.substring( 5, resp.COLUMN_TYPE.length - 1 ) .replace(/'/gi, '"') .replace(/","/gi, '" | "'); - colInfo.options.enum = resp.COLUMN_TYPE.substring( + options.enum = resp.COLUMN_TYPE.substring( 5, resp.COLUMN_TYPE.length - 1 - ).replace(/'/gi, '"'); + ) + .replace(/'/gi, "") + .split(","); + break; + case "set": + tscType = `(${resp.COLUMN_TYPE.substring( + 4, + resp.COLUMN_TYPE.length - 1 + ) + .replace(/'/gi, '"') + .replace(/","/gi, '" | "')})[]`; + options.enum = resp.COLUMN_TYPE.substring( + 4, + resp.COLUMN_TYPE.length - 1 + ) + .replace(/'/gi, "") + .split(","); break; case "json": - colInfo.tsType = "object"; + tscType = "object"; break; case "binary": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "varbinary": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "geometry": - colInfo.tsType = "string"; + tscType = "string"; break; case "point": - colInfo.tsType = "string"; + tscType = "string"; break; case "linestring": - colInfo.tsType = "string"; + tscType = "string"; break; case "polygon": - colInfo.tsType = "string"; + tscType = "string"; break; case "multipoint": - colInfo.tsType = "string"; + tscType = "string"; break; case "multilinestring": - colInfo.tsType = "string"; + tscType = "string"; break; case "multipolygon": - colInfo.tsType = "string"; + tscType = "string"; break; case "geometrycollection": case "geomcollection": - colInfo.options.type = "geometrycollection"; - colInfo.tsType = "string"; + columnType = "geometrycollection"; + tscType = "string"; break; default: + tscType = "NonNullable"; TomgUtils.LogError( `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` ); @@ -219,48 +245,53 @@ export default class MysqlDriver extends AbstractDriver { } if ( this.ColumnTypesWithPrecision.some( - v => v === colInfo.options.type + v => v === columnType ) ) { - colInfo.options.precision = resp.NUMERIC_PRECISION; - colInfo.options.scale = resp.NUMERIC_SCALE; + if (resp.NUMERIC_PRECISION !== null) { + options.precision = resp.NUMERIC_PRECISION; + } + if (resp.NUMERIC_SCALE !== null) { + options.scale = resp.NUMERIC_SCALE; + } } if ( - this.ColumnTypesWithLength.some( - v => v === colInfo.options.type - ) + this.ColumnTypesWithLength.some(v => v === columnType) ) { - colInfo.options.length = + options.length = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : undefined; } if ( this.ColumnTypesWithWidth.some( - v => - v === colInfo.options.type && - colInfo.tsType !== "boolean" + v => v === columnType && tscType !== "boolean" ) ) { - colInfo.options.width = + options.width = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : undefined; } - if (colInfo.options.type) { - ent.Columns.push(colInfo); - } + ent.columns.push({ + generated, + type: columnType, + default: defaultValue, + options, + tscName, + tscType + }); }); }); return entities; } public async GetIndexesFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string, dbNames: string - ): Promise { + ): Promise { const response = await this.ExecQuery<{ TableName: string; IndexName: string; @@ -274,39 +305,39 @@ export default class MysqlDriver extends AbstractDriver { dbNames )})`); entities.forEach(ent => { - response - .filter(filterVal => filterVal.TableName === ent.tsEntityName) - .forEach(resp => { - let indexInfo: IndexInfo = {} as IndexInfo; - const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - if ( - ent.Indexes.filter( - filterVal => filterVal.name === resp.IndexName - ).length > 0 - ) { - indexInfo = ent.Indexes.find( - filterVal => filterVal.name === resp.IndexName - )!; - } else { - indexInfo.columns = [] as IndexColumnInfo[]; - indexInfo.name = resp.IndexName; - indexInfo.isUnique = resp.is_unique === 1; - indexInfo.isPrimaryKey = resp.is_primary_key === 1; - ent.Indexes.push(indexInfo); - } - indexColumnInfo.name = resp.ColumnName; - indexInfo.columns.push(indexColumnInfo); + const entityIndices = response.filter( + filterVal => filterVal.TableName === ent.tscName + ); + const indexNames = new Set(entityIndices.map(v => v.IndexName)); + indexNames.forEach(indexName => { + const records = entityIndices.filter( + v => v.IndexName === indexName + ); + + const indexInfo: Index = { + name: indexName, + columns: [], + options: {} + }; + if (records[0].is_primary_key === 1) indexInfo.primary = true; + if (records[0].is_unique === 1) indexInfo.options.unique = true; + + records.forEach(record => { + indexInfo.columns.push(record.ColumnName); }); + ent.indices.push(indexInfo); + }); }); return entities; } public async GetRelations( - entities: EntityInfo[], + entities: Entity[], schema: string, - dbNames: string - ): Promise { + dbNames: string, + generationOptions: IGenerationOptions + ): Promise { const response = await this.ExecQuery<{ TableWithForeignKey: string; FK_PartNo: number; @@ -334,30 +365,48 @@ export default class MysqlDriver extends AbstractDriver { TABLE_SCHEMA IN (${MysqlDriver.escapeCommaSeparatedList(dbNames)}) AND CU.REFERENCED_TABLE_NAME IS NOT NULL; `); - const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - response.forEach(resp => { - let rels = relationsTemp.find( - val => val.objectId === resp.object_id + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.object_id)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.object_id === relationId); + const ownerTable = entities.find( + v => v.sqlName === rows[0].TableWithForeignKey ); - if (rels === undefined) { - rels = {} as RelationTempInfo; - rels.ownerColumnsNames = []; - rels.referencedColumnsNames = []; - rels.actionOnDelete = - resp.onDelete === "NO_ACTION" ? null : resp.onDelete; - rels.actionOnUpdate = - resp.onUpdate === "NO_ACTION" ? null : resp.onUpdate; - rels.objectId = resp.object_id; - rels.ownerTable = resp.TableWithForeignKey; - rels.referencedTable = resp.TableReferenced; - relationsTemp.push(rels); + const relatedTable = entities.find( + v => v.sqlName === rows[0].TableReferenced + ); + + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${rows[0].TableWithForeignKey} and ${rows[0].TableReferenced} wasn't found in entity model.`, + true + ); + return; } - rels.ownerColumnsNames.push(resp.ForeignKeyColumn); - rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced); + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + if (rows[0].onDelete !== "NO_ACTION") { + internal.onDelete = rows[0].onDelete; + } + if (rows[0].onUpdate !== "NO_ACTION") { + internal.onUpdate = rows[0].onUpdate; + } + rows.forEach(row => { + internal.ownerColumns.push(row.ForeignKeyColumn); + internal.relatedColumns.push(row.ForeignKeyColumnReferenced); + }); + relationsTemp.push(internal); }); + const retVal = MysqlDriver.GetRelationsFromRelationTempInfo( relationsTemp, - entities + entities, + generationOptions ); return retVal; } @@ -394,7 +443,7 @@ export default class MysqlDriver extends AbstractDriver { ssl: { rejectUnauthorized: false }, - timeout: connectionOptons.timeout, + timeout: 60 * 60 * 1000, user: connectionOptons.user }; } else { @@ -403,7 +452,7 @@ export default class MysqlDriver extends AbstractDriver { host: connectionOptons.host, password: connectionOptons.password, port: connectionOptons.port, - timeout: connectionOptons.timeout, + timeout: 60 * 60 * 1000, user: connectionOptons.user }; } @@ -429,21 +478,19 @@ export default class MysqlDriver extends AbstractDriver { } public async CreateDB(dbName: string) { - await this.ExecQuery(`CREATE DATABASE ${dbName}; `); + await this.ExecQuery(`CREATE DATABASE ${dbName}; `); } public async UseDB(dbName: string) { - await this.ExecQuery(`USE ${dbName}; `); + await this.ExecQuery(`USE ${dbName}; `); } public async DropDB(dbName: string) { - await this.ExecQuery(`DROP DATABASE ${dbName}; `); + await this.ExecQuery(`DROP DATABASE ${dbName}; `); } public async CheckIfDBExists(dbName: string): Promise { - const resp = await this.ExecQuery( - `SHOW DATABASES LIKE '${dbName}' ` - ); + const resp = await this.ExecQuery(`SHOW DATABASES LIKE '${dbName}' `); return resp.length > 0; } @@ -453,7 +500,7 @@ export default class MysqlDriver extends AbstractDriver { const stream = query.stream({}); const promise = new Promise((resolve, reject) => { stream.on("data", chunk => { - ret.push((chunk as any) as T); + ret.push((chunk as unknown) as T); }); stream.on("error", err => reject(err)); stream.on("end", () => resolve(true)); @@ -463,11 +510,12 @@ export default class MysqlDriver extends AbstractDriver { } private static ReturnDefaultValueFunction( - defVal: string | null - ): string | null { + defVal: string | undefined, + dataType: string + ): string | undefined { let defaultValue = defVal; if (!defaultValue || defaultValue === "NULL") { - return null; + return undefined; } if (defaultValue.toLowerCase() === "current_timestamp()") { defaultValue = "CURRENT_TIMESTAMP"; @@ -478,6 +526,9 @@ export default class MysqlDriver extends AbstractDriver { ) { return `() => "${defaultValue}"`; } + if (dataType === "set") { + return `() => ['${defaultValue.split(",").join("','")}']`; + } return `() => "'${defaultValue}'"`; } } diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 2c7a208..9518d54 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -2,12 +2,12 @@ import * as TypeormDriver from "typeorm/driver/oracle/OracleDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../models/EntityInfo"; -import ColumnInfo from "../models/ColumnInfo"; -import IndexInfo from "../models/IndexInfo"; -import IndexColumnInfo from "../models/IndexColumnInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; +import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import IGenerationOptions from "../IGenerationOptions"; +import { RelationInternal } from "../models/RelationInternal"; export default class OracleDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.OracleDriver({ @@ -36,20 +36,28 @@ export default class OracleDriver extends AbstractDriver { } } - public GetAllTablesQuery = async () => { + public GetAllTablesQuery = async ( + schema: string, + dbNames: string, + tableNames: string[] + ) => { + const tableCondition = + tableNames.length > 0 + ? ` AND NOT TABLE_NAME IN ('${tableNames.join("','")}')` + : ""; const response: { TABLE_SCHEMA: string; TABLE_NAME: string; DB_NAME: string; - }[] = (await this.Connection.execute( - ` SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual)` - )).rows!; + }[] = ( + await this.Connection.execute( + `SELECT NULL AS TABLE_SCHEMA, TABLE_NAME, NULL AS DB_NAME FROM all_tables WHERE owner = (select user from dual) ${tableCondition}` + ) + ).rows!; return response; }; - public async GetCoulmnsFromEntity( - entities: EntityInfo[] - ): Promise { + public async GetCoulmnsFromEntity(entities: Entity[]): Promise { const response: { TABLE_NAME: string; COLUMN_NAME: string; @@ -59,123 +67,127 @@ export default class OracleDriver extends AbstractDriver { DATA_LENGTH: number; DATA_PRECISION: number; DATA_SCALE: number; - IDENTITY_COLUMN: string; + IDENTITY_COLUMN: string; // doesn't exist in old oracle versions (#195) IS_UNIQUE: number; - }[] = (await this.Connection - .execute(`SELECT utc.TABLE_NAME, utc.COLUMN_NAME, DATA_DEFAULT, NULLABLE, DATA_TYPE, DATA_LENGTH, - DATA_PRECISION, DATA_SCALE, IDENTITY_COLUMN, - (select count(*) from USER_CONS_COLUMNS ucc + }[] = ( + await this.Connection + .execute(`SELECT utc.*, (select count(*) from USER_CONS_COLUMNS ucc JOIN USER_CONSTRAINTS uc ON uc.CONSTRAINT_NAME = ucc.CONSTRAINT_NAME and uc.CONSTRAINT_TYPE='U' where ucc.column_name = utc.COLUMN_NAME AND ucc.table_name = utc.TABLE_NAME) IS_UNIQUE - FROM USER_TAB_COLUMNS utc`)).rows!; + FROM USER_TAB_COLUMNS utc`) + ).rows!; entities.forEach(ent => { response - .filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName) + .filter(filterVal => filterVal.TABLE_NAME === ent.tscName) .forEach(resp => { - const colInfo: ColumnInfo = new ColumnInfo(); - colInfo.tsName = resp.COLUMN_NAME; - colInfo.options.name = resp.COLUMN_NAME; - colInfo.options.nullable = resp.NULLABLE === "Y"; - colInfo.options.generated = resp.IDENTITY_COLUMN === "YES"; - colInfo.options.default = + const tscName = resp.COLUMN_NAME; + const options: Column["options"] = { + name: resp.COLUMN_NAME + }; + if (resp.NULLABLE === "Y") options.nullable = true; + if (resp.IS_UNIQUE > 0) options.unique = true; + const generated = + resp.IDENTITY_COLUMN === "YES" ? true : undefined; + const defaultValue = !resp.DATA_DEFAULT || resp.DATA_DEFAULT.includes('"') - ? null + ? undefined : OracleDriver.ReturnDefaultValueFunction( resp.DATA_DEFAULT ); - colInfo.options.unique = resp.IS_UNIQUE > 0; const DATA_TYPE = resp.DATA_TYPE.replace(/\([0-9]+\)/g, ""); - colInfo.options.type = DATA_TYPE.toLowerCase() as any; + const columnType = DATA_TYPE.toLowerCase(); + let tscType = ""; switch (DATA_TYPE.toLowerCase()) { case "char": - colInfo.tsType = "string"; + tscType = "string"; break; case "nchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "nvarchar2": - colInfo.tsType = "string"; + tscType = "string"; break; case "varchar2": - colInfo.tsType = "string"; + tscType = "string"; break; case "long": - colInfo.tsType = "string"; + tscType = "string"; break; case "raw": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "long raw": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "number": - colInfo.tsType = "number"; + tscType = "number"; break; case "numeric": - colInfo.tsType = "number"; + tscType = "number"; break; case "float": - colInfo.tsType = "number"; + tscType = "number"; break; case "dec": - colInfo.tsType = "number"; + tscType = "number"; break; case "decimal": - colInfo.tsType = "number"; + tscType = "number"; break; case "integer": - colInfo.tsType = "number"; + tscType = "number"; break; case "int": - colInfo.tsType = "number"; + tscType = "number"; break; case "smallint": - colInfo.tsType = "number"; + tscType = "number"; break; case "real": - colInfo.tsType = "number"; + tscType = "number"; break; case "double precision": - colInfo.tsType = "number"; + tscType = "number"; break; case "date": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "timestamp": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "timestamp with time zone": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "timestamp with local time zone": - colInfo.tsType = "Date"; + tscType = "Date"; break; case "interval year to month": - colInfo.tsType = "string"; + tscType = "string"; break; case "interval day to second": - colInfo.tsType = "string"; + tscType = "string"; break; case "bfile": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "blob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "clob": - colInfo.tsType = "string"; + tscType = "string"; break; case "nclob": - colInfo.tsType = "string"; + tscType = "string"; break; case "rowid": - colInfo.tsType = "number"; + tscType = "number"; break; case "urowid": - colInfo.tsType = "number"; + tscType = "number"; break; default: + tscType = "NonNullable"; TomgUtils.LogError( `Unknown column type:${DATA_TYPE}` ); @@ -183,75 +195,85 @@ export default class OracleDriver extends AbstractDriver { } if ( this.ColumnTypesWithPrecision.some( - v => v === colInfo.options.type + v => v === columnType ) ) { - colInfo.options.precision = resp.DATA_PRECISION; - colInfo.options.scale = resp.DATA_SCALE; + if (resp.DATA_PRECISION !== null) { + options.precision = resp.DATA_PRECISION; + } + if (resp.DATA_SCALE !== null) { + options.scale = resp.DATA_SCALE; + } } if ( - this.ColumnTypesWithLength.some( - v => v === colInfo.options.type - ) + this.ColumnTypesWithLength.some(v => v === columnType) ) { - colInfo.options.length = + options.length = resp.DATA_LENGTH > 0 ? resp.DATA_LENGTH : undefined; } - if (colInfo.options.type) { - ent.Columns.push(colInfo); - } + ent.columns.push({ + generated, + type: columnType, + default: defaultValue, + options, + tscName, + tscType + }); }); }); return entities; } - public async GetIndexesFromEntity( - entities: EntityInfo[] - ): Promise { + public async GetIndexesFromEntity(entities: Entity[]): Promise { const response: { COLUMN_NAME: string; TABLE_NAME: string; INDEX_NAME: string; UNIQUENESS: string; ISPRIMARYKEY: number; - }[] = (await this.Connection - .execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY + }[] = ( + await this.Connection + .execute(`SELECT ind.TABLE_NAME, ind.INDEX_NAME, col.COLUMN_NAME,ind.UNIQUENESS, CASE WHEN uc.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END ISPRIMARYKEY FROM USER_INDEXES ind JOIN USER_IND_COLUMNS col ON ind.INDEX_NAME=col.INDEX_NAME LEFT JOIN USER_CONSTRAINTS uc ON uc.INDEX_NAME = ind.INDEX_NAME - ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`)).rows!; + ORDER BY col.INDEX_NAME ASC ,col.COLUMN_POSITION ASC`) + ).rows!; entities.forEach(ent => { - response - .filter(filterVal => filterVal.TABLE_NAME === ent.tsEntityName) - .forEach(resp => { - let indexInfo: IndexInfo = {} as IndexInfo; - const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - if ( - ent.Indexes.filter( - filterVal => filterVal.name === resp.INDEX_NAME - ).length > 0 - ) { - indexInfo = ent.Indexes.find( - filterVal => filterVal.name === resp.INDEX_NAME - )!; - } else { - indexInfo.columns = [] as IndexColumnInfo[]; - indexInfo.name = resp.INDEX_NAME; - indexInfo.isUnique = resp.UNIQUENESS === "UNIQUE"; - indexInfo.isPrimaryKey = resp.ISPRIMARYKEY === 1; - ent.Indexes.push(indexInfo); - } - indexColumnInfo.name = resp.COLUMN_NAME; - indexInfo.columns.push(indexColumnInfo); + const entityIndices = response.filter( + filterVal => filterVal.TABLE_NAME === ent.tscName + ); + const indexNames = new Set(entityIndices.map(v => v.INDEX_NAME)); + indexNames.forEach(indexName => { + const records = entityIndices.filter( + v => v.INDEX_NAME === indexName + ); + const indexInfo: Index = { + columns: [], + options: {}, + name: records[0].INDEX_NAME + }; + if (records[0].ISPRIMARYKEY === 1) indexInfo.primary = true; + if (records[0].UNIQUENESS === "UNIQUE") + indexInfo.options.unique = true; + records.forEach(record => { + indexInfo.columns.push(record.COLUMN_NAME); }); + ent.indices.push(indexInfo); + }); }); return entities; } - public async GetRelations(entities: EntityInfo[]): Promise { + public async GetRelations( + entities: Entity[], + schema: string, + dbNames: string, + generationOptions: IGenerationOptions + ): Promise { const response: { OWNER_TABLE_NAME: string; OWNER_POSITION: string; @@ -260,8 +282,9 @@ export default class OracleDriver extends AbstractDriver { CHILD_COLUMN_NAME: string; DELETE_RULE: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; CONSTRAINT_NAME: string; - }[] = (await this.Connection - .execute(`select owner.TABLE_NAME OWNER_TABLE_NAME,ownCol.POSITION OWNER_POSITION,ownCol.COLUMN_NAME OWNER_COLUMN_NAME, + }[] = ( + await this.Connection + .execute(`select owner.TABLE_NAME OWNER_TABLE_NAME,ownCol.POSITION OWNER_POSITION,ownCol.COLUMN_NAME OWNER_COLUMN_NAME, child.TABLE_NAME CHILD_TABLE_NAME ,childCol.COLUMN_NAME CHILD_COLUMN_NAME, owner.DELETE_RULE, owner.CONSTRAINT_NAME @@ -269,32 +292,48 @@ export default class OracleDriver extends AbstractDriver { join user_constraints child on owner.r_constraint_name=child.CONSTRAINT_NAME and child.constraint_type in ('P','U') JOIN USER_CONS_COLUMNS ownCol ON owner.CONSTRAINT_NAME = ownCol.CONSTRAINT_NAME JOIN USER_CONS_COLUMNS childCol ON child.CONSTRAINT_NAME = childCol.CONSTRAINT_NAME AND ownCol.POSITION=childCol.POSITION - ORDER BY OWNER_TABLE_NAME ASC, owner.CONSTRAINT_NAME ASC, OWNER_POSITION ASC`)) - .rows!; + ORDER BY OWNER_TABLE_NAME ASC, owner.CONSTRAINT_NAME ASC, OWNER_POSITION ASC`) + ).rows!; - const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - response.forEach(resp => { - let rels = relationsTemp.find( - val => val.objectId === resp.CONSTRAINT_NAME + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.CONSTRAINT_NAME)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.CONSTRAINT_NAME === relationId); + const ownerTable = entities.find( + v => v.sqlName === rows[0].OWNER_TABLE_NAME ); - if (rels === undefined) { - rels = {} as RelationTempInfo; - rels.ownerColumnsNames = []; - rels.referencedColumnsNames = []; - rels.actionOnDelete = - resp.DELETE_RULE === "NO ACTION" ? null : resp.DELETE_RULE; - rels.actionOnUpdate = null; - rels.objectId = resp.CONSTRAINT_NAME; - rels.ownerTable = resp.OWNER_TABLE_NAME; - rels.referencedTable = resp.CHILD_TABLE_NAME; - relationsTemp.push(rels); + const relatedTable = entities.find( + v => v.sqlName === rows[0].CHILD_TABLE_NAME + ); + + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${rows[0].OWNER_TABLE_NAME} and ${rows[0].CHILD_TABLE_NAME} wasn't found in entity model.`, + true + ); + return; } - rels.ownerColumnsNames.push(resp.OWNER_COLUMN_NAME); - rels.referencedColumnsNames.push(resp.CHILD_COLUMN_NAME); + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + if (rows[0].DELETE_RULE !== "NO ACTION") { + internal.onDelete = rows[0].DELETE_RULE; + } + rows.forEach(row => { + internal.ownerColumns.push(row.OWNER_COLUMN_NAME); + internal.relatedColumns.push(row.CHILD_COLUMN_NAME); + }); + relationsTemp.push(internal); }); + const retVal = OracleDriver.GetRelationsFromRelationTempInfo( relationsTemp, - entities + entities, + generationOptions ); return retVal; } @@ -305,29 +344,28 @@ export default class OracleDriver extends AbstractDriver { } } - public async ConnectToServer(connectionOptons: IConnectionOptions) { + public async ConnectToServer(connectionOptions: IConnectionOptions) { let config: any; - if (connectionOptons.user === String(process.env.ORACLE_UsernameSys)) { + if (connectionOptions.user === String(process.env.ORACLE_UsernameSys)) { config /* Oracle.IConnectionAttributes */ = { - connectString: `${connectionOptons.host}:${connectionOptons.port}/${connectionOptons.databaseName}`, - externalAuth: connectionOptons.ssl, - password: connectionOptons.password, + connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`, + externalAuth: connectionOptions.ssl, + password: connectionOptions.password, privilege: this.Oracle.SYSDBA, - user: connectionOptons.user + user: connectionOptions.user }; } else { config /* Oracle.IConnectionAttributes */ = { - connectString: `${connectionOptons.host}:${connectionOptons.port}/${connectionOptons.databaseName}`, - externalAuth: connectionOptons.ssl, - password: connectionOptons.password, - user: connectionOptons.user + connectString: `${connectionOptions.host}:${connectionOptions.port}/${connectionOptions.databaseName}`, + externalAuth: connectionOptions.ssl, + password: connectionOptions.password, + user: connectionOptions.user }; } - const that = this; const promise = new Promise((resolve, reject) => { this.Oracle.getConnection(config, (err, connection) => { if (!err) { - that.Connection = connection; + this.Connection = connection; resolve(true); } else { TomgUtils.LogError( @@ -370,10 +408,10 @@ export default class OracleDriver extends AbstractDriver { private static ReturnDefaultValueFunction( defVal: string | null - ): string | null { + ): string | undefined { let defaultVal = defVal; if (!defaultVal) { - return null; + return undefined; } if (defaultVal.endsWith(" ")) { defaultVal = defaultVal.slice(0, -1); diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index 2662b89..174becb 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -4,12 +4,12 @@ import * as TypeormDriver from "typeorm/driver/postgres/PostgresDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../models/EntityInfo"; -import ColumnInfo from "../models/ColumnInfo"; -import IndexInfo from "../models/IndexInfo"; -import IndexColumnInfo from "../models/IndexColumnInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; +import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import IGenerationOptions from "../IGenerationOptions"; +import { RelationInternal } from "../models/RelationInternal"; export default class PostgresDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.PostgresDriver({ @@ -24,22 +24,31 @@ export default class PostgresDriver extends AbstractDriver { private Connection: PG.Client; - public GetAllTablesQuery = async (schema: string) => { + public GetAllTablesQuery = async ( + schema: string, + dbNames: string, + tableNames: string[] + ) => { + const tableCondition = + tableNames.length > 0 + ? ` AND NOT table_name IN ('${tableNames.join("','")}')` + : ""; const response: { TABLE_SCHEMA: string; TABLE_NAME: string; DB_NAME: string; - }[] = (await this.Connection.query( - `SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME", table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) AND table_name<>'spatial_ref_sys'` - )).rows; + }[] = ( + await this.Connection.query( + `SELECT table_schema as "TABLE_SCHEMA",table_name as "TABLE_NAME", table_catalog as "DB_NAME" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema in (${schema}) ${tableCondition}` + ) + ).rows; return response; }; public async GetCoulmnsFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string - ): Promise { + ): Promise { const response: { table_name: string; column_name: string; @@ -53,41 +62,46 @@ export default class PostgresDriver extends AbstractDriver { isidentity: string; isunique: string; enumvalues: string | null; - }[] = (await this.Connection - .query(`SELECT table_name,column_name,udt_name,column_default,is_nullable, - data_type,character_maximum_length,numeric_precision,numeric_scale, - case when column_default LIKE 'nextval%' then 'YES' else 'NO' end isidentity, - (SELECT count(*) - FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc - inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu - on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME - where - tc.CONSTRAINT_TYPE = 'UNIQUE' - and tc.TABLE_NAME = c.TABLE_NAME - and cu.COLUMN_NAME = c.COLUMN_NAME - and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique, - (SELECT -string_agg(enumlabel, ',') -FROM "pg_enum" "e" -INNER JOIN "pg_type" "t" ON "t"."oid" = "e"."enumtypid" -INNER JOIN "pg_namespace" "n" ON "n"."oid" = "t"."typnamespace" -WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name - ) enumValues - FROM INFORMATION_SCHEMA.COLUMNS c - where table_schema in (${schema}) - order by ordinal_position`)).rows; + }[] = ( + await this.Connection + .query(`SELECT table_name,column_name,udt_name,column_default,is_nullable, + data_type,character_maximum_length,numeric_precision,numeric_scale, + case when column_default LIKE 'nextval%' then 'YES' else 'NO' end isidentity, + (SELECT count(*) + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc + inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu + on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME + where + tc.CONSTRAINT_TYPE = 'UNIQUE' + and tc.TABLE_NAME = c.TABLE_NAME + and cu.COLUMN_NAME = c.COLUMN_NAME + and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique, + (SELECT + string_agg(enumlabel, ',') + FROM "pg_enum" "e" + INNER JOIN "pg_type" "t" ON "t"."oid" = "e"."enumtypid" + INNER JOIN "pg_namespace" "n" ON "n"."oid" = "t"."typnamespace" + WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name + ) enumValues + FROM INFORMATION_SCHEMA.COLUMNS c + where table_schema in (${schema}) + order by ordinal_position`) + ).rows; entities.forEach(ent => { response - .filter(filterVal => filterVal.table_name === ent.tsEntityName) + .filter(filterVal => filterVal.table_name === ent.tscName) .forEach(resp => { - const colInfo: ColumnInfo = new ColumnInfo(); - colInfo.tsName = resp.column_name; - colInfo.options.name = resp.column_name; - colInfo.options.nullable = resp.is_nullable === "YES"; - colInfo.options.generated = resp.isidentity === "YES"; - colInfo.options.unique = resp.isunique === "1"; - colInfo.options.default = colInfo.options.generated - ? null + const tscName = resp.column_name; + const options: Column["options"] = { + name: resp.column_name + }; + if (resp.is_nullable === "YES") options.nullable = true; + if (resp.isunique === "1") options.unique = true; + + const generated = + resp.isidentity === "YES" ? true : undefined; + const defaultValue = generated + ? undefined : PostgresDriver.ReturnDefaultValueFunction( resp.column_default ); @@ -97,63 +111,69 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name resp.udt_name, resp.enumvalues ); - if (!columnTypes.sqlType || !columnTypes.tsType) { + if (columnTypes.tsType === "NonNullable") { if ( resp.data_type === "USER-DEFINED" || resp.data_type === "ARRAY" ) { TomgUtils.LogError( - `Unknown ${resp.data_type} column type: ${resp.udt_name} table name: ${resp.table_name} column name: ${resp.column_name}` + `Unknown ${resp.data_type} column type: ${resp.udt_name} table name: ${resp.table_name} column name: ${resp.column_name}` ); } else { TomgUtils.LogError( - `Unknown column type: ${resp.data_type} table name: ${resp.table_name} column name: ${resp.column_name}` + `Unknown column type: ${resp.data_type} table name: ${resp.table_name} column name: ${resp.column_name}` ); } return; } - colInfo.options.type = columnTypes.sqlType as any; - colInfo.tsType = columnTypes.tsType; - colInfo.options.array = columnTypes.isArray; - colInfo.options.enum = columnTypes.enumValues; - if (colInfo.options.array) { - colInfo.tsType = colInfo.tsType + + const columnType = columnTypes.sqlType; + let tscType = columnTypes.tsType; + if (columnTypes.isArray) options.array = true; + if (columnTypes.enumValues.length > 0) + options.enum = columnTypes.enumValues; + if (options.array) { + tscType = tscType .split("|") .map(x => `${x.replace("|", "").trim()}[]`) - .join(" | ") as any; + .join(" | "); } if ( this.ColumnTypesWithPrecision.some( - v => v === colInfo.options.type + v => v === columnType ) ) { - colInfo.options.precision = resp.numeric_precision; - colInfo.options.scale = resp.numeric_scale; + if (resp.numeric_precision !== null) { + options.precision = resp.numeric_precision; + } + if (resp.numeric_scale !== null) { + options.scale = resp.numeric_scale; + } } if ( - this.ColumnTypesWithLength.some( - v => v === colInfo.options.type - ) + this.ColumnTypesWithLength.some(v => v === columnType) ) { - colInfo.options.length = + options.length = resp.character_maximum_length > 0 ? resp.character_maximum_length : undefined; } - if ( - this.ColumnTypesWithWidth.some( - v => v === colInfo.options.type - ) - ) { - colInfo.options.width = + if (this.ColumnTypesWithWidth.some(v => v === columnType)) { + options.width = resp.character_maximum_length > 0 ? resp.character_maximum_length : undefined; } - if (colInfo.options.type && colInfo.tsType) { - ent.Columns.push(colInfo); - } + + ent.columns.push({ + generated, + type: columnType, + default: defaultValue, + options, + tscName, + tscType + }); }); }); return entities; @@ -165,17 +185,16 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name enumValues: string | null ) { let ret: { - tsType?: ColumnInfo["tsType"]; - sqlType: string | null; + tsType: Column["tscType"]; + sqlType: string; isArray: boolean; enumValues: string[]; } = { - tsType: undefined, - sqlType: null, + tsType: "", + sqlType: dataType, isArray: false, enumValues: [] }; - ret.sqlType = dataType; switch (dataType) { case "int2": ret.tsType = "number"; @@ -381,35 +400,30 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name .split(",") .join('" | "')}"` as never) as string; ret.sqlType = "enum"; - ret.enumValues = (`"${enumValues - .split(",") - .join('","')}"` as never) as string[]; - } else { - ret.tsType = undefined; - ret.sqlType = null; + ret.enumValues = enumValues.split(","); } break; } break; default: - ret.tsType = undefined; - ret.sqlType = null; + ret.tsType = "NonNullable"; break; } return ret; } public async GetIndexesFromEntity( - entities: EntityInfo[], + entities: Entity[], schema: string - ): Promise { + ): Promise { const response: { tablename: string; indexname: string; columnname: string; is_unique: number; is_primary_key: number; - }[] = (await this.Connection.query(`SELECT + }[] = ( + await this.Connection.query(`SELECT c.relname AS tablename, i.relname as indexname, f.attname AS columnname, @@ -432,43 +446,40 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name AND n.nspname in (${schema}) AND f.attnum > 0 AND i.oid<>0 - ORDER BY c.relname,f.attname;`)).rows; + ORDER BY c.relname,f.attname;`) + ).rows; entities.forEach(ent => { - response - .filter(filterVal => filterVal.tablename === ent.tsEntityName) - .forEach(resp => { - let indexInfo: IndexInfo = {} as IndexInfo; - const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - if ( - ent.Indexes.filter( - filterVal => filterVal.name === resp.indexname - ).length > 0 - ) { - indexInfo = ent.Indexes.find( - filterVal => filterVal.name === resp.indexname - )!; - } else { - indexInfo.columns = [] as IndexColumnInfo[]; - indexInfo.name = resp.indexname; - indexInfo.isUnique = resp.is_unique === 1; - indexInfo.isPrimaryKey = resp.is_primary_key === 1; - ent.Indexes.push(indexInfo); - } - indexColumnInfo.name = resp.columnname; - if (resp.is_primary_key === 0) { - indexInfo.isPrimaryKey = false; - } - indexInfo.columns.push(indexColumnInfo); + const entityIndices = response.filter( + filterVal => filterVal.tablename === ent.tscName + ); + const indexNames = new Set(entityIndices.map(v => v.indexname)); + indexNames.forEach(indexName => { + const records = entityIndices.filter( + v => v.indexname === indexName + ); + const indexInfo: Index = { + columns: [], + options: {}, + name: records[0].indexname + }; + if (records[0].is_primary_key === 1) indexInfo.primary = true; + if (records[0].is_unique === 1) indexInfo.options.unique = true; + records.forEach(record => { + indexInfo.columns.push(record.columnname); }); + ent.indices.push(indexInfo); + }); }); return entities; } public async GetRelations( - entities: EntityInfo[], - schema: string - ): Promise { + entities: Entity[], + schema: string, + dbNames: string, + generationOptions: IGenerationOptions + ): Promise { const response: { tablewithforeignkey: string; fk_partno: number; @@ -479,7 +490,8 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name onupdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; object_id: string; // Distinct because of note in https://www.postgresql.org/docs/9.1/information-schema.html - }[] = (await this.Connection.query(`SELECT DISTINCT + }[] = ( + await this.Connection.query(`SELECT DISTINCT con.relname AS tablewithforeignkey, att.attnum as fk_partno, att2.attname AS foreignkeycolumn, @@ -518,31 +530,50 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name AND att2.attrelid = con.conrelid AND att2.attnum = con.parent AND rc.constraint_name= con.conname AND constraint_catalog=current_database() AND rc.constraint_schema=nspname - `)).rows; - const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - response.forEach(resp => { - let rels = relationsTemp.find( - val => val.objectId === resp.object_id + `) + ).rows; + + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.object_id)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.object_id === relationId); + const ownerTable = entities.find( + v => v.sqlName === rows[0].tablewithforeignkey ); - if (rels === undefined) { - rels = {} as RelationTempInfo; - rels.ownerColumnsNames = []; - rels.referencedColumnsNames = []; - rels.actionOnDelete = - resp.ondelete === "NO ACTION" ? null : resp.ondelete; - rels.actionOnUpdate = - resp.onupdate === "NO ACTION" ? null : resp.onupdate; - rels.objectId = resp.object_id; - rels.ownerTable = resp.tablewithforeignkey; - rels.referencedTable = resp.tablereferenced; - relationsTemp.push(rels); + const relatedTable = entities.find( + v => v.sqlName === rows[0].tablereferenced + ); + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${rows[0].tablewithforeignkey} and ${rows[0].tablereferenced} wasn't found in entity model.`, + true + ); + return; } - rels.ownerColumnsNames.push(resp.foreignkeycolumn); - rels.referencedColumnsNames.push(resp.foreignkeycolumnreferenced); + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + if (rows[0].ondelete !== "NO ACTION") { + internal.onDelete = rows[0].ondelete; + } + if (rows[0].onupdate !== "NO ACTION") { + internal.onUpdate = rows[0].onupdate; + } + rows.forEach(row => { + internal.ownerColumns.push(row.foreignkeycolumn); + internal.relatedColumns.push(row.foreignkeycolumnreferenced); + }); + relationsTemp.push(internal); }); + const retVal = PostgresDriver.GetRelationsFromRelationTempInfo( relationsTemp, - entities + entities, + generationOptions ); return retVal; } @@ -575,7 +606,7 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name port: connectionOptons.port, ssl: connectionOptons.ssl, // eslint-disable-next-line @typescript-eslint/camelcase - statement_timeout: connectionOptons.timeout, + statement_timeout: 60 * 60 * 1000, user: connectionOptons.user }); @@ -618,10 +649,10 @@ WHERE "n"."nspname" = table_schema AND "t"."typname"=udt_name private static ReturnDefaultValueFunction( defVal: string | null - ): string | null { + ): string | undefined { let defaultValue = defVal; if (!defaultValue) { - return null; + return undefined; } defaultValue = defaultValue.replace(/'::[\w ]*/, "'"); if (defaultValue.startsWith(`'`)) { diff --git a/src/drivers/SqliteDriver.ts b/src/drivers/SqliteDriver.ts index 5dbadc5..2eee238 100644 --- a/src/drivers/SqliteDriver.ts +++ b/src/drivers/SqliteDriver.ts @@ -4,12 +4,12 @@ import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as sqliteLib from "sqlite3"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../models/EntityInfo"; -import ColumnInfo from "../models/ColumnInfo"; -import IndexInfo from "../models/IndexInfo"; -import IndexColumnInfo from "../models/IndexColumnInfo"; -import RelationTempInfo from "../models/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; +import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import IGenerationOptions from "../IGenerationOptions"; +import { RelationInternal } from "../models/RelationInternal"; export default class SqliteDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.SqliteDriver({ @@ -24,33 +24,43 @@ export default class SqliteDriver extends AbstractDriver { public sqlite = sqliteLib.verbose(); - public db: any; + public db: sqliteLib.Database; public tablesWithGeneratedPrimaryKey: string[] = new Array(); public GetAllTablesQuery: any; - public async GetAllTables(): Promise { - const ret: EntityInfo[] = [] as EntityInfo[]; + public async GetAllTables( + schema: string, + dbNames: string, + tableNames: string[] + ): Promise { + const ret: Entity[] = [] as Entity[]; + const tableCondition = + tableNames.length > 0 + ? ` AND NOT tbl_name IN ('${tableNames.join("','")}')` + : ""; const rows = await this.ExecQuery<{ tbl_name: string; sql: string }>( - `SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%'` + `SELECT tbl_name, sql FROM "sqlite_master" WHERE "type" = 'table' AND name NOT LIKE 'sqlite_%' ${tableCondition}` ); rows.forEach(val => { - const ent: EntityInfo = new EntityInfo(); - ent.tsEntityName = val.tbl_name; - ent.Columns = [] as ColumnInfo[]; - ent.Indexes = [] as IndexInfo[]; if (val.sql.includes("AUTOINCREMENT")) { - this.tablesWithGeneratedPrimaryKey.push(ent.tsEntityName); + this.tablesWithGeneratedPrimaryKey.push(val.tbl_name); } - ret.push(ent); + ret.push({ + columns: [], + indices: [], + relations: [], + relationIds: [], + sqlName: val.tbl_name, + tscName: val.tbl_name, + fileImports: [] + }); }); return ret; } - public async GetCoulmnsFromEntity( - entities: EntityInfo[] - ): Promise { + public async GetCoulmnsFromEntity(entities: Entity[]): Promise { await Promise.all( entities.map(async ent => { const response = await this.ExecQuery<{ @@ -60,155 +70,172 @@ export default class SqliteDriver extends AbstractDriver { notnull: number; dflt_value: string; pk: number; - }>(`PRAGMA table_info('${ent.tsEntityName}');`); + }>(`PRAGMA table_info('${ent.tscName}');`); response.forEach(resp => { - const colInfo: ColumnInfo = new ColumnInfo(); - colInfo.tsName = resp.name; - colInfo.options.name = resp.name; - colInfo.options.nullable = resp.notnull === 0; - colInfo.options.primary = resp.pk > 0; - colInfo.options.default = SqliteDriver.ReturnDefaultValueFunction( + const tscName = resp.name; + let tscType = ""; + const options: Column["options"] = { name: resp.name }; + if (resp.notnull === 0) options.nullable = true; + const isPrimary = resp.pk > 0 ? true : undefined; + const defaultValue = SqliteDriver.ReturnDefaultValueFunction( resp.dflt_value ); - colInfo.options.type = resp.type + const columnType = resp.type .replace(/\([0-9 ,]+\)/g, "") .toLowerCase() - .trim() as any; - colInfo.options.generated = - colInfo.options.primary && - this.tablesWithGeneratedPrimaryKey.includes( - ent.tsEntityName - ); - switch (colInfo.options.type) { + .trim(); + const generated = + isPrimary && + this.tablesWithGeneratedPrimaryKey.includes(ent.tscName) + ? true + : undefined; + switch (columnType) { case "int": - colInfo.tsType = "number"; + tscType = "number"; break; case "integer": - colInfo.tsType = "number"; + tscType = "number"; break; case "int2": - colInfo.tsType = "number"; + tscType = "number"; break; case "int8": - colInfo.tsType = "number"; + tscType = "number"; break; case "tinyint": - colInfo.tsType = "number"; + tscType = "number"; break; case "smallint": - colInfo.tsType = "number"; + tscType = "number"; break; case "mediumint": - colInfo.tsType = "number"; + tscType = "number"; break; case "bigint": - colInfo.tsType = "string"; + tscType = "string"; break; case "unsigned big int": - colInfo.tsType = "string"; + tscType = "string"; break; case "character": - colInfo.tsType = "string"; + tscType = "string"; break; case "varchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "varying character": - colInfo.tsType = "string"; + tscType = "string"; break; case "nchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "native character": - colInfo.tsType = "string"; + tscType = "string"; break; case "nvarchar": - colInfo.tsType = "string"; + tscType = "string"; break; case "text": - colInfo.tsType = "string"; + tscType = "string"; break; case "blob": - colInfo.tsType = "Buffer"; + tscType = "Buffer"; break; case "clob": - colInfo.tsType = "string"; + tscType = "string"; break; case "real": - colInfo.tsType = "number"; + tscType = "number"; break; case "double": - colInfo.tsType = "number"; + tscType = "number"; break; case "double precision": - colInfo.tsType = "number"; + tscType = "number"; break; case "float": - colInfo.tsType = "number"; + tscType = "number"; break; case "numeric": - colInfo.tsType = "number"; + tscType = "number"; break; case "decimal": - colInfo.tsType = "number"; + tscType = "number"; break; case "boolean": - colInfo.tsType = "boolean"; + tscType = "boolean"; break; case "date": - colInfo.tsType = "string"; + tscType = "string"; break; case "datetime": - colInfo.tsType = "Date"; + tscType = "Date"; break; default: + tscType = "NonNullable"; TomgUtils.LogError( - `Unknown column type: ${colInfo.options.type} table name: ${ent.tsEntityName} column name: ${resp.name}` + `Unknown column type: ${columnType} table name: ${ent.tscName} column name: ${resp.name}` ); break; } - const options = resp.type.match(/\([0-9 ,]+\)/g); + const sqlOptions = resp.type.match(/\([0-9 ,]+\)/g); if ( this.ColumnTypesWithPrecision.some( - v => v === colInfo.options.type + v => v === columnType ) && - options + sqlOptions ) { - colInfo.options.precision = options[0] - .substring(1, options[0].length - 1) - .split(",")[0] as any; - colInfo.options.scale = options[0] - .substring(1, options[0].length - 1) - .split(",")[1] as any; + options.precision = Number.parseInt( + sqlOptions[0] + .substring(1, sqlOptions[0].length - 1) + .split(",")[0], + 10 + ); + options.scale = Number.parseInt( + sqlOptions[0] + .substring(1, sqlOptions[0].length - 1) + .split(",")[1], + 10 + ); } if ( this.ColumnTypesWithLength.some( - v => v === colInfo.options.type + v => v === columnType ) && - options + sqlOptions ) { - colInfo.options.length = options[0].substring( - 1, - options[0].length - 1 - ) as any; + options.length = Number.parseInt( + sqlOptions[0].substring( + 1, + sqlOptions[0].length - 1 + ), + 10 + ); } if ( this.ColumnTypesWithWidth.some( - v => - v === colInfo.options.type && - colInfo.tsType !== "boolean" + v => v === columnType && tscType !== "boolean" ) && - options + sqlOptions ) { - colInfo.options.width = options[0].substring( - 1, - options[0].length - 1 - ) as any; + options.width = Number.parseInt( + sqlOptions[0].substring( + 1, + sqlOptions[0].length - 1 + ), + 10 + ); } - if (colInfo.options.type) { - ent.Columns.push(colInfo); - } + ent.columns.push({ + generated, + primary: isPrimary, + type: columnType, + default: defaultValue, + options, + tscName, + tscType + }); }); }) ); @@ -216,9 +243,7 @@ export default class SqliteDriver extends AbstractDriver { return entities; } - public async GetIndexesFromEntity( - entities: EntityInfo[] - ): Promise { + public async GetIndexesFromEntity(entities: Entity[]): Promise { await Promise.all( entities.map(async ent => { const response = await this.ExecQuery<{ @@ -227,7 +252,7 @@ export default class SqliteDriver extends AbstractDriver { unique: number; origin: string; partial: number; - }>(`PRAGMA index_list('${ent.tsEntityName}');`); + }>(`PRAGMA index_list('${ent.tscName}');`); await Promise.all( response.map(async resp => { const indexColumnsResponse = await this.ExecQuery<{ @@ -235,37 +260,29 @@ export default class SqliteDriver extends AbstractDriver { cid: number; name: string; }>(`PRAGMA index_info('${resp.name}');`); - indexColumnsResponse.forEach(element => { - let indexInfo: IndexInfo = {} as IndexInfo; - const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - if ( - ent.Indexes.filter(filterVal => { - return filterVal.name === resp.name; - }).length > 0 - ) { - indexInfo = ent.Indexes.find( - filterVal => filterVal.name === resp.name - )!; - } else { - indexInfo.columns = [] as IndexColumnInfo[]; - indexInfo.name = resp.name; - indexInfo.isUnique = resp.unique === 1; - ent.Indexes.push(indexInfo); - } - indexColumnInfo.name = element.name; - if ( - indexColumnsResponse.length === 1 && - indexInfo.isUnique - ) { - ent.Columns.filter( - v => v.tsName === indexColumnInfo.name - ).forEach(v => { + + const indexInfo: Index = { + name: resp.name, + columns: [], + options: {} + }; + if (resp.unique === 1) indexInfo.options.unique = true; + + indexColumnsResponse.forEach(record => { + indexInfo.columns.push(record.name); + }); + if ( + indexColumnsResponse.length === 1 && + indexInfo.options.unique + ) { + ent.columns + .filter(v => v.tscName === indexInfo.columns[0]) + .forEach(v => { // eslint-disable-next-line no-param-reassign v.options.unique = true; }); - } - indexInfo.columns.push(indexColumnInfo); - }); + } + ent.indices.push(indexInfo); }) ); }) @@ -274,7 +291,12 @@ export default class SqliteDriver extends AbstractDriver { return entities; } - public async GetRelations(entities: EntityInfo[]): Promise { + public async GetRelations( + entities: Entity[], + schema: string, + dbNames: string, + generationOptions: IGenerationOptions + ): Promise { let retVal = entities; await Promise.all( retVal.map(async entity => { @@ -295,25 +317,49 @@ export default class SqliteDriver extends AbstractDriver { | "SET NULL" | "NO ACTION"; match: string; - }>(`PRAGMA foreign_key_list('${entity.tsEntityName}');`); - const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - response.forEach(resp => { - const rels = {} as RelationTempInfo; - rels.ownerColumnsNames = []; - rels.referencedColumnsNames = []; - rels.actionOnDelete = - resp.on_delete === "NO ACTION" ? null : resp.on_delete; - rels.actionOnUpdate = - resp.on_update === "NO ACTION" ? null : resp.on_update; - rels.ownerTable = entity.tsEntityName; - rels.referencedTable = resp.table; - relationsTemp.push(rels); - rels.ownerColumnsNames.push(resp.from); - rels.referencedColumnsNames.push(resp.to); + }>(`PRAGMA foreign_key_list('${entity.tscName}');`); + + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.id)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.id === relationId); + const ownerTable = entities.find( + v => v.sqlName === entity.tscName + ); + const relatedTable = entities.find( + v => v.sqlName === rows[0].table + ); + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${entity.tscName} and ${rows[0].table} wasn't found in entity model.`, + true + ); + return; + } + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + if (rows[0].on_delete !== "NO ACTION") { + internal.onDelete = rows[0].on_delete; + } + if (rows[0].on_update !== "NO ACTION") { + internal.onUpdate = rows[0].on_update; + } + rows.forEach(row => { + internal.ownerColumns.push(row.from); + internal.relatedColumns.push(row.to); + }); + relationsTemp.push(internal); }); + retVal = SqliteDriver.GetRelationsFromRelationTempInfo( relationsTemp, - retVal + retVal, + generationOptions ); }) ); @@ -362,7 +408,7 @@ export default class SqliteDriver extends AbstractDriver { } public async ExecQuery(sql: string): Promise { - let ret: any; + let ret: T[] = []; const promise = new Promise((resolve, reject) => { this.db.serialize(() => { this.db.all(sql, [], (err, row) => { @@ -386,9 +432,9 @@ export default class SqliteDriver extends AbstractDriver { private static ReturnDefaultValueFunction( defVal: string | null - ): string | null { + ): string | undefined { if (!defVal) { - return null; + return undefined; } if (defVal.startsWith(`'`)) { return `() => "${defVal}"`; diff --git a/src/entity.mst b/src/entity.mst deleted file mode 100644 index 8b333e8..0000000 --- a/src/entity.mst +++ /dev/null @@ -1,46 +0,0 @@ -import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; -{{relationImports}}{{#each UniqueImports}}import {{curly true}}{{toEntityName this}}{{curly false}} from "./{{toFileName this}}"; -{{/each}} - - -@Entity("{{sqlEntityName}}"{{#Schema}} ,{schema:"{{.}}"{{#if ../Database}}, database:"{{../Database}}"{{/if}} } {{/Schema}}) -{{#Indexes}}{{^isPrimaryKey}}@Index("{{name}}",[{{#columns}}"{{toPropertyName name}}",{{/columns}}]{{#isUnique}},{unique:true}{{/isUnique}}) -{{/isPrimaryKey}}{{/Indexes}}export class {{toEntityName tsEntityName}}{{#IsActiveRecord}} extends BaseEntity{{/IsActiveRecord}} { -{{#Columns}} - - {{^relations}}{{#options}}{{#generated}} @PrimaryGeneratedColumn({ - type:"{{type}}", {{/generated}}{{^generated}} @Column("{{type}}",{ {{#nullable}} - nullable:true,{{/nullable}}{{^nullable}} - nullable:false,{{/nullable}}{{#primary}} - primary:{{primary}},{{/primary}}{{#unique}} - unique: true,{{/unique}}{{/generated}}{{#length}} - length:{{.}},{{/length}}{{#width}} - width:{{.}},{{/width}}{{#unsigned}} - unsigned: true,{{/unsigned}}{{#default}} - default: {{.}},{{/default}}{{#precision}} - precision:{{.}},{{/precision}}{{#scale}} - scale:{{.}},{{/scale}}{{#enum}} - enum:[{{.}}],{{/enum}}{{#array}} - array:{{array}},{{/array}} - name:"{{name}}" - }){{/options}} - {{printPropertyVisibility}}{{toPropertyName tsName}}{{strictMode}}:{{tsType}}{{#options/nullable}} | null{{/options/nullable}}; - {{/relations}}{{#relations}} - @{{relationType}}(()=>{{toEntityName relatedTable}}, ({{toPropertyName relatedTable}}: {{toEntityName relatedTable}})=>{{toPropertyName relatedTable}}.{{#if isOwner}}{{toPropertyName ownerColumn}},{ {{#../options/primary}}primary:true,{{/../options/primary}}{{^../options/nullable}} nullable:false,{{/../options/nullable}}{{#actionOnDelete}}onDelete: '{{.}}',{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{else}}{{toPropertyName relatedColumn}}{{#if (or actionOnDelete actionOnUpdate ) }},{ {{#actionOnDelete}}onDelete: '{{.}}' ,{{/actionOnDelete}}{{#actionOnUpdate}}onUpdate: '{{.}}'{{/actionOnUpdate}} }{{/if}}{{/if}}){{#isOwner}} - {{#if isManyToMany}}@JoinTable({ name:'{{ ../options/name}}'{{#if joinColumn}},joinColumn:{name:'{{joinColumn}}'}{{/if}}{{#if inverseJoinColumn}},inverseJoinColumn:{name:'{{inverseJoinColumn}}'}{{/if}} }){{else}}@JoinColumn({ name:'{{ ../options/name}}'}){{/if}}{{/isOwner}} - {{#if (or isOneToMany isManyToMany)}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}{{strictMode}}:{{toLazy (concat (toEntityName relatedTable) "[]")}}; - {{else}}{{printPropertyVisibility}}{{toPropertyName ../tsName}}{{strictMode}}:{{toLazy (concat (toEntityName relatedTable) ' | null')}}; - {{/if}} - {{#if relationIdField }} - - @RelationId(({{toPropertyName ../../tsEntityName}}: {{toEntityName ../../tsEntityName}}) => {{toPropertyName ../../tsEntityName}}.{{toPropertyName ../tsName}}) - {{printPropertyVisibility}}{{toPropertyName ../tsName}}Id{{strictMode}}: {{#if isOneToOne}}{{toLazy ../tsType}}{{else}}{{toLazy (concat ../tsType "[]")}}{{/if}};{{/if}}{{/relations}} - {{/Columns}} - {{#if GenerateConstructor}} - - {{printPropertyVisibility}}constructor(init?: Partial<{{toEntityName tsEntityName}}>) { - {{#IsActiveRecord}}super(); - {{/IsActiveRecord}}Object.assign(this, init); - } - {{/if}} -} diff --git a/src/index.ts b/src/index.ts index 299a195..9f40faf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,12 @@ import * as Yargs from "yargs"; import { createDriver, createModelFromDatabase } from "./Engine"; import * as TomgUtils from "./Utils"; -import AbstractDriver from "./drivers/AbstractDriver"; -import IConnectionOptions from "./IConnectionOptions"; -import IGenerationOptions from "./IGenerationOptions"; +import IConnectionOptions, { + getDefaultConnectionOptions +} from "./IConnectionOptions"; +import IGenerationOptions, { + getDefaultGenerationOptions +} from "./IGenerationOptions"; import fs = require("fs-extra"); import inquirer = require("inquirer"); @@ -12,72 +15,154 @@ import path = require("path"); // eslint-disable-next-line @typescript-eslint/no-floating-promises CliLogic(); +type options = { + connectionOptions: IConnectionOptions; + generationOptions: IGenerationOptions; +}; + async function CliLogic() { console.log(TomgUtils.packageVersion()); - let driver: AbstractDriver; - let connectionOptions: IConnectionOptions; - let generationOptions: IGenerationOptions; + let options = makeDefaultConfigs(); + const TOMLConfig = readTOMLConfig(options); + options = TOMLConfig.options; if (process.argv.length > 2) { - const retVal = GetUtilParametersByArgs(); - connectionOptions = retVal.connectionOptions; - generationOptions = retVal.generationOptions; - driver = retVal.driver; - } else if (fs.existsSync(path.resolve(process.cwd(), ".tomg-config"))) { - console.log( - `[${new Date().toLocaleTimeString()}] Using configuration file. [${path.resolve( - process.cwd(), - ".tomg-config" - )}]` - ); - const retVal = await fs.readJson( - path.resolve(process.cwd(), ".tomg-config") - ); - [connectionOptions, generationOptions] = retVal; - driver = createDriver(connectionOptions.databaseType); - } else { - const retVal = await GetUtilParametersByInquirer(); - driver = retVal.driver; - connectionOptions = retVal.connectionOptions; - generationOptions = retVal.generationOptions; + options = checkYargsParameters(options); + } else if (!TOMLConfig.fullConfigFile) { + options = await useInquirer(options); } + options = validateConfig(options); + const driver = createDriver(options.connectionOptions.databaseType); console.log( `[${new Date().toLocaleTimeString()}] Starting creation of model classes.` ); - await createModelFromDatabase(driver, connectionOptions, generationOptions); + await createModelFromDatabase( + driver, + options.connectionOptions, + options.generationOptions + ); console.info( `[${new Date().toLocaleTimeString()}] Typeorm model classes created.` ); } +function validateConfig(options: options): options { + if ( + options.generationOptions.lazy && + options.generationOptions.relationIds + ) { + TomgUtils.LogError( + "Typeorm doesn't support RelationId fields for lazy relations.", + false + ); + options.generationOptions.relationIds = false; + } + return options; +} +function makeDefaultConfigs() { + const generationOptions = getDefaultGenerationOptions(); + const connectionOptions = getDefaultConnectionOptions(); + return { + generationOptions, + connectionOptions + }; +} +function readTOMLConfig( + options: options +): { options; fullConfigFile: boolean } { + if (!fs.existsSync(path.resolve(process.cwd(), ".tomg-config"))) { + return { options, fullConfigFile: false }; + } + console.log( + `[${new Date().toLocaleTimeString()}] Using configuration file. [${path.resolve( + process.cwd(), + ".tomg-config" + )}]` + ); + const retVal = fs.readJsonSync(path.resolve(process.cwd(), ".tomg-config")); + const [loadedGenerationOptions, loadedConnectionOptions] = retVal; -function GetUtilParametersByArgs() { + let hasUnknownProperties = false; + if (loadedConnectionOptions) { + Object.keys(loadedConnectionOptions).forEach(key => { + if ( + Object.prototype.hasOwnProperty.call( + options.connectionOptions, + key + ) + ) { + options.connectionOptions[key] = loadedConnectionOptions[key]; + } else { + console.error(`Unknown connection option ${key}.`); + hasUnknownProperties = true; + } + }); + } + if (loadedGenerationOptions) { + Object.keys(loadedGenerationOptions).forEach(key => { + if ( + Object.prototype.hasOwnProperty.call( + options.generationOptions, + key + ) + ) { + options.generationOptions[key] = loadedGenerationOptions[key]; + } else { + console.error(`Unknown generation option ${key}.`); + hasUnknownProperties = true; + } + }); + } + + const fullConfigFile = + !hasUnknownProperties && + loadedConnectionOptions && + loadedGenerationOptions && + Object.keys(loadedConnectionOptions).length === + Object.keys(options.connectionOptions).length && + Object.keys(loadedGenerationOptions).length === + Object.keys(options.generationOptions).length; + + return { + options, + fullConfigFile + }; +} +function checkYargsParameters(options: options): options { const { argv } = Yargs.usage( - "Usage: typeorm-model-generator -h -d -p [port] -u -x [password] -e [engine]\nYou can also run program without specyfiying any parameters." - ) - .option("h", { + "Usage: typeorm-model-generator -h -d -p [port] -u -x [password] -e [engine]\nYou can also run program without specifying any parameters." + ).options({ + h: { alias: "host", - default: "127.0.0.1", + string: true, + default: options.connectionOptions.host, describe: "IP address/Hostname for database server" - }) - .option("d", { + }, + d: { alias: "database", + string: true, demand: true, + default: options.connectionOptions.databaseName, describe: "Database name(or path for sqlite). You can pass multiple values separated by comma." - }) - .option("u", { + }, + u: { alias: "user", + string: true, + default: options.connectionOptions.user, describe: "Username for database server" - }) - .option("x", { + }, + x: { alias: "pass", - default: "", + string: true, + default: options.connectionOptions.password, describe: "Password for database server" - }) - .option("p", { + }, + p: { + number: true, alias: "port", + default: options.connectionOptions.port, describe: "Port number for database server" - }) - .option("e", { + }, + e: { alias: "engine", choices: [ "mssql", @@ -87,155 +172,183 @@ function GetUtilParametersByArgs() { "oracle", "sqlite" ], - default: "mssql", + demand: true, + default: options.connectionOptions.databaseType, describe: "Database engine" - }) - .option("o", { + }, + o: { alias: "output", - default: path.resolve(process.cwd(), "output"), + default: options.generationOptions.resultsPath, describe: "Where to place generated models" - }) - .option("s", { + }, + s: { alias: "schema", + string: true, + default: options.connectionOptions.schemaName, describe: "Schema name to create model from. Only for mssql and postgres. You can pass multiple values separated by comma eg. -s scheme1,scheme2,scheme3" - }) - .option("ssl", { + }, + ssl: { boolean: true, - default: false - }) - .option("noConfig", { + default: options.connectionOptions.ssl + }, + noConfig: { boolean: true, - default: false, + default: options.generationOptions.noConfigs, describe: `Doesn't create tsconfig.json and ormconfig.json` - }) - .option("cf", { + }, + cf: { alias: "case-file", choices: ["pascal", "param", "camel", "none"], - default: "pascal", + default: options.generationOptions.convertCaseFile, describe: "Convert file names to specified case" - }) - .option("ce", { + }, + ce: { alias: "case-entity", choices: ["pascal", "camel", "none"], - default: "pascal", + default: options.generationOptions.convertCaseEntity, describe: "Convert class names to specified case" - }) - .option("cp", { + }, + cp: { alias: "case-property", choices: ["pascal", "camel", "none"], - default: "camel", + default: options.generationOptions.convertCaseProperty, describe: "Convert property names to specified case" - }) - .option("pv", { + }, + pv: { alias: "property-visibility", choices: ["public", "protected", "private", "none"], - default: "none", + default: options.generationOptions.propertyVisibility, describe: "Defines which visibility should have the generated property" - }) - .option("lazy", { + }, + lazy: { boolean: true, - default: false, + default: options.generationOptions.lazy, describe: "Generate lazy relations" - }) - .option("a", { + }, + a: { alias: "active-record", boolean: true, - default: false, + default: options.generationOptions.activeRecord, describe: "Use ActiveRecord syntax for generated models" - }) - .option("namingStrategy", { - describe: "Use custom naming strategy" - }) - .option("relationIds", { + }, + namingStrategy: { + describe: "Use custom naming strategy", + default: options.generationOptions.customNamingStrategyPath, + string: true + }, + relationIds: { boolean: true, - default: false, + default: options.generationOptions.relationIds, describe: "Generate RelationId fields" - }) - .option("skipSchema", { + }, + skipSchema: { boolean: true, - default: false, + default: options.generationOptions.skipSchema, describe: "Omits schema identifier in generated entities" - }) - .option("generateConstructor", { + }, + generateConstructor: { boolean: true, - default: false, + default: options.generationOptions.generateConstructor, describe: "Generate constructor allowing partial initialization" - }) - .option("strictMode", { + }, + disablePluralization: { + boolean: true, + default: !options.generationOptions.pluralizeNames, + describe: + "Disable pluralization of OneToMany, ManyToMany relation names" + }, + skipTables: { + string: true, + default: options.connectionOptions.skipTables.join(","), + describe: + "Skip schema generation for specific tables. You can pass multiple values separated by comma" + }, + strictMode: { choices: ["none", "?", "!"], - default: "none", + default: options.generationOptions.strictMode, describe: "Mark fields as optional(?) or non-null(!)" - }) - .option("timeout", { - describe: "SQL Query timeout(ms)", - number: true - }); + }, + index: { + boolean: true, + default: options.generationOptions.indexFile, + describe: "Generate index file" + }, + defaultExport: { + boolean: true, + default: options.generationOptions.exportType === "default", + describe: "Generate index file" + } + }); - const driver = createDriver(argv.e); - const { standardPort } = driver; - const { standardSchema } = driver; - const standardUser = driver.standardPort; - let namingStrategyPath: string; - if (argv.namingStrategy && argv.namingStrategy !== "") { - namingStrategyPath = argv.namingStrategy; - } else { - namingStrategyPath = ""; - } - const connectionOptions: IConnectionOptions = new IConnectionOptions(); - connectionOptions.databaseName = argv.d ? argv.d.toString() : null; - connectionOptions.databaseType = argv.e; - connectionOptions.host = argv.h; - connectionOptions.password = argv.x ? argv.x.toString() : null; - connectionOptions.port = parseInt(argv.p, 10) || standardPort; - connectionOptions.schemaName = argv.s ? argv.s.toString() : standardSchema; - connectionOptions.ssl = argv.ssl; - connectionOptions.timeout = argv.timeout; - connectionOptions.user = argv.u ? argv.u.toString() : standardUser; - const generationOptions: IGenerationOptions = new IGenerationOptions(); - generationOptions.activeRecord = argv.a; - generationOptions.generateConstructor = argv.generateConstructor; - generationOptions.convertCaseEntity = argv.ce; - generationOptions.convertCaseFile = argv.cf; - generationOptions.convertCaseProperty = argv.cp; - generationOptions.lazy = argv.lazy; - generationOptions.customNamingStrategyPath = namingStrategyPath; - generationOptions.noConfigs = argv.noConfig; - generationOptions.propertyVisibility = argv.pv; - generationOptions.relationIds = argv.relationIds; - generationOptions.skipSchema = argv.skipSchema; - generationOptions.resultsPath = argv.o ? argv.o.toString() : null; - generationOptions.strictMode = - argv.strictMode === "none" ? false : argv.strictMode; + options.connectionOptions.databaseName = argv.d; + options.connectionOptions.databaseType = argv.e; - return { driver, connectionOptions, generationOptions }; + const driver = createDriver(options.connectionOptions.databaseType); + const { standardPort, standardSchema, standardUser } = driver; + + options.connectionOptions.host = argv.h; + options.connectionOptions.password = argv.x; + options.connectionOptions.port = argv.p || standardPort; + options.connectionOptions.schemaName = argv.s + ? argv.s.toString() + : standardSchema; + options.connectionOptions.ssl = argv.ssl; + options.connectionOptions.user = argv.u || standardUser; + options.connectionOptions.skipTables = argv.skipTables.split(","); + options.generationOptions.activeRecord = argv.a; + options.generationOptions.generateConstructor = argv.generateConstructor; + options.generationOptions.convertCaseEntity = argv.ce as IGenerationOptions["convertCaseEntity"]; + options.generationOptions.convertCaseFile = argv.cf as IGenerationOptions["convertCaseFile"]; + options.generationOptions.convertCaseProperty = argv.cp as IGenerationOptions["convertCaseProperty"]; + options.generationOptions.lazy = argv.lazy; + options.generationOptions.customNamingStrategyPath = argv.namingStrategy; + options.generationOptions.noConfigs = argv.noConfig; + options.generationOptions.propertyVisibility = argv.pv as IGenerationOptions["propertyVisibility"]; + options.generationOptions.relationIds = argv.relationIds; + options.generationOptions.skipSchema = argv.skipSchema; + options.generationOptions.resultsPath = argv.o; + options.generationOptions.pluralizeNames = !argv.disablePluralization; + options.generationOptions.strictMode = argv.strictMode as IGenerationOptions["strictMode"]; + options.generationOptions.indexFile = argv.index; + options.generationOptions.exportType = argv.defaultExport + ? "default" + : "named"; + + return options; } -async function GetUtilParametersByInquirer() { - const connectionOptions: IConnectionOptions = new IConnectionOptions(); - const generationOptions: IGenerationOptions = new IGenerationOptions(); - - connectionOptions.databaseType = ((await inquirer.prompt([ - { - choices: [ - "mssql", - "postgres", - "mysql", - "mariadb", - "oracle", - "sqlite" - ], - message: "Choose database engine", - name: "engine", - type: "list" - } - ])) as any).engine; - const driver = createDriver(connectionOptions.databaseType); - if (connectionOptions.databaseType !== "sqlite") { - const answ: any = await inquirer.prompt([ +async function useInquirer(options: options): Promise { + const oldDatabaseType = options.connectionOptions.databaseType; + options.connectionOptions.databaseType = ( + await inquirer.prompt([ { - default: "localhost", + choices: [ + "mssql", + "postgres", + "mysql", + "mariadb", + "oracle", + "sqlite" + ], + default: options.connectionOptions.databaseType, + message: "Choose database engine", + name: "engine", + type: "list" + } + ]) + ).engine; + const driver = createDriver(options.connectionOptions.databaseType); + if (options.connectionOptions.databaseType !== oldDatabaseType) { + options.connectionOptions.port = driver.standardPort; + options.connectionOptions.user = driver.standardUser; + options.connectionOptions.schemaName = driver.standardSchema; + } + if (options.connectionOptions.databaseType !== "sqlite") { + const answ = await inquirer.prompt([ + { + default: options.connectionOptions.host, message: "Database address:", name: "host", type: "input" @@ -244,16 +357,14 @@ async function GetUtilParametersByInquirer() { message: "Database port:", name: "port", type: "input", - default() { - return driver.standardPort; - }, + default: options.connectionOptions.port, validate(value) { const valid = !Number.isNaN(parseInt(value, 10)); return valid || "Please enter a valid port number"; } }, { - default: false, + default: options.connectionOptions.ssl, message: "Use SSL:", name: "ssl", type: "confirm" @@ -262,9 +373,7 @@ async function GetUtilParametersByInquirer() { message: "Database user name:", name: "login", type: "input", - default() { - return driver.standardUser; - } + default: options.connectionOptions.user }, { message: "Database user password:", @@ -272,7 +381,7 @@ async function GetUtilParametersByInquirer() { type: "password" }, { - default: "", + default: options.connectionOptions.databaseName, message: "Database name: (You can pass multiple values separated by comma)", name: "dbName", @@ -280,227 +389,307 @@ async function GetUtilParametersByInquirer() { } ]); if ( - connectionOptions.databaseType === "mssql" || - connectionOptions.databaseType === "postgres" + options.connectionOptions.databaseType === "mssql" || + options.connectionOptions.databaseType === "postgres" ) { - connectionOptions.schemaName = ((await inquirer.prompt([ + options.connectionOptions.schemaName = ( + await inquirer.prompt([ + { + default: options.connectionOptions.schemaName, + message: + "Database schema: (You can pass multiple values separated by comma)", + name: "schema", + type: "input" + } + ]) + ).schema; + } + options.connectionOptions.port = parseInt(answ.port, 10); + options.connectionOptions.host = answ.host; + options.connectionOptions.user = answ.login; + options.connectionOptions.password = answ.password; + options.connectionOptions.databaseName = answ.dbName; + options.connectionOptions.ssl = answ.ssl; + } else { + options.connectionOptions.databaseName = ( + await inquirer.prompt([ { - default: driver.standardSchema, - message: - "Database schema: (You can pass multiple values separated by comma)", - name: "schema", + default: options.connectionOptions.databaseName, + message: "Path to database file:", + name: "dbName", type: "input" } - ])) as any).schema; - } - connectionOptions.port = parseInt(answ.port, 10); - connectionOptions.host = answ.host; - connectionOptions.user = answ.login; - connectionOptions.password = answ.password; - connectionOptions.databaseName = answ.dbName; - connectionOptions.ssl = answ.ssl; - } else { - connectionOptions.databaseName = ((await inquirer.prompt([ + ]) + ).dbName; + } + + const ignoreSpecyficTables = ( + await inquirer.prompt([ { - default: "", - message: "Path to database file:", - name: "dbName", + default: + options.connectionOptions.skipTables.length === 0 + ? "All of them" + : "Ignore specific tables", + message: "Generate schema for tables:", + choices: ["All of them", "Ignore specific tables"], + name: "specyficTables", + type: "list" + } + ]) + ).specyficTables; + if (ignoreSpecyficTables === "Ignore specific tables") { + const { tableNames } = await inquirer.prompt({ + default: options.connectionOptions.skipTables.join(","), + message: "Table names(separated by comma)", + name: "tableNames", + type: "input" + }); + options.connectionOptions.skipTables = tableNames.split(","); + } else { + options.connectionOptions.skipTables = []; + } + + options.generationOptions.resultsPath = ( + await inquirer.prompt([ + { + default: options.generationOptions.resultsPath, + message: "Path where generated models should be stored:", + name: "output", type: "input" } - ])) as any).dbName; - } - generationOptions.resultsPath = ((await inquirer.prompt([ - { - default: path.resolve(process.cwd(), "output"), - message: "Path where generated models should be stored:", - name: "output", - type: "input" - } - ])) as any).output; - - if ( - connectionOptions.databaseType === "mssql" || - connectionOptions.databaseType === "postgres" - ) { - const { changeRequestTimeout } = (await inquirer.prompt([ - { - default: false, - message: "Do you want to change default sql query timeout?", - name: "changeRequestTimeout", - type: "confirm" - } - ])) as any; - if (changeRequestTimeout) { - const { timeout } = (await inquirer.prompt({ - message: "Query timeout(ms):", - name: "timeout", - type: "input", - validate(value) { - const valid = !Number.isNaN(parseInt(value, 10)); - return valid || "Please enter a valid number"; - } - })) as any; - connectionOptions.timeout = parseInt(timeout, 10); - } - } - const { customizeGeneration } = (await inquirer.prompt([ + ]) + ).output; + const { customizeGeneration } = await inquirer.prompt([ { default: false, message: "Do you want to customize generated model?", name: "customizeGeneration", type: "confirm" } - ])) as any; + ]); if (customizeGeneration) { - const customizations: string[] = ((await inquirer.prompt([ - { - choices: [ - { - checked: true, - name: "Generate config files", - value: "config" - }, - { - name: "Generate lazy relations", - value: "lazy" - }, - { - name: "Use ActiveRecord syntax for generated models", - value: "activeRecord" - }, - { - name: "Use custom naming strategy", - value: "namingStrategy" - }, - { - name: "Generate RelationId fields", - value: "relationId" - }, - { - name: "Omits schema identifier in generated entities", - value: "skipSchema" - }, - { - name: - "Generate constructor allowing partial initialization", - value: "constructor" - }, - { - name: "Use specific naming convention", - value: "namingConvention" - } - ], - message: "Available customizations", - name: "selected", - type: "checkbox" - } - ])) as any).selected; + const defaultGenerationOptions = getDefaultGenerationOptions(); + const customizations: string[] = ( + await inquirer.prompt([ + { + choices: [ + { + checked: !options.generationOptions.noConfigs, + name: "Generate config files", + value: "config" + }, + { + name: "Generate lazy relations", + value: "lazy", + checked: options.generationOptions.lazy + }, + { + name: + "Use ActiveRecord syntax for generated models", + value: "activeRecord", + checked: options.generationOptions.activeRecord + }, + { + name: "Use custom naming strategy", + value: "namingStrategy", + checked: !!options.generationOptions + .customNamingStrategyPath + }, + { + name: "Generate RelationId fields", + value: "relationId", + checked: options.generationOptions.relationIds + }, + { + name: + "Omits schema identifier in generated entities", + value: "skipSchema", + checked: options.generationOptions.skipSchema + }, + { + name: + "Generate constructor allowing partial initialization", + value: "constructor", + checked: + options.generationOptions.generateConstructor + }, + { + name: "Use specific naming convention", + value: "namingConvention", + checked: + options.generationOptions.convertCaseEntity !== + defaultGenerationOptions.convertCaseEntity || + options.generationOptions + .convertCaseProperty !== + defaultGenerationOptions.convertCaseProperty || + options.generationOptions.convertCaseFile !== + defaultGenerationOptions.convertCaseFile + }, + { + name: + "Pluralize OneToMany, ManyToMany relation names", + value: "pluralize", + checked: options.generationOptions.pluralizeNames + }, + { + name: "Generate index file", + value: "index", + checked: options.generationOptions.indexFile + }, + { + name: "Prefer default exports", + value: "defaultExport", + checked: + options.generationOptions.exportType === + "default" + } + ], + message: "Available customizations", + name: "selected", + type: "checkbox" + } + ]) + ).selected; - generationOptions.propertyVisibility = ((await inquirer.prompt([ - { - choices: ["public", "protected", "private", "none"], - message: - "Defines which visibility should have the generated property", - name: "propertyVisibility", - default: "none", - type: "list" - } - ])) as any).propertyVisibility; + options.generationOptions.propertyVisibility = ( + await inquirer.prompt([ + { + choices: ["public", "protected", "private", "none"], + message: + "Defines which visibility should have the generated property", + name: "propertyVisibility", + default: options.generationOptions.propertyVisibility, + type: "list" + } + ]) + ).propertyVisibility; - const { strictModeRaw } = (await inquirer.prompt([ - { - choices: ["none", "?", "!"], - message: "Mark fields as optional(?) or non-null(!)", - name: "strictModeRaw", - default: "none", - type: "list" - } - ])) as any; + options.generationOptions.strictMode = ( + await inquirer.prompt([ + { + choices: ["none", "?", "!"], + message: "Mark fields as optional(?) or non-null(!)", + name: "strictMode", + default: options.generationOptions.strictMode, + type: "list" + } + ]) + ).strictMode; - generationOptions.strictMode = - strictModeRaw === "none" ? false : strictModeRaw; - generationOptions.noConfigs = !customizations.includes("config"); - generationOptions.lazy = customizations.includes("lazy"); - generationOptions.activeRecord = customizations.includes( + options.generationOptions.noConfigs = !customizations.includes( + "config" + ); + options.generationOptions.pluralizeNames = customizations.includes( + "pluralize" + ); + options.generationOptions.lazy = customizations.includes("lazy"); + options.generationOptions.activeRecord = customizations.includes( "activeRecord" ); - generationOptions.relationIds = customizations.includes("relationId"); - generationOptions.skipSchema = customizations.includes("skipSchema"); - generationOptions.generateConstructor = customizations.includes( + options.generationOptions.relationIds = customizations.includes( + "relationId" + ); + options.generationOptions.skipSchema = customizations.includes( + "skipSchema" + ); + options.generationOptions.generateConstructor = customizations.includes( "constructor" ); + options.generationOptions.indexFile = customizations.includes("index"); + options.generationOptions.exportType = customizations.includes( + "defaultExport" + ) + ? "default" + : "named"; if (customizations.includes("namingStrategy")) { - const namingStrategyPath = ((await inquirer.prompt([ - { - default: path.resolve(process.cwd()), - message: "Path to custom naming strategy file:", - name: "namingStrategy", - type: "input", - validate(value) { - const valid = value === "" || fs.existsSync(value); - return ( - valid || - "Please enter a a valid path to custom naming strategy file" - ); + const namingStrategyPath = ( + await inquirer.prompt([ + { + default: + options.generationOptions.customNamingStrategyPath, + message: "Path to custom naming strategy file:", + name: "namingStrategy", + type: "input", + validate(value) { + const valid = value === "" || fs.existsSync(value); + return ( + valid || + "Please enter a a valid path to custom naming strategy file" + ); + } } - } - ])) as any).namingStrategy; + ]) + ).namingStrategy; if (namingStrategyPath && namingStrategyPath !== "") { - generationOptions.customNamingStrategyPath = namingStrategyPath; + options.generationOptions.customNamingStrategyPath = namingStrategyPath; } else { - generationOptions.customNamingStrategyPath = ""; + options.generationOptions.customNamingStrategyPath = ""; } } if (customizations.includes("namingConvention")) { - const namingConventions = (await inquirer.prompt([ + const namingConventions = await inquirer.prompt([ { choices: ["pascal", "param", "camel", "none"], - default: "pascal", + default: options.generationOptions.convertCaseFile, message: "Convert file names to specified case:", name: "fileCase", type: "list" }, { choices: ["pascal", "camel", "none"], - default: "pascal", + default: options.generationOptions.convertCaseEntity, message: "Convert class names to specified case:", name: "entityCase", type: "list" }, { choices: ["pascal", "camel", "none"], - default: "camel", + default: options.generationOptions.convertCaseProperty, message: "Convert property names to specified case:", name: "propertyCase", type: "list" } - ])) as any; - generationOptions.convertCaseFile = namingConventions.fileCase; - generationOptions.convertCaseProperty = + ]); + options.generationOptions.convertCaseFile = + namingConventions.fileCase; + options.generationOptions.convertCaseProperty = namingConventions.propertyCase; - generationOptions.convertCaseEntity = namingConventions.entityCase; + options.generationOptions.convertCaseEntity = + namingConventions.entityCase; } } - const { saveConfig } = (await inquirer.prompt([ + const { saveConfig } = await inquirer.prompt([ { - default: false, + choices: [ + "Yes, only model customization options", + "Yes, with connection details", + "No" + ], + default: "No", message: "Save configuration to config file?", name: "saveConfig", - type: "confirm" + type: "list" } - ])) as any; - if (saveConfig) { + ]); + if (saveConfig === "Yes, with connection details") { await fs.writeJson( path.resolve(process.cwd(), ".tomg-config"), - [connectionOptions, generationOptions], + [options.generationOptions, options.connectionOptions], { spaces: 2 } ); console.log(`[${new Date().toLocaleTimeString()}] Config file saved.`); console.warn( `\x1b[33m[${new Date().toLocaleTimeString()}] WARNING: Password was saved as plain text.\x1b[0m` ); + } else if (saveConfig === "Yes, only model customization options") { + await fs.writeJson( + path.resolve(process.cwd(), ".tomg-config"), + [options.generationOptions], + { spaces: 2 } + ); + console.log(`[${new Date().toLocaleTimeString()}] Config file saved.`); } - return { driver, connectionOptions, generationOptions }; + return options; } diff --git a/src/library.ts b/src/library.ts new file mode 100644 index 0000000..a7d8584 --- /dev/null +++ b/src/library.ts @@ -0,0 +1,18 @@ +import * as Engine from "./Engine"; +import * as IConnectionOptions from "./IConnectionOptions"; +import * as IGenerationOptions from "./IGenerationOptions"; +import * as NamingStrategy from "./NamingStrategy"; +import * as Utils from "./Utils"; + +export { Column } from "./models/Column"; +export { Entity } from "./models/Entity"; +export { Index } from "./models/Index"; +export { Relation } from "./models/Relation"; +export { RelationId } from "./models/RelationId"; +export { + Engine, + IConnectionOptions, + IGenerationOptions, + NamingStrategy, + Utils +}; diff --git a/src/models/Column.ts b/src/models/Column.ts new file mode 100644 index 0000000..f62271e --- /dev/null +++ b/src/models/Column.ts @@ -0,0 +1,25 @@ +import { ColumnType } from "typeorm"; + +export type Column = { + tscType: string; + tscName: string; + type: ColumnType | string; // TODO: remove ? + isUsedInRelationAsOwner?: true; // TODO: move to separate object/calulate when us + isUsedInRelationAsReferenced?: true; // TODO: move to separate object/calulate when us + + primary?: boolean; + generated?: true | "increment" | "uuid"; + default?: string; // ? + options: { + name: string; + length?: number; + width?: number; + nullable?: boolean; + unique?: boolean; // ? + precision?: number; + scale?: number; + unsigned?: boolean; + enum?: string[]; + array?: boolean; // ? + }; +}; diff --git a/src/models/ColumnInfo.ts b/src/models/ColumnInfo.ts deleted file mode 100644 index b373c99..0000000 --- a/src/models/ColumnInfo.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ColumnOptions } from "typeorm"; -import RelationInfo from "./RelationInfo"; - -export default class ColumnInfo { - public options: ColumnOptions = {}; - - public tsName: string = ""; - - public tsType: - | "number" - | "string" - | "boolean" - | "Date" - | "Buffer" - | "object" - | "string | object" - | "string | string[]" - | "any" - | string; - - public relations: RelationInfo[] = []; -} diff --git a/src/models/Entity.ts b/src/models/Entity.ts new file mode 100644 index 0000000..8c189f9 --- /dev/null +++ b/src/models/Entity.ts @@ -0,0 +1,21 @@ +import { Column } from "./Column"; +import { Relation } from "./Relation"; +import { Index } from "./Index"; +import { RelationId } from "./RelationId"; + +export type Entity = { + sqlName: string; + tscName: string; + + database?: string; + schema?: string; + + columns: Column[]; + relationIds: RelationId[]; + relations: Relation[]; + indices: Index[]; + // TODO: move to sub-object or use handlebars helpers(?) + fileImports: string[]; + activeRecord?: true; + generateConstructor?: true; +}; diff --git a/src/models/EntityInfo.ts b/src/models/EntityInfo.ts deleted file mode 100644 index b1cf4a7..0000000 --- a/src/models/EntityInfo.ts +++ /dev/null @@ -1,38 +0,0 @@ -import ColumnInfo from "./ColumnInfo"; -import IndexInfo from "./IndexInfo"; - -export default class EntityInfo { - public tsEntityName: string; - - public sqlEntityName: string; - - public Columns: ColumnInfo[]; - - public Imports: string[]; - - public UniqueImports: string[]; - - public Indexes: IndexInfo[]; - - public Schema?: string; - - public GenerateConstructor: boolean; - - public IsActiveRecord: boolean; - - public Database?: string; - - public relationImports() { - const imports: string[] = []; - this.Columns.forEach(column => { - column.relations.forEach(relation => { - if (this.tsEntityName !== relation.relatedTable) { - imports.push(relation.relatedTable); - } - }); - }); - this.UniqueImports = imports.filter( - (elem, index, self) => index === self.indexOf(elem) - ); - } -} diff --git a/src/models/Index.ts b/src/models/Index.ts new file mode 100644 index 0000000..1f171fa --- /dev/null +++ b/src/models/Index.ts @@ -0,0 +1,8 @@ +export type Index = { + name: string; + columns: string[]; + options: { + unique?: boolean; + }; + primary?: boolean; +}; diff --git a/src/models/IndexColumnInfo.ts b/src/models/IndexColumnInfo.ts deleted file mode 100644 index f4fa605..0000000 --- a/src/models/IndexColumnInfo.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default interface IndexColumnInfo { - name: string; -} diff --git a/src/models/IndexInfo.ts b/src/models/IndexInfo.ts deleted file mode 100644 index ac94f15..0000000 --- a/src/models/IndexInfo.ts +++ /dev/null @@ -1,8 +0,0 @@ -import IndexColumnInfo from "./IndexColumnInfo"; - -export default interface IndexInfo { - name: string; - columns: IndexColumnInfo[]; - isUnique: boolean; - isPrimaryKey: boolean; -} diff --git a/src/models/Relation.ts b/src/models/Relation.ts new file mode 100644 index 0000000..7c35c24 --- /dev/null +++ b/src/models/Relation.ts @@ -0,0 +1,12 @@ +import { JoinColumnOptions, RelationOptions } from "typeorm"; +import { JoinTableMultipleColumnsOptions } from "typeorm/decorator/options/JoinTableMultipleColumnsOptions"; + +export type Relation = { + relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"; + relatedTable: string; + relatedField: string; + fieldName: string; + relationOptions?: RelationOptions; + joinColumnOptions?: Required[]; + joinTableOptions?: JoinTableMultipleColumnsOptions; +}; diff --git a/src/models/RelationId.ts b/src/models/RelationId.ts new file mode 100644 index 0000000..bef6676 --- /dev/null +++ b/src/models/RelationId.ts @@ -0,0 +1,5 @@ +export type RelationId = { + fieldName: string; + fieldType: string; + relationField: string; +}; diff --git a/src/models/RelationInfo.ts b/src/models/RelationInfo.ts deleted file mode 100644 index d9a0b17..0000000 --- a/src/models/RelationInfo.ts +++ /dev/null @@ -1,50 +0,0 @@ -export default class RelationInfo { - public isOwner: boolean; - - public relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"; - - public relatedTable: string; - - public relatedColumn: string; - - public ownerTable: string; - - public ownerColumn: string; - - public joinColumn?: string; - - public inverseJoinColumn?: string; - - public actionOnDelete: - | "RESTRICT" - | "CASCADE" - | "SET NULL" - | "DEFAULT" - | "NO ACTION" - | null; - - public actionOnUpdate: - | "RESTRICT" - | "CASCADE" - | "SET NULL" - | "DEFAULT" - | null; - - public relationIdField: boolean = false; - - public get isOneToMany(): boolean { - return this.relationType === "OneToMany"; - } - - public get isManyToMany(): boolean { - return this.relationType === "ManyToMany"; - } - - public get isOneToOne(): boolean { - return this.relationType === "OneToOne"; - } - - public get isManyToOne(): boolean { - return this.relationType === "ManyToOne"; - } -} diff --git a/src/models/RelationInternal.ts b/src/models/RelationInternal.ts new file mode 100644 index 0000000..0d3923a --- /dev/null +++ b/src/models/RelationInternal.ts @@ -0,0 +1,12 @@ +import { OnDeleteType } from "typeorm/metadata/types/OnDeleteType"; +import { OnUpdateType } from "typeorm/metadata/types/OnUpdateType"; +import { Entity } from "./Entity"; + +export type RelationInternal = { + ownerTable: Entity; + relatedTable: Entity; + ownerColumns: string[]; + relatedColumns: string[]; + onDelete?: OnDeleteType; + onUpdate?: OnUpdateType; +}; diff --git a/src/models/RelationTempInfo.ts b/src/models/RelationTempInfo.ts deleted file mode 100644 index f6914f8..0000000 --- a/src/models/RelationTempInfo.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default interface RelationTempInfo { - ownerTable: string; - ownerColumnsNames: string[]; - referencedTable: string; - referencedColumnsNames: string[]; - actionOnDelete: - | "RESTRICT" - | "CASCADE" - | "SET NULL" - | "DEFAULT" - | "NO ACTION" - | null; - actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "DEFAULT" | null; - objectId: number | string; -} diff --git a/src/templates/entity.mst b/src/templates/entity.mst new file mode 100644 index 0000000..c9b57e8 --- /dev/null +++ b/src/templates/entity.mst @@ -0,0 +1,47 @@ +{{#*inline "Index"}} +@Index("{{name}}",[{{#columns}}"{{toPropertyName .}}",{{/columns~}}],{ {{json options}} }) +{{/inline}} +{{#*inline "Import"}} +import {{localImport (toEntityName .)}} from './{{toFileName .}}' +{{/inline}} +{{#*inline "Column"}} +{{#generated}}@PrimaryGeneratedColumn({ type:"{{type}}", {{/generated}}{{^generated}}@Column("{{type}}",{ {{#primary}}primary:{{primary}},{{/primary}}{{/generated}}{{json options}}{{#default}},default: {{.}},{{/default}} }) +{{printPropertyVisibility}}{{toPropertyName tscName}}{{strictMode}}:{{tscType}}{{#if options.nullable}} | null{{/if}}; + +{{/inline}} +{{#*inline "JoinColumnOptions"}} +{ name: "{{name}}", referencedColumnName: "{{toPropertyName referencedColumnName}}" }, +{{/inline}} +{{#*inline "Relation"}} +@{{relationType}}(()=>{{toEntityName relatedTable}},{{toPropertyName relatedTable}}=>{{toPropertyName relatedTable}}.{{toPropertyName relatedField}}{{#if relationOptions}},{ {{json relationOptions}} }{{/if}}) +{{#if joinColumnOptions}}@JoinColumn([{{#joinColumnOptions}}{{> JoinColumnOptions}}{{/joinColumnOptions}}]){{/if}} +{{#joinTableOptions}}@JoinTable({ name:"{{name}}", joinColumns:[{{#joinColumns}}{{> JoinColumnOptions}}{{/joinColumns}}],inverseJoinColumns:[{{#inverseJoinColumns}}{{> JoinColumnOptions}}{{/inverseJoinColumns}}],{{#database}}database:"{{.}}",{{/database}}{{#schema}}schema:"{{.}}"{{/schema}} }){{/joinTableOptions}} +{{printPropertyVisibility}}{{toPropertyName fieldName}}{{strictMode}}:{{toRelation (toEntityName relatedTable) relationType}}; + +{{/inline}} +{{#*inline "RelationId"}} +@RelationId(({{toPropertyName entityName}}:{{toEntityName entityName}})=>{{toPropertyName entityName}}.{{toPropertyName relationField}}) +{{printPropertyVisibility}}{{toPropertyName fieldName}}{{strictMode}}:{{fieldType}}; + +{{/inline}} +{{#*inline "Constructor"}} +{{printPropertyVisibility}}constructor(init?: Partial<{{toEntityName entityName}}>) { + {{#activeRecord}}super(); + {{/activeRecord}}Object.assign(this, init); +} +{{/inline}} +{{#*inline "Entity"}} +{{#indices}}{{> Index}}{{/indices~}} +@Entity("{{sqlName}}"{{#schema}} ,{schema:"{{.}}"{{#if ../database}}, database:"{{../database}}"{{/if}} } {{/schema}}) +export {{defaultExport}} class {{toEntityName tscName}}{{#activeRecord}} extends BaseEntity{{/activeRecord}} { + +{{#columns}}{{> Column}}{{/columns~}} +{{#relations}}{{> Relation}}{{/relations~}} +{{#relationIds}}{{> RelationId entityName=../tscName}}{{/relationIds~}} +{{#if generateConstructor}}{{>Constructor entityName=tscName}}{{/if~}} +} +{{/inline}} +import {BaseEntity,Column,Entity,Index,JoinColumn,JoinTable,ManyToMany,ManyToOne,OneToMany,OneToOne,PrimaryColumn,PrimaryGeneratedColumn,RelationId} from "typeorm"; +{{#fileImports}}{{> Import}}{{/fileImports}} + +{{> Entity}} diff --git a/src/templates/index.mst b/src/templates/index.mst new file mode 100644 index 0000000..4c7d5fe --- /dev/null +++ b/src/templates/index.mst @@ -0,0 +1,5 @@ +{{#entities~}} +import {{localImport (toEntityName tscName)}} from './{{toFileName tscName}}' +{{/entities}} + +export { {{#entities}}{{toEntityName tscName}},{{/entities~}} } diff --git a/src/templates/ormconfig.mst b/src/templates/ormconfig.mst new file mode 100644 index 0000000..800022e --- /dev/null +++ b/src/templates/ormconfig.mst @@ -0,0 +1,16 @@ +[ + { + "name": "default", + "type": "{{databaseType}}", + "host": "{{host}}", + "port": {{port}}, + "username": "{{user}}", + "password": "{{password}}", + "database": "{{databaseName}}",{{#schemaName}} + "schema": "{{.}}",{{/schemaName}} + "synchronize": false, + "entities": [ + "entities/*.js" + ] + } +] \ No newline at end of file diff --git a/src/templates/tsconfig.mst b/src/templates/tsconfig.mst new file mode 100644 index 0000000..474ae94 --- /dev/null +++ b/src/templates/tsconfig.mst @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true + } +} \ No newline at end of file diff --git a/test/configs/.eslintrc.js b/test/configs/.eslintrc.js new file mode 100644 index 0000000..c2a28ca --- /dev/null +++ b/test/configs/.eslintrc.js @@ -0,0 +1,30 @@ +module.exports = { + env: { + node: true, + }, + extends: [ + "airbnb-base", + "plugin:@typescript-eslint/recommended", + "prettier", + "prettier/@typescript-eslint" + ], + parser: "@typescript-eslint/parser", + parserOptions: { + project: "test/configs/tsconfig.json" + }, + plugins: ["@typescript-eslint"], + rules: { // TODO: remove some rule overrides after disabling eslint on model customization tests(?) + "import/extensions": ["off"], + "import/prefer-default-export": ["off"], + "@typescript-eslint/no-explicit-any": ["off"], + "@typescript-eslint/camelcase": ["off"], + "@typescript-eslint/class-name-casing": ["off"] + }, + settings: { + "import/resolver": { + node: { + extensions: [".ts"] + } + } + } +}; diff --git a/test/configs/tsconfig.json b/test/configs/tsconfig.json new file mode 100644 index 0000000..8d56403 --- /dev/null +++ b/test/configs/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "newLine": "LF", + "typeRoots": [ + "../../node_modules/@types" + ], + "resolveJsonModule": true, + }, + "include": [ + "../../output" + ] +} diff --git a/test/drivers/MssqlDriver.test.ts b/test/drivers/MssqlDriver.test.ts index 4a15204..19d90ff 100644 --- a/test/drivers/MssqlDriver.test.ts +++ b/test/drivers/MssqlDriver.test.ts @@ -2,10 +2,7 @@ import { expect } from "chai"; import * as MSSQL from "mssql"; import * as Sinon from "sinon"; import MssqlDriver from "../../src/drivers/MssqlDriver"; -import EntityInfo from "../../src/models/EntityInfo"; -import ColumnInfo from "../../src/models/ColumnInfo"; -import IndexInfo from "../../src/models/IndexInfo"; -import RelationInfo from "../../src/models/RelationInfo"; +import { Entity } from "../../src/models/Entity"; interface FakeResponse extends MSSQL.IResult { recordsets: MSSQL.IRecordSet[]; @@ -26,7 +23,7 @@ class FakeRecordset extends Array implements MSSQL.IRecordSet { } } -describe("MssqlDriver", function() { +describe("MssqlDriver", () => { let driver: MssqlDriver; const sandbox = Sinon.sandbox.create(); @@ -50,15 +47,19 @@ describe("MssqlDriver", function() { return response; } }); - const result = await driver.GetAllTables("schema", "db"); - const expectedResult = [] as EntityInfo[]; - const y = new EntityInfo(); - y.tsEntityName = "name"; - y.sqlEntityName = "name"; - y.Schema = "schema"; - y.Columns = [] as ColumnInfo[]; - y.Indexes = [] as IndexInfo[]; - y.Database = ""; + const result = await driver.GetAllTables("schema", "db", []); + const expectedResult = [] as Entity[]; + const y: Entity = { + columns: [], + indices: [], + relationIds: [], + relations: [], + sqlName: "name", + tscName: "name", + schema: "schema", + database: "", + fileImports: [] + }; expectedResult.push(y); expect(result).to.be.deep.equal(expectedResult); }); @@ -73,7 +74,7 @@ describe("MssqlDriver", function() { COLUMN_DEFAULT: "'a'", COLUMN_NAME: "name", DATA_TYPE: "int", - IS_NULLABLE: "YES", + IS_NULLABLE: "NO", NUMERIC_PRECISION: 0, NUMERIC_SCALE: 0, IsIdentity: 1 @@ -82,27 +83,31 @@ describe("MssqlDriver", function() { } }); - const entities = [] as EntityInfo[]; - const y = new EntityInfo(); - y.tsEntityName = "name"; - y.Columns = [] as ColumnInfo[]; - y.Indexes = [] as IndexInfo[]; - y.Database = ""; + const entities = [] as Entity[]; + const y: Entity = { + columns: [], + indices: [], + relationIds: [], + relations: [], + sqlName: "name", + tscName: "name", + schema: "schema", + database: "", + fileImports: [] + }; entities.push(y); - const expected: EntityInfo[] = JSON.parse(JSON.stringify(entities)); - expected[0].Columns.push({ + const expected: Entity[] = JSON.parse(JSON.stringify(entities)); + expected[0].columns.push({ options: { - default: `() => "'a'"`, - nullable: true, - generated: true, - name: "name", - unique: false, - type: "int" + name: "name" }, - tsName: "name", - tsType: "number", - relations: [] as RelationInfo[] + type: "int", + generated: true, + default: `() => "'a'"`, + tscName: "name", + tscType: "number" }); + const result = await driver.GetCoulmnsFromEntity( entities, "schema", diff --git a/test/integration/entityTypes/mariadb/entity/Post.ts b/test/integration/entityTypes/mariadb/entity/Post.ts index 972bd30..271bad0 100644 --- a/test/integration/entityTypes/mariadb/entity/Post.ts +++ b/test/integration/entityTypes/mariadb/entity/Post.ts @@ -116,4 +116,10 @@ export class Post { @Column("geometrycollection") geometrycollection: string; + + @Column("set", { + enum: ["A", "B", "C"], + default: ["A", "B"] + }) + roles: ("A" | "B" | "C")[] } diff --git a/test/integration/entityTypes/mssql/entity/Post.ts b/test/integration/entityTypes/mssql/entity/Post.ts index dc00e73..3f15287 100644 --- a/test/integration/entityTypes/mssql/entity/Post.ts +++ b/test/integration/entityTypes/mssql/entity/Post.ts @@ -2,7 +2,6 @@ import { Entity, PrimaryColumn, Column } from "typeorm"; @Entity("Post") export class Post { - @PrimaryColumn() id: number; @@ -91,7 +90,7 @@ export class Post { hierarchyid: string; @Column("sql_variant") - sql_variant: string; + sqlVariant: string; @Column("timestamp") timestamp: Date; @@ -107,5 +106,4 @@ export class Post { @Column("geography") geography: string; - } diff --git a/test/integration/entityTypes/mysql/entity/Post.ts b/test/integration/entityTypes/mysql/entity/Post.ts index f76777f..d529f2e 100644 --- a/test/integration/entityTypes/mysql/entity/Post.ts +++ b/test/integration/entityTypes/mysql/entity/Post.ts @@ -118,4 +118,10 @@ export class Post { @Column("geometrycollection") geometrycollection: string; + + @Column("set", { + enum: ["A", "B", "C"], + default: ["A", "B"] + }) + roles: ("A" | "B" | "C")[] } diff --git a/test/integration/entityTypes/oracle/entity/Post.ts b/test/integration/entityTypes/oracle/entity/Post.ts index ea69e96..ced4844 100644 --- a/test/integration/entityTypes/oracle/entity/Post.ts +++ b/test/integration/entityTypes/oracle/entity/Post.ts @@ -2,7 +2,6 @@ import { Entity, PrimaryColumn, Column } from "typeorm"; @Entity("Post") export class Post { - @PrimaryColumn() id: number; @@ -58,7 +57,7 @@ export class Post { real: number; @Column("double precision") - double_precision: number; + doublePrecision: number; @Column("date") date: Date; @@ -67,16 +66,16 @@ export class Post { timestamp: Date; @Column("timestamp with time zone") - timestamp_with_time_zone: Date; + timestampWithTimeZone: Date; @Column("timestamp with local time zone") - timestamp_with_local_time_zone: Date; + timestampWithLocalTimeZone: Date; @Column("interval year to month") - interval_year_to_month: string; + intervalYearToMonth: string; @Column("interval day to second") - interval_day_to_second: string; + intervalDayToSecond: string; @Column("bfile") bfile: Buffer; @@ -95,5 +94,4 @@ export class Post { @Column("urowid") urowid: number; - } diff --git a/test/integration/entityTypes/postgres/entity/Post.ts b/test/integration/entityTypes/postgres/entity/Post.ts index b715176..be2d592 100644 --- a/test/integration/entityTypes/postgres/entity/Post.ts +++ b/test/integration/entityTypes/postgres/entity/Post.ts @@ -81,7 +81,7 @@ export class Post { varbit: string; @Column("bit varying") - bit_varying: string; + bitVarying: string; @Column("timetz") timetz: string; @@ -93,10 +93,10 @@ export class Post { timestamp: Date; @Column("timestamp without time zone") - timestamp_without_time_zone: Date; + timestampWithoutTimeZone: Date; @Column("timestamp with time zone") - timestamp_with_time_zone: Date; + timestampWithTimeZone: Date; @Column("date") date: string; @@ -104,10 +104,10 @@ export class Post { @Column("time") time: string; @Column("time without time zone") - time_without_time_zone: string; + timeWithoutTimeZone: string; @Column("time with time zone") - time_with_time_zone: string; + timeWithTimeZone: string; @Column("interval") interval: any; diff --git a/test/integration/entityTypes/postgres/entity/PostArrays.ts b/test/integration/entityTypes/postgres/entity/PostArrays.ts index fde1012..5b7a6ad 100644 --- a/test/integration/entityTypes/postgres/entity/PostArrays.ts +++ b/test/integration/entityTypes/postgres/entity/PostArrays.ts @@ -2,7 +2,6 @@ import { Entity, PrimaryColumn, Column } from "typeorm"; @Entity("PostArrays") export class PostArrays { - @PrimaryColumn() id: number; @@ -82,7 +81,7 @@ export class PostArrays { varbit: string[]; @Column("bit varying", { array: true }) - bit_varying: string[]; + bitVarying: string[]; @Column("timetz", { array: true }) timetz: string[]; @@ -97,7 +96,7 @@ export class PostArrays { // timestamp_without_time_zone: Date[]; @Column("timestamp with time zone", { array: true }) - timestamp_with_time_zone: Date[]; + timestampWithTimeZone: Date[]; @Column("date", { array: true }) date: string[]; @@ -105,10 +104,10 @@ export class PostArrays { @Column("time", { array: true }) time: string[]; @Column("time without time zone", { array: true }) - time_without_time_zone: string[]; + timeWithoutTimeZone: string[]; @Column("time with time zone", { array: true }) - time_with_time_zone: string[]; + timeWithTimeZone: string[]; @Column("interval", { array: true }) interval: any[]; @@ -187,5 +186,4 @@ export class PostArrays { @Column("daterange", { array: true }) daterange: string[]; - } diff --git a/test/integration/entityTypes/sqlite/entity/Post.ts b/test/integration/entityTypes/sqlite/entity/Post.ts index 73326e4..24d4aae 100644 --- a/test/integration/entityTypes/sqlite/entity/Post.ts +++ b/test/integration/entityTypes/sqlite/entity/Post.ts @@ -2,7 +2,6 @@ import { Entity, PrimaryColumn, Column } from "typeorm"; @Entity("Post") export class Post { - @PrimaryColumn() id: number; @@ -34,7 +33,7 @@ export class Post { bigint: string; @Column("unsigned big int") - unsigned_big_int: string; + unsignedBigInt: string; @Column("character") character: string; @@ -43,13 +42,13 @@ export class Post { varchar: string; @Column("varying character") - varying_character: string; + varyingCharacter: string; @Column("nchar") nchar: string; @Column("native character") - native_character: string; + nativeCharacter: string; @Column("nvarchar") nvarchar: string; @@ -88,5 +87,4 @@ export class Post { @Column("datetime") datetime: Date; - } diff --git a/test/integration/examples/sample1-simple-entity/entity/Post.ts b/test/integration/examples/sample1-simple-entity/entity/Post.ts index acc4bc1..3511066 100644 --- a/test/integration/examples/sample1-simple-entity/entity/Post.ts +++ b/test/integration/examples/sample1-simple-entity/entity/Post.ts @@ -1,8 +1,13 @@ -import { Column, Entity, PrimaryGeneratedColumn, Index, Generated } from "typeorm"; +import { + Column, + Entity, + PrimaryGeneratedColumn, + Index, + Generated +} from "typeorm"; @Entity("Post") export class Post { - @PrimaryGeneratedColumn() id: number; @@ -13,8 +18,8 @@ export class Post { text: string; @Column("int", { - nullable: false + // Columns are non-nullable by default + // nullable: false }) likesCount: number; - } diff --git a/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts b/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts index a0f1a1e..c6012f4 100644 --- a/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts +++ b/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts @@ -1,8 +1,14 @@ -import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } from "typeorm"; +import { + PrimaryGeneratedColumn, + Column, + Entity, + OneToOne, + JoinColumn, + Index +} from "typeorm"; @Entity("EverythingEntity") export class EverythingEntity { - //TODO: change to check column types per database engine @PrimaryGeneratedColumn() id: number; @@ -68,5 +74,4 @@ export class EverythingEntity { // @UpdateDateColumn() // updatedDate: Date; - } diff --git a/test/integration/examples/sample18-lazy-relations/entity/Author.ts b/test/integration/examples/sample18-lazy-relations/entity/Author.ts index 0d3d178..7a2bd65 100644 --- a/test/integration/examples/sample18-lazy-relations/entity/Author.ts +++ b/test/integration/examples/sample18-lazy-relations/entity/Author.ts @@ -1,9 +1,14 @@ -import { Column, Entity, Index, PrimaryGeneratedColumn, OneToMany } from "typeorm" -import {Post} from "./Post"; +import { + Column, + Entity, + Index, + PrimaryGeneratedColumn, + OneToMany +} from "typeorm"; +import { Post } from "./Post"; @Entity("Author") export class Author { - @PrimaryGeneratedColumn() id: number; @@ -12,6 +17,7 @@ export class Author { @OneToMany(type => Post, post => post.author, { // cascade: true + lazy: true }) posts: Promise; @@ -21,5 +27,4 @@ export class Author { // asPromise() { // return Promise.resolve(this); // } - } diff --git a/test/integration/examples/sample18-lazy-relations/entity/Category.ts b/test/integration/examples/sample18-lazy-relations/entity/Category.ts index 410df9b..4b7632f 100644 --- a/test/integration/examples/sample18-lazy-relations/entity/Category.ts +++ b/test/integration/examples/sample18-lazy-relations/entity/Category.ts @@ -1,16 +1,23 @@ -import { Column, Entity, Index, PrimaryGeneratedColumn, VersionColumn, ManyToMany } from "typeorm" -import {Post} from "./Post"; +import { + Column, + Entity, + Index, + PrimaryGeneratedColumn, + VersionColumn, + ManyToMany +} from "typeorm"; +import { Post } from "./Post"; @Entity("Category") export class Category { - @PrimaryGeneratedColumn() id: number; @Column() name: string; - @ManyToMany(type => Post, post => post.categorys) + @ManyToMany(type => Post, post => post.categories, { + lazy: true + }) posts: Promise; - } diff --git a/test/integration/examples/sample18-lazy-relations/entity/Post.ts b/test/integration/examples/sample18-lazy-relations/entity/Post.ts index 6d74a76..0209d7e 100644 --- a/test/integration/examples/sample18-lazy-relations/entity/Post.ts +++ b/test/integration/examples/sample18-lazy-relations/entity/Post.ts @@ -1,10 +1,17 @@ -import { Column, Entity, Index, PrimaryGeneratedColumn, ManyToOne, ManyToMany, JoinTable } from "typeorm" +import { + Column, + Entity, + Index, + PrimaryGeneratedColumn, + ManyToOne, + ManyToMany, + JoinTable +} from "typeorm"; import { Author } from "./Author"; import { Category } from "./Category"; @Entity("Post") export class Post { - @PrimaryGeneratedColumn() id: number; @@ -15,16 +22,17 @@ export class Post { text: string; @ManyToOne(type => Author, author => author.posts, { + lazy: true, // cascade: ["insert"], - onDelete: "SET NULL", - onUpdate: "CASCADE" + onDelete: "SET NULL" + // onUpdate: "CASCADE" - onUpdate not supported on oracledb }) author: Promise; @ManyToMany(type => Category, category => category.posts, { + lazy: true // cascade: true }) @JoinTable() - categorys: Promise; - + categories: Promise; } diff --git a/test/integration/examples/sample3-many-to-one/entity/Post.ts b/test/integration/examples/sample3-many-to-one/entity/Post.ts index 4505194..01a5140 100644 --- a/test/integration/examples/sample3-many-to-one/entity/Post.ts +++ b/test/integration/examples/sample3-many-to-one/entity/Post.ts @@ -1,4 +1,12 @@ -import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm"; +import { + PrimaryGeneratedColumn, + Column, + Entity, + OneToOne, + OneToMany, + ManyToOne, + JoinColumn +} from "typeorm"; import { PostDetails } from "./PostDetails"; import { PostCategory } from "./PostCategory"; import { PostAuthor } from "./PostAuthor"; @@ -8,7 +16,6 @@ import { PostMetadata } from "./PostMetadata"; @Entity("Post") export class Post { - @PrimaryGeneratedColumn() id: number; @@ -20,41 +27,40 @@ export class Post { // post has relation with category, however inverse relation is not set (category does not have relation with post set) @ManyToOne(type => PostCategory, { - cascade: true, - onDelete: 'CASCADE' + // cascade: true, + onDelete: "CASCADE" }) category: PostCategory; // post has relation with details. cascade inserts here means if new PostDetails instance will be set to this // relation it will be inserted automatically to the db when you save this Post entity @ManyToOne(type => PostDetails, details => details.posts, { - cascade: true, + // cascade: true, }) details: PostDetails; // post has relation with details. cascade update here means if new PostDetail instance will be set to this relation // it will be inserted automatically to the db when you save this Post entity @ManyToOne(type => PostImage, image => image.posts, { - cascade: true, + // cascade: true, }) image: PostImage; // post has relation with details. cascade update here means if new PostDetail instance will be set to this relation // it will be inserted automatically to the db when you save this Post entity @ManyToOne(type => PostMetadata, metadata => metadata.posts, { - cascade: true, + // cascade: true, }) metadata: PostMetadata | null; // post has relation with details. full cascades here @ManyToOne(type => PostInformation, information => information.posts, { - cascade: true, - onDelete: 'CASCADE' + // cascade: true, + onDelete: "CASCADE" }) information: PostInformation; // post has relation with details. not cascades here. means cannot be persisted, updated or removed @ManyToOne(type => PostAuthor, author => author.posts) author: PostAuthor; - } diff --git a/test/integration/examples/sample4-many-to-many/entity/Post.ts b/test/integration/examples/sample4-many-to-many/entity/Post.ts index 83b80c0..a3e219c 100644 --- a/test/integration/examples/sample4-many-to-many/entity/Post.ts +++ b/test/integration/examples/sample4-many-to-many/entity/Post.ts @@ -1,14 +1,23 @@ -import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; -import {PostDetail} from "./PostDetail"; -import {PostCategory} from "./PostCategory"; -import {PostAuthor} from "./PostAuthor"; -import {PostInformation} from "./PostInformation"; -import {PostImage} from "./PostImage"; -import {PostMetadata} from "./PostMetadata"; +import { + PrimaryGeneratedColumn, + Column, + Entity, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { PostDetail } from "./PostDetail"; +import { PostCategory } from "./PostCategory"; +import { PostAuthor } from "./PostAuthor"; +import { PostInformation } from "./PostInformation"; +import { PostImage } from "./PostImage"; +import { PostMetadata } from "./PostMetadata"; @Entity("Post") export class Post { - @PrimaryGeneratedColumn() id: number; @@ -20,15 +29,15 @@ export class Post { // post has relation with category, however inverse relation is not set (category does not have relation with post set) @ManyToMany(type => PostCategory, { - cascade: true + // cascade: true }) @JoinTable() - postCategorys: PostCategory[]; + postCategories: PostCategory[]; // post has relation with details. cascade inserts here means if new PostDetails instance will be set to this // relation it will be inserted automatically to the db when you save this Post entity @ManyToMany(type => PostDetail, details => details.posts, { - cascade: true + // cascade: true }) @JoinTable() postDetails: PostDetail[]; @@ -36,7 +45,7 @@ export class Post { // post has relation with details. cascade update here means if new PostDetail instance will be set to this relation // it will be inserted automatically to the db when you save this Post entity @ManyToMany(type => PostImage, image => image.posts, { - cascade: true + // cascade: true }) @JoinTable() postImages: PostImage[]; @@ -45,11 +54,11 @@ export class Post { // it will be inserted automatically to the db when you save this Post entity @ManyToMany(type => PostMetadata, metadata => metadata.posts) @JoinTable() - postMetadatas: PostMetadata[]; + postMetadata: PostMetadata[]; // post has relation with details. full cascades here @ManyToMany(type => PostInformation, information => information.posts, { - cascade: true + // cascade: true }) @JoinTable() postInformations: PostInformation[]; @@ -58,5 +67,4 @@ export class Post { @ManyToMany(type => PostAuthor, author => author.posts) @JoinTable() postAuthors: PostAuthor[]; - } diff --git a/test/integration/examples/sample4-many-to-many/entity/PostMetadata.ts b/test/integration/examples/sample4-many-to-many/entity/PostMetadata.ts index 9bb0f38..280ff53 100644 --- a/test/integration/examples/sample4-many-to-many/entity/PostMetadata.ts +++ b/test/integration/examples/sample4-many-to-many/entity/PostMetadata.ts @@ -1,16 +1,24 @@ -import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; -import {Post} from "./Post"; +import { + PrimaryGeneratedColumn, + Column, + Entity, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { Post } from "./Post"; @Entity("PostMetadata") export class PostMetadata { - @PrimaryGeneratedColumn() id: number; @Column() description: string; - @ManyToMany(type => Post, post => post.postMetadatas) + @ManyToMany(type => Post, post => post.postMetadata) posts: Post[]; - } diff --git a/test/integration/github-issues/117/entity/Post.ts b/test/integration/github-issues/117/entity/Post.ts new file mode 100644 index 0000000..b408da2 --- /dev/null +++ b/test/integration/github-issues/117/entity/Post.ts @@ -0,0 +1,29 @@ +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { Section } from "./Section"; + +@Entity("Post") +export class Post { + @Column("int", { + primary: true, + name: "Id" + }) + id: number; + + @OneToOne(type => Section, section => section.post) + @JoinColumn([ + { name: "work", referencedColumnName: "work" }, + { name: "section", referencedColumnName: "section" } + ]) + section: Section; +} diff --git a/test/integration/github-issues/117/entity/Section.ts b/test/integration/github-issues/117/entity/Section.ts new file mode 100644 index 0000000..b67b276 --- /dev/null +++ b/test/integration/github-issues/117/entity/Section.ts @@ -0,0 +1,32 @@ +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; +import { Post } from "./Post"; + +@Entity("Section") +export class Section { + @Column("int", { + primary: true, + name: "work" + }) + work: number; + + @Column("int", { + primary: true, + name: "section" + }) + section: number; + + @OneToOne(type => Post, Post => Post.id) + post: Post; +} diff --git a/test/integration/github-issues/135/entity/Post.ts b/test/integration/github-issues/135/entity/Post.ts index cdce663..b637582 100644 --- a/test/integration/github-issues/135/entity/Post.ts +++ b/test/integration/github-issues/135/entity/Post.ts @@ -1,26 +1,36 @@ -import { Index, Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; import { PostAuthor } from "./PostAuthor"; import { PostCategory } from "./PostCategory"; - -@Index("travel_travelplanextra_travel_plan_id_extra_id_f825ca51_uniq",["postAuthor","postCategory",],{unique:true}) +@Index( + "travel_travelplanextra_travel_plan_id_extra_id_f825ca51_uniq", + ["postAuthor", "postCategory"], + { unique: true } +) @Entity("Post") export class Post { - @Column("int", { - nullable: false, primary: true, - name: "Id" + name: "id" }) - Id: number; + id: number; - @ManyToOne(type => PostAuthor, PostAuthor => PostAuthor.Id) + @ManyToOne(type => PostAuthor, PostAuthor => PostAuthor.id) @JoinColumn() postAuthor: PostAuthor; - - @ManyToOne(type => PostCategory, PostCategory => PostCategory.Id) + @ManyToOne(type => PostCategory, PostCategory => PostCategory.id) @JoinColumn() postCategory: PostCategory; - } diff --git a/test/integration/github-issues/135/entity/PostAuthor.ts b/test/integration/github-issues/135/entity/PostAuthor.ts index db8ca99..0a649ae 100644 --- a/test/integration/github-issues/135/entity/PostAuthor.ts +++ b/test/integration/github-issues/135/entity/PostAuthor.ts @@ -1,20 +1,26 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostAuthor") export class PostAuthor { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToMany(type => Post, Post => Post.Id) - posts:Post[]; - + @OneToMany(type => Post, Post => Post.id) + posts: Post[]; } diff --git a/test/integration/github-issues/135/entity/PostCategory.ts b/test/integration/github-issues/135/entity/PostCategory.ts index 5804e3f..675f571 100644 --- a/test/integration/github-issues/135/entity/PostCategory.ts +++ b/test/integration/github-issues/135/entity/PostCategory.ts @@ -1,20 +1,26 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostCategory") export class PostCategory { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToMany(type => Post, Post => Post.Id) - posts:Post[]; - + @OneToMany(type => Post, Post => Post.id) + posts: Post[]; } diff --git a/test/integration/github-issues/183/entity/Client.ts b/test/integration/github-issues/183/entity/Client.ts new file mode 100644 index 0000000..e8b856d --- /dev/null +++ b/test/integration/github-issues/183/entity/Client.ts @@ -0,0 +1,19 @@ +import { PrimaryGeneratedColumn, Entity, ManyToMany, JoinTable } from "typeorm"; +import { ClientCategory } from "./ClientCategory"; + +@Entity("Client") +export class Client { + @PrimaryGeneratedColumn() + id: number; + + @ManyToMany( + () => ClientCategory, + (clientCategory: ClientCategory) => clientCategory.clients + ) + @JoinTable({ + name: "client_categories", + joinColumn: { name: "client_id" }, + inverseJoinColumn: { name: "category_id" } + }) + clientCategories: ClientCategory[]; +} diff --git a/test/integration/github-issues/183/entity/ClientCategory.ts b/test/integration/github-issues/183/entity/ClientCategory.ts new file mode 100644 index 0000000..b7aae65 --- /dev/null +++ b/test/integration/github-issues/183/entity/ClientCategory.ts @@ -0,0 +1,11 @@ +import { Entity, PrimaryGeneratedColumn, ManyToMany } from "typeorm"; +import { Client } from "./Client"; + +@Entity("ClientCategory") +export class ClientCategory { + @PrimaryGeneratedColumn() + id: number; + + @ManyToMany(() => Client, (client: Client) => client.clientCategories) + clients: Client[]; +} diff --git a/test/integration/github-issues/227/entity/Post.ts b/test/integration/github-issues/227/entity/Post.ts new file mode 100644 index 0000000..20ce4c5 --- /dev/null +++ b/test/integration/github-issues/227/entity/Post.ts @@ -0,0 +1,15 @@ +import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } from "typeorm"; + +@Entity("Post") +export class Post { + + @PrimaryGeneratedColumn() + id: number; + + @Column("varchar", { nullable: true }) + title: string | null; + + @Column() + text: string; + +} diff --git a/test/integration/github-issues/39/entity/Post.ts b/test/integration/github-issues/39/entity/Post.ts index 378587a..52b18d8 100644 --- a/test/integration/github-issues/39/entity/Post.ts +++ b/test/integration/github-issues/39/entity/Post.ts @@ -1,28 +1,30 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm"; -import {User} from "./User"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + JoinColumn +} from "typeorm"; +import { User } from "./User"; - -@Entity("Post",{schema:"sch1"}) +@Entity("Post", { schema: "sch1" }) export class Post { + @Column("integer", { + primary: true, + name: "id" + }) + id: number; - @Column("integer",{ - nullable:false, - primary:true, - name:"id" - }) - id:number; - - - - @ManyToOne(type=>User, userId=>userId.posts) - @JoinColumn({ name:"userId"}) - userId:User; - - - @Column("text",{ - nullable:true, - name:"body" - }) - body:string; + @ManyToOne(type => User, user => user.posts) + @JoinColumn({ name: "userId" }) + user: User; + @Column("text", { + nullable: true, + name: "body" + }) + body: string; } diff --git a/test/integration/github-issues/39/entity/User.ts b/test/integration/github-issues/39/entity/User.ts index a709565..8370780 100644 --- a/test/integration/github-issues/39/entity/User.ts +++ b/test/integration/github-issues/39/entity/User.ts @@ -1,27 +1,29 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm"; -import {Post} from "./Post"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + JoinColumn +} from "typeorm"; +import { Post } from "./Post"; - -@Entity("User",{schema:"sch2"}) +@Entity("User", { schema: "sch2" }) export class User { + @Column("integer", { + primary: true, + name: "id" + }) + id: number; - @Column("integer",{ - nullable:false, - primary:true, - name:"id" - }) - id:number; - - - @Column("text",{ - nullable:true, - name:"name" - }) - name:string; - - - - @OneToMany(type=>Post, posts=>posts.userId) - posts:Post[]; + @Column("text", { + nullable: true, + name: "name" + }) + name: string; + @OneToMany(type => Post, posts => posts.user) + posts: Post[]; } diff --git a/test/integration/github-issues/57/entity/Post.ts b/test/integration/github-issues/57/entity/Post.ts index b7fdf4e..69eee28 100644 --- a/test/integration/github-issues/57/entity/Post.ts +++ b/test/integration/github-issues/57/entity/Post.ts @@ -1,20 +1,25 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm"; - +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + JoinColumn +} from "typeorm"; @Entity("Post") export class Post { + @Column("integer", { + primary: true, + name: "id" + }) + id: number; - @Column("integer",{ - nullable:false, - primary:true, - name:"id" - }) - id:number; + @Column({ unique: true }) + body: string; - @Column({unique:true}) - body:string; - @Column() - body2:string; - + body2: string; } diff --git a/test/integration/github-issues/58/entity/Feedextrainfo.ts b/test/integration/github-issues/58/entity/Feedextrainfo.ts new file mode 100644 index 0000000..bdd1a4d --- /dev/null +++ b/test/integration/github-issues/58/entity/Feedextrainfo.ts @@ -0,0 +1,46 @@ +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { Users } from "./Users"; +import { Quests } from "./Quests"; + +@Entity("feedextrainfo") +@Index("feedExtraInfo_FeedOwnerId_idx", ["feedOwnerId"], { unique: true }) +@Index("feedExtraInfo_ReaderId_idx", ["readerId"], { unique: true }) +@Index("feedExtraInfo_QuestId_idx", ["questId"], { unique: true }) +export class Feedextrainfo { + @PrimaryColumn({ name: "FeedOwnerId" }) + feedOwnerId: number; + + @PrimaryColumn({ name: "QuestId" }) + questId: number; + + @PrimaryColumn({ name: "ReaderId" }) + readerId: number; + + @OneToOne(type => Users, FeedOwnerId => FeedOwnerId.feedextrainfo) + @JoinColumn({ name: "FeedOwnerId" }) + feedOwner: Users; + + @OneToOne(type => Quests, QuestId => QuestId.feedextrainfo) + @JoinColumn({ name: "QuestId" }) + quest: Quests; + + @OneToOne(type => Users, ReaderId => ReaderId.feedextrainfo2) + @JoinColumn({ name: "ReaderId" }) + reader: Users; + + @Column("int", { + name: "MostUpdatedFeedEntryIdUserRead" + }) + mostUpdatedFeedEntryIdUserRead: number; +} diff --git a/test/integration/github-issues/58/entity/Quests.ts b/test/integration/github-issues/58/entity/Quests.ts new file mode 100644 index 0000000..a4b2362 --- /dev/null +++ b/test/integration/github-issues/58/entity/Quests.ts @@ -0,0 +1,25 @@ +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { Feedextrainfo } from "./Feedextrainfo"; + +@Entity("quests") +export class Quests { + @Column("int", { + primary: true, + name: "QuestId" + }) + questId: number; + + @OneToOne(type => Feedextrainfo, feedextrainfo => feedextrainfo.quest) + feedextrainfo: Feedextrainfo; +} diff --git a/test/integration/github-issues/58/entity/Users.ts b/test/integration/github-issues/58/entity/Users.ts new file mode 100644 index 0000000..06d1560 --- /dev/null +++ b/test/integration/github-issues/58/entity/Users.ts @@ -0,0 +1,28 @@ +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; +import { Feedextrainfo } from "./Feedextrainfo"; + +@Entity("users") +export class Users { + @Column("int", { + primary: true, + name: "UserId" + }) + userId: number; + + @OneToOne(type => Feedextrainfo, feedextrainfo => feedextrainfo.feedOwner) + feedextrainfo: Feedextrainfo; + + @OneToOne(type => Feedextrainfo, feedextrainfo2 => feedextrainfo2.reader) + feedextrainfo2: Feedextrainfo; +} diff --git a/test/integration/github-issues/58/entity/feedextrainfo.ts b/test/integration/github-issues/58/entity/feedextrainfo.ts deleted file mode 100644 index 2721cb9..0000000 --- a/test/integration/github-issues/58/entity/feedextrainfo.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable} from "typeorm"; -import {users} from "./users"; -import {quests} from "./quests"; - - -@Entity("feedextrainfo") -@Index("feedExtraInfo_FeedOwnerId_idx",["feedOwnerId",],{unique:true}) -@Index("feedExtraInfo_ReaderId_idx",["readerId",],{unique:true}) -@Index("feedExtraInfo_QuestId_idx",["questId",],{unique:true}) -export class feedextrainfo { - - - @OneToOne(type=>users, FeedOwnerId=>FeedOwnerId.feedextrainfo,{primary:true, nullable:false, }) - @JoinColumn({ name:'FeedOwnerId'}) - feedOwnerId:users; - - - - @OneToOne(type=>quests, QuestId=>QuestId.feedextrainfo,{primary:true, nullable:false, }) - @JoinColumn({ name:'QuestId'}) - questId:quests; - - - - @OneToOne(type=>users, ReaderId=>ReaderId.feedextrainfo2,{primary:true, nullable:false, }) - @JoinColumn({ name:'ReaderId'}) - readerId:users; - - - @Column("int",{ - nullable:false, - name:"MostUpdatedFeedEntryIdUserRead" - }) - MostUpdatedFeedEntryIdUserRead:number; - -} diff --git a/test/integration/github-issues/58/entity/quests.ts b/test/integration/github-issues/58/entity/quests.ts deleted file mode 100644 index acdc56d..0000000 --- a/test/integration/github-issues/58/entity/quests.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable} from "typeorm"; -import {feedextrainfo} from "./feedextrainfo"; - - -@Entity("quests") -export class quests { - - @Column("int",{ - nullable:false, - primary:true, - name:"QuestId" - }) - QuestId:number; - - - - @OneToOne(type=>feedextrainfo, feedextrainfo=>feedextrainfo.questId) - feedextrainfo:feedextrainfo; - -} diff --git a/test/integration/github-issues/58/entity/users.ts b/test/integration/github-issues/58/entity/users.ts deleted file mode 100644 index 754e1e1..0000000 --- a/test/integration/github-issues/58/entity/users.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable} from "typeorm"; -import {feedextrainfo} from "./feedextrainfo"; - - -@Entity("users") -export class users { - - @Column("int",{ - nullable:false, - primary:true, - name:"UserId" - }) - UserId:number; - - - - @OneToOne(type=>feedextrainfo, feedextrainfo=>feedextrainfo.feedOwnerId) - feedextrainfo:feedextrainfo; - - - - @OneToOne(type=>feedextrainfo, feedextrainfo2=>feedextrainfo2.readerId) - feedextrainfo2:feedextrainfo; - -} diff --git a/test/integration/github-issues/65/entity/Post.ts b/test/integration/github-issues/65/entity/Post.ts index abe57e9..af629a0 100644 --- a/test/integration/github-issues/65/entity/Post.ts +++ b/test/integration/github-issues/65/entity/Post.ts @@ -1,24 +1,29 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; import { PostAuthor } from "./PostAuthor"; import { PostReader } from "./PostReader"; - @Entity("Post") export class Post { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToOne(type => PostAuthor, PostAuthor => PostAuthor.Id) + @OneToOne(type => PostAuthor, PostAuthor => PostAuthor.id) postAuthor: PostAuthor; - @OneToMany(type => PostReader, PostReader => PostReader.Id) + @OneToMany(type => PostReader, PostReader => PostReader.id) postReaders: PostReader[]; - } diff --git a/test/integration/github-issues/65/entity/PostAuthor.ts b/test/integration/github-issues/65/entity/PostAuthor.ts index 8ff3809..fd16930 100644 --- a/test/integration/github-issues/65/entity/PostAuthor.ts +++ b/test/integration/github-issues/65/entity/PostAuthor.ts @@ -1,22 +1,29 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostAuthor") export class PostAuthor { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToOne(type => Post, Post => Post.Id) + @OneToOne(type => Post, Post => Post.id) @JoinColumn() - post:Post; + post: Post; @RelationId((postAuthor: PostAuthor) => postAuthor.post) postId: number; diff --git a/test/integration/github-issues/65/entity/PostReader.ts b/test/integration/github-issues/65/entity/PostReader.ts index 1fcc60e..37a0462 100644 --- a/test/integration/github-issues/65/entity/PostReader.ts +++ b/test/integration/github-issues/65/entity/PostReader.ts @@ -1,20 +1,29 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostReader") export class PostReader { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - @ManyToOne(type => Post, Post => Post.Id) + @ManyToOne(type => Post, Post => Post.id) @JoinColumn() - post:Post; + post: Post; @RelationId((postReader: PostReader) => postReader.post) postId: number[]; diff --git a/test/integration/github-issues/71/entity/Post.ts b/test/integration/github-issues/71/entity/Post.ts index c9b85b6..8c96706 100644 --- a/test/integration/github-issues/71/entity/Post.ts +++ b/test/integration/github-issues/71/entity/Post.ts @@ -1,41 +1,47 @@ -import { Index, Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable +} from "typeorm"; import { PostReader } from "./PostReader"; import { PostAuthor } from "./PostAuthor"; import { PostCategory } from "./PostCategory"; import { PostDetails } from "./PostDetails"; - @Entity("Post") export class Post { - @Column("int", { - nullable: false, + // nullable: false, primary: true, - name: "Id" + name: "id" }) - Id: number; + id: number; - @OneToOne(type => PostAuthor, PostAuthor => PostAuthor.Id, - { - // onDelete: "CASCADE", - // onUpdate: "CASCADE" - }) + @OneToOne(type => PostAuthor, PostAuthor => PostAuthor.id, { + // onDelete: "CASCADE", + // onUpdate: "CASCADE" + }) postAuthor: PostAuthor; - @OneToOne(type => PostReader, PostReader => PostReader.Id) + @OneToOne(type => PostReader, PostReader => PostReader.id) postReader: PostReader; - @OneToOne(type => PostCategory, PostCategory => PostCategory.Id, - { - // onDelete: "RESTRICT", - // onUpdate: "RESTRICT" - }) + @OneToOne(type => PostCategory, PostCategory => PostCategory.id, { + // onDelete: "RESTRICT", + // onUpdate: "RESTRICT" + }) postCategory: PostCategory; - @OneToOne(type => PostDetails, PostDetails => PostDetails.Id, - { - // onDelete: "SET NULL", - // onUpdate: "SET NULL" - }) + @OneToOne(type => PostDetails, PostDetails => PostDetails.id, { + // onDelete: "SET NULL", + // onUpdate: "SET NULL" + }) postDetails: PostDetails; } diff --git a/test/integration/github-issues/71/entity/PostAuthor.ts b/test/integration/github-issues/71/entity/PostAuthor.ts index 70fcfc7..b09cd20 100644 --- a/test/integration/github-issues/71/entity/PostAuthor.ts +++ b/test/integration/github-issues/71/entity/PostAuthor.ts @@ -1,24 +1,30 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostAuthor") export class PostAuthor { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToOne(type => Post, Post => Post.Id,{ - onDelete: "CASCADE", + @OneToOne(type => Post, Post => Post.id, { + // onDelete: "CASCADE" // onUpdate: "CASCADE" }) @JoinColumn() - post:Post; - + post: Post; } diff --git a/test/integration/github-issues/71/entity/PostCategory.ts b/test/integration/github-issues/71/entity/PostCategory.ts index 688d343..5aef2f3 100644 --- a/test/integration/github-issues/71/entity/PostCategory.ts +++ b/test/integration/github-issues/71/entity/PostCategory.ts @@ -1,25 +1,30 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostCategory") export class PostCategory { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - - - @OneToOne(type => Post, Post => Post.Id, - { - // onDelete: "RESTRICT", - // onUpdate: "RESTRICT" - }) + @OneToOne(type => Post, Post => Post.id, { + // onDelete: "RESTRICT", + // onUpdate: "RESTRICT" + }) @JoinColumn() - post:Post; - + post: Post; } diff --git a/test/integration/github-issues/71/entity/PostDetails.ts b/test/integration/github-issues/71/entity/PostDetails.ts index 7935433..fb4f959 100644 --- a/test/integration/github-issues/71/entity/PostDetails.ts +++ b/test/integration/github-issues/71/entity/PostDetails.ts @@ -1,23 +1,30 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostDetails") export class PostDetails { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - @OneToOne(type => Post, Post => Post.Id, - { - onDelete: "SET NULL", - // onUpdate: "SET NULL" - }) + @OneToOne(type => Post, Post => Post.id, { + // onDelete: "SET NULL" + // onUpdate: "SET NULL" + }) @JoinColumn() - post:Post; - + post: Post; } diff --git a/test/integration/github-issues/71/entity/PostReader.ts b/test/integration/github-issues/71/entity/PostReader.ts index 9e91689..86b1566 100644 --- a/test/integration/github-issues/71/entity/PostReader.ts +++ b/test/integration/github-issues/71/entity/PostReader.ts @@ -1,19 +1,27 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable, RelationId} from "typeorm"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + ManyToMany, + JoinColumn, + JoinTable, + RelationId +} from "typeorm"; import { Post } from "./Post"; - @Entity("PostReader") export class PostReader { + @Column("int", { + primary: true, + name: "id" + }) + id: number; - @Column("int",{ - nullable:false, - primary:true, - name:"Id" - }) - Id:number; - - @OneToOne(type => Post, Post => Post.Id) + @OneToOne(type => Post, Post => Post.id) @JoinColumn() - post:Post; - + post: Post; } diff --git a/test/integration/runTestsFromPath.test.ts b/test/integration/runTestsFromPath.test.ts index 47674a5..9b52340 100644 --- a/test/integration/runTestsFromPath.test.ts +++ b/test/integration/runTestsFromPath.test.ts @@ -1,48 +1,39 @@ import "reflect-metadata"; -import { expect } from "chai"; +import * as chai from "chai"; import * as ts from "typescript"; +import * as fs from "fs-extra"; +import * as path from "path"; +import * as chaiSubset from "chai-subset"; +import * as flatMap from "array.prototype.flatmap"; +import yn from "yn"; +import { CLIEngine } from "eslint"; import EntityFileToJson from "../utils/EntityFileToJson"; -import { - createDriver, - dataCollectionPhase, - modelCustomizationPhase, - modelGenerationPhase -} from "../../src/Engine"; +import { createDriver, dataCollectionPhase } from "../../src/Engine"; import * as GTU from "../utils/GeneralTestUtils"; -import EntityInfo from "../../src/models/EntityInfo"; +import { Entity } from "../../src/models/Entity"; import IConnectionOptions from "../../src/IConnectionOptions"; - -import fs = require("fs-extra"); -import path = require("path"); -import chaiSubset = require("chai-subset"); -import chai = require("chai"); -import yn = require("yn"); +import modelCustomizationPhase from "../../src/ModelCustomization"; +import modelGenerationPhase from "../../src/ModelGeneration"; require("dotenv").config(); +flatMap.shim(); chai.use(chaiSubset); +const { expect } = chai; -it("Column default values", async function() { +it("Column default values", async () => { const testPartialPath = "test/integration/defaultValues"; - this.timeout(60000); - this.slow(10000); // compiling created models takes time await runTestsFromPath(testPartialPath, true); }); -it("Platform specyfic types", async function() { - this.timeout(60000); - this.slow(10000); // compiling created models takes time +it("Platform specific types", async () => { const testPartialPath = "test/integration/entityTypes"; await runTestsFromPath(testPartialPath, true); }); -describe("GitHub issues", async function() { - this.timeout(60000); - this.slow(10000); // compiling created models takes time +describe("GitHub issues", async () => { const testPartialPath = "test/integration/github-issues"; await runTestsFromPath(testPartialPath, false); }); -describe("TypeOrm examples", async function() { - this.timeout(60000); - this.slow(10000); // compiling created models takes time +describe("TypeOrm examples", async () => { const testPartialPath = "test/integration/examples"; await runTestsFromPath(testPartialPath, false); }); @@ -77,8 +68,8 @@ function runTestForMultipleDrivers( dbDrivers: string[], testPartialPath: string ) { - it(testName, async function() { - const driversToRun = selectDriversForSpecyficTest(); + it(testName, async () => { + const driversToRun = selectDriversForSpecificTest(); const modelGenerationPromises = driversToRun.map(async dbDriver => { const { generationOptions, @@ -87,25 +78,26 @@ function runTestForMultipleDrivers( resultsPath, filesOrgPathTS } = await prepareTestRuns(testPartialPath, testName, dbDriver); - let dbModel: EntityInfo[] = []; + let dbModel: Entity[] = []; switch (testName) { case "144": dbModel = await dataCollectionPhase( driver, Object.assign(connectionOptions, { databaseName: "db1,db2" - }) + }), + generationOptions ); break; default: dbModel = await dataCollectionPhase( driver, - connectionOptions + connectionOptions, + generationOptions ); break; } - dbModel = modelCustomizationPhase( dbModel, generationOptions, @@ -127,7 +119,7 @@ function runTestForMultipleDrivers( compileGeneratedModel(path.resolve(process.cwd(), `output`), dbDrivers); }); - function selectDriversForSpecyficTest() { + function selectDriversForSpecificTest() { switch (testName) { case "39": return dbDrivers.filter( @@ -161,7 +153,11 @@ async function runTest( resultsPath, filesOrgPathTS } = await prepareTestRuns(testPartialPath, dbDriver, dbDriver); - let dbModel = await dataCollectionPhase(driver, connectionOptions); + let dbModel = await dataCollectionPhase( + driver, + connectionOptions, + generationOptions + ); dbModel = modelCustomizationPhase( dbModel, generationOptions, @@ -190,23 +186,74 @@ function compareGeneratedFiles(filesOrgPathTS: string, filesGenPath: string) { const filesGen = fs .readdirSync(filesGenPath) .filter(val => val.toString().endsWith(".ts")); - expect(filesOrg, "Errors detected in model comparision").to.be.deep.equal( + expect(filesOrg, "Errors detected in model comparison").to.be.deep.equal( filesGen ); - filesOrg.forEach(file => { - const jsonEntityOrg = EntityFileToJson.convert( - fs.readFileSync(path.resolve(filesOrgPathTS, file)) - ); - const jsonEntityGen = EntityFileToJson.convert( + const generatedEntities = filesOrg.map(file => + EntityFileToJson.convert( fs.readFileSync(path.resolve(filesGenPath, file)) - ); - expect(jsonEntityGen, `Error in file ${file}`).to.containSubset( - jsonEntityOrg - ); - }); + ) + ); + const originalEntities = filesGen.map(file => + EntityFileToJson.convert( + fs.readFileSync(path.resolve(filesOrgPathTS, file)) + ) + ); + generatedEntities + .flatMap(entity => + entity.columns + .filter( + column => + column.relationType === "ManyToMany" && + column.joinOptions.length > 0 + ) + .map(v => { + return { + ownerColumn: v, + ownerEntity: entity + }; + }) + ) + + .forEach(({ ownerColumn, ownerEntity }) => { + const childColumn = generatedEntities + .find( + childEntity => + childEntity.entityName.toLowerCase() === + ownerColumn.columnTypes[0] + .substring(0, ownerColumn.columnTypes[0].length - 2) + .toLowerCase() + )! + .columns.find( + column => + column.columnTypes[0].toLowerCase() === + `${ownerEntity.entityName}[]`.toLowerCase() + )!; + childColumn.joinOptions = ownerColumn.joinOptions.map(options => { + return { + ...options, + joinColumns: options.inverseJoinColumns, + inverseJoinColumns: options.joinColumns + }; + }); + }); + // TODO: set relation options on ManyToMany to both side of relation + generatedEntities + .map((ent, i) => [ent, originalEntities[i], filesOrg[i]]) + .forEach(([generated, original, file]) => { + expect(generated, `Error in file ${file}`).to.containSubset( + original + ); + }); } -function compileGeneratedModel(filesGenPath: string, drivers: string[]) { +// TODO: Move(?) +// eslint-disable-next-line import/prefer-default-export +export function compileGeneratedModel( + filesGenPath: string, + drivers: string[], + lintGeneratedFiles = true +) { const currentDirectoryFiles: string[] = []; drivers.forEach(driver => { const entitiesPath = path.resolve(filesGenPath, driver, "entities"); @@ -223,7 +270,7 @@ function compileGeneratedModel(filesGenPath: string, drivers: string[]) { ); } }); - const compileErrors = GTU.compileTsFiles(currentDirectoryFiles, { + const compiledWithoutErrors = GTU.compileTsFiles(currentDirectoryFiles, { experimentalDecorators: true, sourceMap: false, emitDecoratorMetadata: true, @@ -231,8 +278,24 @@ function compileGeneratedModel(filesGenPath: string, drivers: string[]) { moduleResolution: ts.ModuleResolutionKind.NodeJs, module: ts.ModuleKind.CommonJS }); - expect(compileErrors, "Errors detected while compiling generated model").to - .be.false; + expect( + compiledWithoutErrors, + "Errors detected while compiling generated model" + ).to.equal(true); + + if (lintGeneratedFiles) { + const cli = new CLIEngine({ configFile: "test/configs/.eslintrc.js" }); + const lintReport = cli.executeOnFiles(currentDirectoryFiles); + lintReport.results.forEach(result => + result.messages.forEach(message => { + console.error( + `${result.filePath}:${message.line} - ${message.message}` + ); + }) + ); + expect(lintReport.errorCount).to.equal(0); + expect(lintReport.warningCount).to.equal(0); + } } async function prepareTestRuns( @@ -276,7 +339,8 @@ async function prepareTestRuns( password: String(process.env.MYSQL_Password), databaseType: "mysql", schemaName: "ignored", - ssl: yn(process.env.MYSQL_SSL) + ssl: yn(process.env.MYSQL_SSL, { default: false }), + skipTables: [] }; break; case "mariadb": @@ -288,7 +352,8 @@ async function prepareTestRuns( password: String(process.env.MARIADB_Password), databaseType: "mariadb", schemaName: "ignored", - ssl: yn(process.env.MARIADB_SSL) + ssl: yn(process.env.MARIADB_SSL, { default: false }), + skipTables: [] }; break; diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..05132a0 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,3 @@ +--timeout 60000 +--slow 20000 +-R spec \ No newline at end of file diff --git a/test/modelCustomization/modelCustomization.test.ts b/test/modelCustomization/modelCustomization.test.ts new file mode 100644 index 0000000..8082c48 --- /dev/null +++ b/test/modelCustomization/modelCustomization.test.ts @@ -0,0 +1,741 @@ +import * as path from "path"; +import * as fs from "fs-extra"; +import * as chai from "chai"; +import * as chaiSubset from "chai-subset"; +import { Entity } from "../../src/models/Entity"; +import modelCustomizationPhase from "../../src/ModelCustomization"; +import { getDefaultGenerationOptions } from "../../src/IGenerationOptions"; +import modelGenerationPhase from "../../src/ModelGeneration"; +import { getDefaultConnectionOptions } from "../../src/IConnectionOptions"; +import { compileGeneratedModel } from "../integration/runTestsFromPath.test"; + +chai.use(chaiSubset); +const { expect } = chai; + +// TODO: test for connectionOptions.specyficTables +describe("Model customization phase", async () => { + const generateSampleData: () => Entity[] = () => [ + { + columns: [ + { + generated: true, + type: "integer", + options: { name: "id" }, + tscName: "id", + tscType: "number", + primary: true + }, + { + type: "character varying", + options: { name: "name" }, + tscName: "name", + tscType: "string" + } + ], + indices: [ + { + columns: ["id"], + options: { unique: true }, + name: "PK_6571d08cfb2f1ab06c3aab425a6", + primary: true + } + ], + relations: [ + { + fieldName: "Post", + relatedField: "authorId", + relatedTable: "Post", + relationType: "OneToMany" + } + ], + relationIds: [], + sqlName: "PostAuthor", + tscName: "PostAuthor", + database: "", + schema: "public", + fileImports: [] + }, + { + columns: [ + { + generated: true, + type: "integer", + options: { name: "id" }, + tscName: "id", + tscType: "number", + primary: true + }, + { + type: "character varying", + options: { name: "title" }, + tscName: "title", + tscType: "string" + }, + { + type: "character varying", + options: { name: "text" }, + tscName: "text", + tscType: "string" + } + ], + indices: [ + { + columns: ["authorId"], + options: { unique: true }, + name: "REL_cef8d6e8edb69c82e5f10bb402" + }, + { + columns: ["id"], + options: { unique: true }, + name: "PK_c4d3b3dcd73db0b0129ea829f9f", + primary: true + } + ], + relations: [ + { + fieldName: "authorId", + relatedField: "Post", + joinColumnOptions: [ + { name: "authorId", referencedColumnName: "id" } + ], + relatedTable: "PostAuthor", + relationType: "ManyToOne" + } + ], + relationIds: [], + sqlName: "Post", + tscName: "Post", + database: "", + schema: "public", + fileImports: [] + } + ]; + + const resultsPath = path.resolve(process.cwd(), `output`); + const generateGenerationOptions = () => { + const generationOptions = getDefaultGenerationOptions(); + generationOptions.resultsPath = resultsPath; + return generationOptions; + }; + const clearGenerationDir = () => { + fs.ensureDirSync(resultsPath); + fs.emptyDirSync(resultsPath); + }; + describe("case-file", () => { + it("PascalCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseFile = "pascal"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const files = fs.readdirSync(filesGenPath).sort(); + expect(files[0]).to.equal("Post.ts"); + expect(files[1]).to.equal("PostAuthor.ts"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("camelCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseFile = "camel"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const files = fs.readdirSync(filesGenPath).sort(); + expect(files[0]).to.equal("post.ts"); + expect(files[1]).to.equal("postAuthor.ts"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); + describe("case-entity", () => { + it("PascalCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseEntity = "pascal"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.contain("class Post {"); + expect(postAuthorContent).to.contain("class PostAuthor {"); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("camelCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseEntity = "camel"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.contain("class post {"); + expect(postAuthorContent).to.contain("class postAuthor {"); + + compileGeneratedModel(generationOptions.resultsPath, [""], false); + }); + }); + describe("case-property", async () => { + it("PascalCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseProperty = "pascal"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.contain("Title: string;"); + expect(postAuthorContent).to.contain("Posts: Post[];"); + + compileGeneratedModel(generationOptions.resultsPath, [""], false); + }); + it("camelCase", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.convertCaseProperty = "camel"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.contain("title: string;"); + expect(postAuthorContent).to.contain("posts: Post[];"); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); + describe("property-visibility", () => { + it("public", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.propertyVisibility = "public"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(" public title: string"); + expect(postAuthorContent).to.have.string(" public posts: Post[];"); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("none", () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.propertyVisibility = "none"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(" title: string"); + expect(postAuthorContent).to.have.string(" posts: Post[];"); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); + it("lazy", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.lazy = true; + generationOptions.pluralizeNames = false; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string("lazy: true"); + expect(postContent).to.have.string("Promise;"); + expect(postAuthorContent).to.have.string("lazy: true"); + expect(postAuthorContent).to.have.string("Promise"); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("activeRecord", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.activeRecord = true; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string( + `export class Post extends BaseEntity ` + ); + expect(postAuthorContent).to.have.string( + `export class PostAuthor extends BaseEntity ` + ); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("skipSchema", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.skipSchema = true; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(`@Entity("Post")`); + expect(postAuthorContent).to.have.string(`@Entity("PostAuthor")`); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("generateConstructor", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.generateConstructor = true; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(`constructor(init?: Partial)`); + expect(postContent).to.have.string(`Object.assign(this, init);`); + expect(postAuthorContent).to.have.string( + `constructor(init?: Partial)` + ); + expect(postAuthorContent).to.have.string(`Object.assign(this, init);`); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("generateConstructor with activeRecord", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.generateConstructor = true; + generationOptions.activeRecord = true; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(`constructor(init?: Partial)`); + expect(postContent).to.have.string(`super();`); + expect(postContent).to.have.string(`Object.assign(this, init);`); + expect(postAuthorContent).to.have.string( + `constructor(init?: Partial)` + ); + expect(postAuthorContent).to.have.string(`super();`); + expect(postAuthorContent).to.have.string(`Object.assign(this, init);`); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + describe("strictMode", () => { + it("!", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.strictMode = "!"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(`id!: number;`); + expect(postContent).to.have.string(`title!: string;`); + expect(postContent).to.have.string(`text!: string;`); + expect(postContent).to.have.string(`author!: PostAuthor;`); + expect(postAuthorContent).to.have.string(`id!: number;`); + expect(postAuthorContent).to.have.string(`name!: string;`); + expect(postAuthorContent).to.have.string(`posts!: Post[];`); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("?", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + + generationOptions.strictMode = "?"; + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postContent).to.have.string(`id?: number;`); + expect(postContent).to.have.string(`title?: string;`); + expect(postContent).to.have.string(`text?: string;`); + expect(postContent).to.have.string(`author?: PostAuthor;`); + expect(postAuthorContent).to.have.string(`id?: number;`); + expect(postAuthorContent).to.have.string(`name?: string;`); + expect(postAuthorContent).to.have.string(`posts?: Post[];`); + + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); + it("naming strategy", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + clearGenerationDir(); + generationOptions.convertCaseEntity = "none"; + generationOptions.convertCaseFile = "none"; + generationOptions.convertCaseProperty = "none"; + generationOptions.customNamingStrategyPath = + "test/modelCustomization/testNamingStrategy.ts"; + // TODO: relationId + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postContent = fs + .readFileSync(path.resolve(filesGenPath, "Post_B.ts")) + .toString(); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor_B.ts")) + .toString(); + expect(postContent).to.have.string(`@Entity("Post"`); + expect(postContent).to.have.string(`class Post_B {`); + expect(postContent).to.have.string(`id_C: number;`); + expect(postContent).to.have.string(`author_A: PostAuthor_B`); + expect(postContent).to.have.string( + `import { PostAuthor_B } from "./PostAuthor_B";` + ); + expect(postAuthorContent).to.have.string(`@Entity("PostAuthor"`); + expect(postAuthorContent).to.have.string(`class PostAuthor_B`); + expect(postAuthorContent).to.have.string(`id_C: number;`); + expect(postAuthorContent).to.have.string( + `import { Post_B } from "./Post_B";` + ); + + compileGeneratedModel(generationOptions.resultsPath, [""], false); + }); + describe("pluralization", () => { + it("enabled", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + generationOptions.pluralizeNames = true; + clearGenerationDir(); + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postAuthorContent).to.contain("posts: Post[];"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("disabled", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + generationOptions.pluralizeNames = false; + clearGenerationDir(); + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const postAuthorContent = fs + .readFileSync(path.resolve(filesGenPath, "PostAuthor.ts")) + .toString(); + expect(postAuthorContent).to.contain("post: Post[];"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); + describe("index file generation", () => { + it("named export", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + generationOptions.indexFile = true; + clearGenerationDir(); + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const indexFileContent = fs + .readFileSync(path.resolve(filesGenPath, "Index.ts")) + .toString(); + expect(indexFileContent).to.contain( + 'import { PostAuthor } from "./PostAuthor' + ); + expect(indexFileContent).to.contain('import { Post } from "./Post'); + expect(indexFileContent).to.contain("export { PostAuthor, Post }"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("default export", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + generationOptions.indexFile = true; + generationOptions.exportType = "default"; + clearGenerationDir(); + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + const indexFileContent = fs + .readFileSync(path.resolve(filesGenPath, "Index.ts")) + .toString(); + expect(indexFileContent).to.contain( + 'import PostAuthor from "./PostAuthor' + ); + expect(indexFileContent).to.contain('import Post from "./Post'); + expect(indexFileContent).to.contain("export { PostAuthor, Post }"); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + it("disabled", async () => { + const data = generateSampleData(); + const generationOptions = generateGenerationOptions(); + generationOptions.pluralizeNames = false; + clearGenerationDir(); + + const customizedModel = modelCustomizationPhase( + data, + generationOptions, + {} + ); + modelGenerationPhase( + getDefaultConnectionOptions(), + generationOptions, + customizedModel + ); + const filesGenPath = path.resolve(resultsPath, "entities"); + expect( + fs.existsSync(path.resolve(filesGenPath, "Index.ts")) + ).to.equal(false); + compileGeneratedModel(generationOptions.resultsPath, [""]); + }); + }); +}); diff --git a/test/modelCustomization/testNamingStrategy.ts b/test/modelCustomization/testNamingStrategy.ts new file mode 100644 index 0000000..b3ed507 --- /dev/null +++ b/test/modelCustomization/testNamingStrategy.ts @@ -0,0 +1,22 @@ +import * as NamingStrategy from "../../src/NamingStrategy"; +import { RelationId } from "../../src/models/RelationId"; +import { Relation } from "../../src/models/Relation"; + +export function relationIdName( + relationId: RelationId, + relation: Relation +): string { + return `${NamingStrategy.relationIdName(relationId, relation)}`; +} + +export function relationName(relation: Relation): string { + return `${NamingStrategy.relationName(relation)}_A`; +} + +export function entityName(oldEntityName: string): string { + return `${NamingStrategy.entityName(oldEntityName)}_B`; +} + +export function columnName(oldColumnName: string): string { + return `${NamingStrategy.columnName(oldColumnName)}_C`; +} diff --git a/test/utils/EntityFileToJson.ts b/test/utils/EntityFileToJson.ts index 981c10c..443aef1 100644 --- a/test/utils/EntityFileToJson.ts +++ b/test/utils/EntityFileToJson.ts @@ -2,38 +2,35 @@ class EntityJson { public entityName: string; - public entityOptions: any = {}; + public entityOptions: { [key: string]: string | boolean } = {}; public columns: EntityColumn[] = [] as EntityColumn[]; - public indicies: EntityIndex[] = [] as EntityIndex[]; + public indices: EntityIndex[] = [] as EntityIndex[]; } class EntityColumn { public columnName: string; public columnTypes: string[] = []; - public columnOptions: any = {}; + public columnOptions: { [key: string]: string | boolean } = {}; - public relationType: - | "OneToOne" - | "OneToMany" - | "ManyToOne" - | "ManyToMany" - | "None" = "None"; + public joinOptions: { [key: string]: string | boolean }[] = []; - public isOwnerOfRelation: boolean = false; + public relationType: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"; + + public isOwnerOfRelation = false; } class EntityIndex { public indexName: string; public columnNames: string[] = []; - public isUnique: boolean = false; + public isUnique = false; } export default class EntityFileToJson { - public static getEntityOptions(trimmedLine: string, ent: EntityJson) { + public static getEntityOptions(trimmedLine: string, ent: EntityJson): void { const decoratorParameters = trimmedLine.slice( trimmedLine.indexOf("(") + 1, trimmedLine.lastIndexOf(")") @@ -62,7 +59,7 @@ export default class EntityFileToJson { public static getColumnOptionsAndType( trimmedLine: string, col: EntityColumn - ) { + ): void { const decoratorParameters = trimmedLine.slice( trimmedLine.indexOf("(") + 1, trimmedLine.lastIndexOf(")") @@ -122,7 +119,10 @@ export default class EntityFileToJson { } } - public static getRelationOptions(trimmedLine: string, col: EntityColumn) { + public static getRelationOptions( + trimmedLine: string, + col: EntityColumn + ): void { const decoratorParameters = trimmedLine.slice( trimmedLine.indexOf("(") + 1, trimmedLine.lastIndexOf(")") @@ -151,7 +151,7 @@ export default class EntityFileToJson { } } - public static getIndexOptions(trimmedLine: string, ind: EntityIndex) { + public static getIndexOptions(trimmedLine: string, ind: EntityIndex): void { const decoratorParameters = trimmedLine.slice( trimmedLine.indexOf("(") + 1, trimmedLine.lastIndexOf(")") @@ -166,7 +166,7 @@ export default class EntityFileToJson { decoratorParameters.indexOf('"') + 1, decoratorParameters .substr(decoratorParameters.indexOf('"') + 1) - .indexOf('"') + .indexOf('"') + 1 ); } if (containsTables) { @@ -241,6 +241,14 @@ export default class EntityFileToJson { } if (!isInClassBody) { if (trimmedLine.startsWith("import")) { + if ( + EntityFileToJson.isPartOfMultilineStatement(trimmedLine) + ) { + isMultilineStatement = true; + priorPartOfMultilineStatement = trimmedLine; + } else { + isMultilineStatement = false; + } return; } if (trimmedLine.startsWith("@Entity")) { @@ -275,7 +283,7 @@ export default class EntityFileToJson { isMultilineStatement = false; const ind = new EntityIndex(); EntityFileToJson.getIndexOptions(trimmedLine, ind); - retVal.indicies.push(ind); + retVal.indices.push(ind); } return; } @@ -341,6 +349,7 @@ export default class EntityFileToJson { retVal.columns.push(column); column.relationType = "ManyToOne"; column.isOwnerOfRelation = true; + EntityFileToJson.getRelationOptions(trimmedLine, column); } return; } @@ -353,6 +362,7 @@ export default class EntityFileToJson { const column = new EntityColumn(); retVal.columns.push(column); column.relationType = "OneToMany"; + EntityFileToJson.getRelationOptions(trimmedLine, column); } return; } @@ -365,6 +375,7 @@ export default class EntityFileToJson { const column = new EntityColumn(); retVal.columns.push(column); column.relationType = "ManyToMany"; + EntityFileToJson.getRelationOptions(trimmedLine, column); } return; } @@ -390,6 +401,23 @@ export default class EntityFileToJson { retVal.columns[ retVal.columns.length - 1 ].isOwnerOfRelation = true; + const decoratorParameters = trimmedLine + .substring( + trimmedLine.indexOf("(") + 1, + trimmedLine.indexOf(")") + ) + .trim() + .replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '); + if (decoratorParameters.length > 0) { + const column = + retVal.columns[retVal.columns.length - 1]; + const options = JSON.parse(decoratorParameters); + if (Array.isArray(options)) { + column.joinOptions = options as any; + } else { + column.joinOptions = [options] as any; + } + } } return; } @@ -399,9 +427,35 @@ export default class EntityFileToJson { priorPartOfMultilineStatement = trimmedLine; } else { isMultilineStatement = false; - retVal.columns[ - retVal.columns.length - 1 - ].isOwnerOfRelation = true; + const decoratorParameters = trimmedLine + .substring( + trimmedLine.indexOf("(") + 1, + trimmedLine.indexOf(")") + ) + .trim() + .replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '); + if (decoratorParameters.length > 0) { + const column = + retVal.columns[retVal.columns.length - 1]; + const options = JSON.parse(decoratorParameters); + if ( + options.inverseJoinColumn && + !Array.isArray(options.inverseJoinColumn) + ) { + options.inverseJoinColumns = [ + options.inverseJoinColumn + ]; + delete options.inverseJoinColumn; + } + if ( + options.joinColumn && + !Array.isArray(options.joinColumn) + ) { + options.joinColumns = [options.joinColumn]; + delete options.joinColumn; + } + column.joinOptions = [options]; + } } return; } @@ -413,7 +467,7 @@ export default class EntityFileToJson { isMultilineStatement = false; const ind = new EntityIndex(); EntityFileToJson.getIndexOptions(trimmedLine, ind); - retVal.indicies.push(ind); + retVal.indices.push(ind); } return; } @@ -439,7 +493,7 @@ export default class EntityFileToJson { colTypes = colTypes.substring(8, colTypes.length - 1); retVal.columns[ retVal.columns.length - 1 - ].columnOptions.isLazy = true; + ].columnOptions.isTypeLazy = true; } retVal.columns[ retVal.columns.length - 1 @@ -461,13 +515,11 @@ export default class EntityFileToJson { ); } if ( - retVal.indicies.length > 0 && - retVal.indicies[retVal.indicies.length - 1].columnNames + retVal.indices.length > 0 && + retVal.indices[retVal.indices.length - 1].columnNames .length === 0 ) { - retVal.indicies[ - retVal.indicies.length - 1 - ].columnNames.push( + retVal.indices[retVal.indices.length - 1].columnNames.push( retVal.columns[retVal.columns.length - 1].columnName ); } @@ -483,16 +535,7 @@ export default class EntityFileToJson { console.log(`${trimmedLine}`); }); - retVal.columns = retVal.columns.map(col => { - if (col.columnName.endsWith("Id")) { - col.columnName = col.columnName.substr( - 0, - col.columnName.length - 2 - ); - } - return col; - }); - retVal.indicies = retVal.indicies.map(ind => { + retVal.indices = retVal.indices.map(ind => { ind.columnNames = ind.columnNames.map(colName => { if (colName.endsWith("Id")) { colName = colName.substr(0, colName.length - 2); @@ -504,7 +547,7 @@ export default class EntityFileToJson { return retVal; } - public static isPartOfMultilineStatement(statement: string) { + public static isPartOfMultilineStatement(statement: string): boolean { const matchStarting = statement.split("(").length + statement.split("{").length; const matchEnding = diff --git a/test/utils/GeneralTestUtils.ts b/test/utils/GeneralTestUtils.ts index 8c4af84..1606c59 100644 --- a/test/utils/GeneralTestUtils.ts +++ b/test/utils/GeneralTestUtils.ts @@ -1,7 +1,9 @@ import { ConnectionOptions, createConnection } from "typeorm"; import * as ts from "typescript"; import * as yn from "yn"; -import IGenerationOptions from "../../src/IGenerationOptions"; +import IGenerationOptions, { + getDefaultGenerationOptions +} from "../../src/IGenerationOptions"; import IConnectionOptions from "../../src/IConnectionOptions"; import MssqlDriver from "../../src/drivers/MssqlDriver"; import MariaDbDriver from "../../src/drivers/MariaDbDriver"; @@ -12,21 +14,9 @@ import MysqlDriver from "../../src/drivers/MysqlDriver"; import path = require("path"); export function getGenerationOptions(resultsPath: string): IGenerationOptions { - return { - resultsPath, - noConfigs: false, - convertCaseEntity: "none", - convertCaseFile: "none", - convertCaseProperty: "none", - propertyVisibility: "none", - lazy: false, - generateConstructor: false, - customNamingStrategyPath: "", - relationIds: false, - skipSchema: false, - activeRecord: false, - strictMode: false - }; + const retVal = getDefaultGenerationOptions(); + retVal.resultsPath = resultsPath; + return retVal; } export async function createMSSQLModels( @@ -41,7 +31,8 @@ export async function createMSSQLModels( password: String(process.env.MSSQL_Password), databaseType: "mssql", schemaName: "dbo,sch1,sch2", - ssl: yn(process.env.MSSQL_SSL) + ssl: yn(process.env.MSSQL_SSL, { default: false }), + skipTables: [] }; await driver.ConnectToServer(connectionOptions); connectionOptions.databaseName = String(process.env.MSSQL_Database); @@ -92,7 +83,8 @@ export async function createPostgresModels( password: String(process.env.POSTGRES_Password), databaseType: "postgres", schemaName: "public,sch1,sch2", - ssl: yn(process.env.POSTGRES_SSL) + ssl: yn(process.env.POSTGRES_SSL, { default: false }), + skipTables: ["spatial_ref_sys"] }; await driver.ConnectToServer(connectionOptions); connectionOptions.databaseName = String(process.env.POSTGRES_Database); @@ -142,7 +134,8 @@ export async function createSQLiteModels( password: "", databaseType: "sqlite", schemaName: "", - ssl: false + ssl: false, + skipTables: [] }; const connOpt: ConnectionOptions = { @@ -176,7 +169,8 @@ export async function createMysqlModels( password: String(process.env.MYSQL_Password), databaseType: "mysql", schemaName: "ignored", - ssl: yn(process.env.MYSQL_SSL) + ssl: yn(process.env.MYSQL_SSL, { default: false }), + skipTables: [] }; await driver.ConnectToServer(connectionOptions); @@ -218,7 +212,8 @@ export async function createMariaDBModels( password: String(process.env.MARIADB_Password), databaseType: "mariadb", schemaName: "ignored", - ssl: yn(process.env.MARIADB_SSL) + ssl: yn(process.env.MARIADB_SSL, { default: false }), + skipTables: [] }; await driver.ConnectToServer(connectionOptions); @@ -262,7 +257,8 @@ export async function createOracleDBModels( password: String(process.env.ORACLE_PasswordSys), databaseType: "oracle", schemaName: String(process.env.ORACLE_Username), - ssl: yn(process.env.ORACLE_SSL) + ssl: yn(process.env.ORACLE_SSL, { default: false }), + skipTables: [] }; await driver.ConnectToServer(connectionOptions); connectionOptions.user = String(process.env.ORACLE_Username); @@ -301,7 +297,7 @@ export function compileTsFiles( ): boolean { const program = ts.createProgram(fileNames, options); const emitResult = program.emit(); - let compileErrors = false; + let compiledWithoutErrors = true; const preDiagnostics = ts.getPreEmitDiagnostics(program); const allDiagnostics = [...preDiagnostics, ...emitResult.diagnostics]; @@ -318,13 +314,13 @@ export function compileTsFiles( `${diagnostic.file!.fileName} (${lineAndCharacter.line + 1},${lineAndCharacter.character + 1}): ${message}` ); - compileErrors = true; + compiledWithoutErrors = false; }); - return compileErrors; + return compiledWithoutErrors; } -export function getEnabledDbDrivers() { +export function getEnabledDbDrivers(): string[] { const dbDrivers: string[] = []; if (process.env.SQLITE_Skip === "0") { dbDrivers.push("sqlite"); diff --git a/tsconfig.json b/tsconfig.json index bcc555a..85e2d71 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,31 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "noImplicitAny": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "sourceMap": true, - "declaration": false, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "stripInternal": true, - "strictNullChecks": true, - "moduleResolution": "node", - "newLine": "LF", - "outDir": "dist", - "lib": [ - "es2017" - ], - "resolveJsonModule": true, - }, - "include": [ - "src", - "test" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "noImplicitAny": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true, + "declaration": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "stripInternal": true, + "strictNullChecks": true, + "moduleResolution": "node", + "newLine": "LF", + "outDir": "dist", + "lib": [ + "es2019", + "es2019.array" + ], + "typeRoots": [ + "./node_modules/@types" + ], + "resolveJsonModule": true, + }, + "include": [ + "src", + "test", + ], + "exclude": ["**/node_modules", "node_modules"] }